簡體   English   中英

將數據庫從一個應用程序復制到另一個應用程序

[英]Copy database from one app to another app

我正在嘗試將數據庫從 Android 應用程序復制到另一個應用程序 換句話說,我想將位於以下路徑/data/data/com.other.package/databases/filename.db的文件復制到/data/data/com.my.app/databases/new_file.db

到目前為止,我正在使用root 命令來執行該過程,然后嘗試修復權限,但我無法讀取復制的文件。 這是我收到的 logcat 錯誤:

type=1400 audit(0.0:6364): avc: denied { open } for name="database.db" dev="mmcblk0p28" ino=171293 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0
os_unix.c:31278: (13) open(/data/user/0/com.testapp/databases/database.db)

這是我想出的代碼:

// Define in and out filepaths
String DB_INPUT = "/data/data/com.package.name/databases/database.db";
String DB_OUTPUT = activity.getDatabasePath("database.db").getPath();

try {
    // Request superuser permissions
    Process suProcess = Runtime.getRuntime().exec("su");
    DataOutputStream suOutputStream = new DataOutputStream(suProcess.getOutputStream());

    // Copy database
    suOutputStream.writeBytes("cat " + DB_INPUT + " > " + DB_OUTPUT + "\n");

    // Fix permissions
    int appUID = getApplication().getApplicationInfo().uid;
    suOutputStream.writeBytes("chmod 600 " + DB_OUTPUT + "\n"); // rw- --- ---
    suOutputStream.writeBytes("chown " + appUID + "." + appUID  + " " + DB_OUTPUT + "\n");
    suOutputStream.writeBytes("exit\n");
    suProcess.waitFor();
    suOutputStream.close();

    // Test
    SQLiteDatabase.openDatabase(DB_OUTPUT, null, SQLiteDatabase.OPEN_READWRITE);
} catch(Exception e) {
    Log.e(LOGTAG, "Something went terrible wrong: " + e.getMessage());
}

最后但並非最不重要的一點是幫助您找到答案的上下文:

  • 我在真正的 root 設備上運行此代碼
  • 數據庫是一個有效的 SQLite 文件,用 SQLite Editor for Android 測試過
  • 文件被正確復制到輸出路徑(校驗和匹配)
  • 權限、所有者和組正在更改為正確的,使用終端仿真器和命令ls [path] -l
  • 無法更改要從中復制數據庫的應用程序的源代碼

我發現了一個非常簡單的技巧,可以通過創建一個同名的空數據庫然后覆蓋它來避免重寫所有者、組和權限。 這是最終代碼的樣子:

// Define in and out filepaths
String DB_INPUT = "/data/data/com.package.name/databases/database.db";
String DB_OUTPUT = activity.getDatabasePath("database.db").getPath();

// Create empty database to grant permissions
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_OUTPUT, null);
db.close();

try {
    // Request superuser permissions
    Process suProcess = Runtime.getRuntime().exec("su");
    DataOutputStream suOutputStream = new DataOutputStream(suProcess.getOutputStream());

    // Copy database
    suOutputStream.writeBytes("cat " + DB_INPUT + " > " + DB_OUTPUT + "\n");

    // Close terminal
    suOutputStream.writeBytes("exit\n");
    suProcess.waitFor();
    suOutputStream.close();
} catch(Exception e) {
    Log.e(LOGTAG, "Something went terrible wrong: " + e.getMessage());
}

您與原始代碼非常接近,但您的問題是avc: denied { open }的 SELinux 錯誤avc: denied { open }

當您復制 DB 文件時,您需要使用類似chcon u:object_r:app_data_file:s0:c512,c768 database.db類的內容更改 SELinux 上下文作為終端中的 SSH 命令。

在您的代碼上下文中,它類似於

suOutputStream.writeBytes("chcon u:object_r:app_data_file:s0:c512,c768 " + DB_OUTPUT + "\n");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM