I'm writing an app that works perfectly on an Android 4.4 but failed to work on an Android 7. The 2 devices are rooted.
The aim of my app is to take files from the data directory of an other application (let's call it com.game.orig), copy them to my application directory (let's call it com.game.cheat) and there read them, modify them before writing them back to the original directory.
So using "su" (throw the function found there ExecuteAsRootBase.java) i copy files from com.game.orig to com.game.cheat directory like this:
PackageManager m = context.getPackageManager();
String appDir = getPackageDirectory("com.game.orig",m);// /data/user/0/com.game.orig/files/
String localDir = getPackageDirectory(context.getPackageName(),m);// /data/user/0/com.game.cheat/files/
if (ExecuteAsRootBase.canRunRootCommands()) {
ExecuteAsRootBase rootBase = new ExecuteAsRootBase();
Sting fileName="savedgame.dat";
int uid=context.getApplicationInfo().uid;//get the uid (owner) of my app.
//Create localDir (files subdirectory) if not exists
File directory = new File(localDir);
if (!directory.exists()) {
directory.mkdirs();
//adjust file permission (not sure it's realy needed)
rootBase.executecmd("chmod 777 "+ localDir);
rootBase.executecmd("chown " + uid + "." + uid + " " + localDir);
}
//copy file from appDir to localdir using 'su'
rootBase.execute("cp "+ appDir +fileName + " " + localDir)){
//adjust file permission
rootBase.execute("chmod 777 "+ localDir +fileName);
rootBase.execute("chown " + uid + "." + uid + " " + localDir + fileName);
}
Ending here, everything works fine:
i have my files directory with perms: drwxrwxrwx and owned by u0_a115, group u0_a115. (that matches the owner/group of /data/data/com.game.cheat) and my copied files with same owner/group and perms: -rwxrwxrwx
now when trying to open the copied file to read it:
InputStream input = context.openFileInput( fileName );
the openFileInput throw an exception:
java.io.FileNotFoundException: /data/user/0/com.game.cheat/files/savedgame.dat (Permission denied)
And this occcurs only on the phone with Android 7.0 API24.
Anyone have some hints about what is wrong in my approch, di i missed something new with latest API?
thanks.
Until API 23 the permissions in manifest were enough for you to access the external storage of a device along side other kind of permissions. From API 23 some permissions must be granted by the user in runtime, such as the permission to write in external storage.
Here is an example how you could do it:
private boolean checkWriteExternalPermission() {
String permission_read = Manifest.permission.READ_EXTERNAL_STORAGE;
String permission_write = Manifest.permission.WRITE_EXTERNAL_STORAGE;
int res = this.checkCallingOrSelfPermission(permission_read);
int res2 = this.checkCallingOrSelfPermission(permission_write);
return (res == PackageManager.PERMISSION_GRANTED && res2 == PackageManager.PERMISSION_GRANTED);
}
Now you only need to apply this to your method such as:
if(checkWriteExternalPermission()){
//do your logic with file writing/reading
} else{
//ask for user permissions
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}