尝试在API 25上复制文件时出现FileNotFoundException

时间:2018-07-11 12:37:40

标签: android file mobile

最近几个小时我一直在尝试解决一个问题,但未能解决。我试图将数据库从一个位置复制到另一个位置。 在具有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均已植根。

1 个答案:

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