我有一个问题,在过去的几个小时里我一直试图解决,但没有成功。我试图将数据库从一个位置复制到另一个位置。当我的代码在安卓v.5.1.1的设备上运行时,我的代码可以正常工作,但在另一台运行7.1.0的设备上无法做到这一点。这是我的代码:
在AndroidManifest.xml 中请求权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".App"
android:allowBackup="true"
在我的活动
private static final int PHONE_STATE_PERMISSION = 0;
@Override
public void onViewDisplayed() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};
requestPermissions(permissions, PHONE_STATE_PERMISSION);
}
}
}
最后是负责复制的方法:
@Override
public Completable cloneDatabase() {
return Completable.fromAction(new Action() {
@Override
public void run() throws Exception {
try {
String currentDBPath = "/data/data/com.a/databases/my_db.db";
String backupDBPath = "/storage/emulated/0/my_folder/my_db_copy.db";
File currentDB = new File(currentDBPath);
File backupDB = new File(backupDBPath);
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
} catch (Exception e) {
Timber.e("Error while attempting to clone database " + e.getMessage());
}
}
});
}
这就是我得到的错误:
java.io.FileNotFoundException: /data/data/com.a/databases/my_db.db (Permission denied)
注:两个设备Nexus 5 5.1.1&Nexus 5x 7.1.0已生根。
根据我的观察,这里有两点。
首先,
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED
应该是
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
当权限未被授予时,无论是被拒绝还是其他情况,您都应该请求权限。我认为权限Manifest.permission.WRITE_EXTERNAL_STORAGE
就足够了。
其次,在用户与权限对话框交互后,您需要onRequestPermissionsResult
功能。若用户授予您复制数据库的权限,您就可以复制数据库。
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (requestCode == PHONE_STATE_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
cloneDatabase();
}
}
}