最近几个小时我一直在尝试解决一个问题,但未能解决。我试图将数据库从一个位置复制到另一个位置。 在具有android v.1.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均已植根。
答案 0 :(得分:1)
根据我的观察,这里有两点。
首先,
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();
}
}
}