Android 10设备上的存储权限因sdk目标30与目标27而不同

问题描述

我有两个版本的应用程序共有的文件访问例程(这是完整的方法):

public void openDataRestore(CfgTab tableFileEnum){
    cfgStatFileName = sensorCalibFileNames[tableFileEnum.ordinal()]+".cfg"; // "FrAccTab.cfg"
    File apdatSubDir;
    if(System.getenv("EXTERNAL_STORAGE")!=null){
        try {
            String extPath;
            extPath = System.getenv("EXTERNAL_STORAGE"); // "/sdcard"
            String fullPathName = extPath+getApplicationContext().getString(R.string.dat_dir); // "/sdcard/apdat/"
            apdatSubDir = new File(fullPathName);
            File[] reportFiles = apdatSubDir.listFiles(new FilenameFilter() {
                public boolean accept(File dir,String name) {
                    return name.matches(cfgStatFileName);  // "FrAccTab.cfg"
                }
            });
            if(reportFiles!=null&&reportFiles.length==1) {
                File reportFile = reportFiles[0];
                cfgFr = new FileReader(reportFile);
                cfgIn = new BufferedReader(cfgFr);
            }
        } catch (IOException ioe) {
            if(ioe.getMessage().contains("Permission denied")){
                AlertDialog.Builder builder2 = new AlertDialog.Builder(activeFragmentView.getContext());
                builder2.setMessage(ioe.getMessage()+"\n\n"+getApplicationContext().getString(R.string.store_perms))
                        .setNeutralButton(R.string.ok,new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,int id) {
                                confirmOpenRestoreFile = true;
                            }
                        });
                builder2.show();
                return;
            }
            System.err.println(ioe.getMessage());
        }
    }
}

在较早的部署中,它可与清单权限API 29:目标27:

一起使用
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

但是在较新的一种API 30 Target 30上,只有在这修改清单的情况下,它才有效:

<application
    android:requestLegacyExternalStorage="true"
 ....
</application>

我的测试设备是Android 10,这意味着API 29,这意味着使用AS4.0推荐的API 30目标30会给代码段带来更多麻烦?我尝试过的另一种文件访问过程:

File targetItem = new File(fullPathName+cfgStatFileName);
if(targetItem!=null){
   cfgFr = new FileReader(targetItem);
   cfgIn = new BufferedReader(cfgFr);
}

在创建新的FileReader(targetItem)时在API 30 Target 30中生成IOException,并且比尝试先打开子目录的失败失败更令人欣慰。 而且,File.mkdirs()在只读上下文中似乎不合适,这是较新的应用程序试图从较旧的应用程序读取的内容。理想情况下,需要两者在特定平台上共存吗?。

PS:我删除了多余的mkdirs(),还尝试通过撤消Manifest requestLegacyExternalStorage来重新创建错误。但是问题并未重现,因为显然Android 10现在知道此新版本已获得许可。所以问题出在新应用上,因为旧应用在Android从9升级到10之前已经获得许可...

解决方法

似乎与新应用的Android 10权限处理有关。在出现问题期间,没有任何手动的“ Android设置权限管理器允许”尝试将允许新应用在允许的“ 14 of 26”存储权限下列出,现在,由于在运行带有requestLegacyExternalStorage =“ true”的操作后,Android 10现在显示“允许26个中的15个,并且该应用现在已列出,而在此之前,我必须先按名称搜索它,以手动设置其权限。