简体   繁体   中英

Copy database from one app to another app

I'm trying to copy a database from an Android app to another app . In other words, I want to copy a file located in the following path /data/data/com.other.package/databases/filename.db to /data/data/com.my.app/databases/new_file.db .

So far, I'm using root commands to do the process and then try to fix permissions , but I can't read the copied file. This is the logcat error I'm getting:

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)

This is the code I've come up with:

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

Last but not least, a little bit of context to help you find an answer:

  • I'm running this code on a real rooted device
  • The database is a valid SQLite file, tested with SQLite Editor for Android
  • The file is being copied correctly to the output path (checksum matches)
  • Permissions, owner and group are being changed to the correct ones, tested using terminal emulator with command ls [path] -l
  • It is NOT possible to change the source code of the app from which I want to copy the database

I found a pretty simple trick to avoid having to rewrite owner, group and permissions by creating an empty database with the same name and then overwriting it . This is how the final code looks like:

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

You were very close with your original code but your problem was the SELinux error in avc: denied { open }

When you copy the DB file in, you need to change the SELinux context with something like chcon u:object_r:app_data_file:s0:c512,c768 database.db as an SSH command in terminal.

In the the context of your code, it'd be something like

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM