我不明白为什么在 Android 11 中使用 `storage\emulated...\downloads` 文件夹可以 read/write 某些文件而不是其他文件?

I don't understand why in Android 11 use of `storage\emulated...\downloads` folder can read/write some files and not others?

问题: 我似乎无法理解为什么,针对 API 30 (Android 11),我的应用仍然可以从 storage\emulated...\download 文件夹整天存放各种文件,但每次在 *.db 文件上都失败...我能够在 API 29 上没有问题。

作为一个新应用程序,也是我的第一个应用程序,我真的不想依赖旧的解决方法。我宁愿这项工作从一开始就正确。此应用需要能够允许用户将文件附件导入和导出到此应用的数据库。

所以,回到我原来的问题...我不明白为什么使用 new FileInputStream(filename) 对一个文件使用相同的路径而不是另一个文件没有问题?这是应用程序和用户需要的唯一共享文件夹,它缓存所有其他内容。

使用此文件和相同路径

不使用此文件和相同的路径

更新: 添加了代码以阐明复制的意图。

InputStream source = new FileInputStream(sourcePath);
OutputStream destination = new FileOutputStream(destinationPath);
DatabaseManager.copyDatabase(dbSource, destination);

我可以使用 getContentResolver 进行更新和替换,但同样的问题仍然存在——适用于一台设备,而不适用于另一台设备。

InputStream source = getContentResolver().openInputStream(uri);

在上面评论中 Mark 的帮助下,这解决了我的问题。由于无法识别 .db 扩展名,我不得不使用 intent.setType("*/*") 并在 resultLauncher(即 ActivityResultLauncher)验证文件和扩展名。

https://developer.android.com/training/data-storage/shared/documents-files#open-file

private void setupImportDBButton(){
    mImportDB.setOnClickListener(v -> {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        resultLauncher.launch(intent);
    });
}

包含在 ActivityResultLauncher 中:用于解决 Android 11 (API 30) 要求强制的多设备使用的功能基础。关键是使用 getContentResolver().

Uri uri = result.getData().getData();
String destinationPath = this.getDatabasePath(strDBName).getPath();

    InputStream source = this.getContentResolver().openInputStream(uri);
    OutputStream destination = this.getContentResolver().openOutputStream(Uri.fromFile(new File(destinationPath)));
    DatabaseManager.copyDatabase(source, destination);