将数据库从一个应用程序复制到另一个

时间:2016-07-25 13:20:05

标签: java android database sqlite root

我正在尝试将数据库从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文件,使用适用于Android的SQLite编辑器进行测试
  • 正在将文件正确复制到输出路径(校验和匹配)
  • 权限,所有者和组正在更改为正确的权限,使用带有命令ls [path] -l的终端模拟器进行测试
  • 无法更改我要从中复制数据库的应用的源代码

2 个答案:

答案 0 :(得分:1)

我发现了一个非常简单的技巧,可以避免通过创建一个具有相同名称的空数据库然后覆盖它来重写所有者,组和权限。这是最终代码的样子:

// 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());
}

答案 1 :(得分:0)

您与原始代码非常接近,但是问题是avc: denied { open }中的SELinux错误

在其中复制数据库文件时,您需要使用chcon u:object_r:app_data_file:s0:c512,c768 database.db之类的东西来更改SELinux上下文,作为终端中的SSH命令。<​​/ p>

在您的代码上下文中,类似于

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