重装Android应用后无法访问公共文件夹文件的问题求助
适配Android 13公共目录访问权限问题的解决办法
针对重装应用后访问公共文档文件夹出现open failed: EACCES (Permission denied)的问题,Android 13对存储权限做了严格限制,android:requestLegacyExternalStorage="true"这个配置在Android 13及以上版本已完全失效,以下是适配的解决办法:
方案一:使用MANAGE_EXTERNAL_STORAGE权限(全存储访问)
这个权限允许应用访问设备上的所有文件,但属于特殊权限,需要用户手动到系统设置开启,且Google Play对该权限的使用有严格审核要求,仅适用于文件管理器、备份类等确实需要全存储访问的应用:
- 在
AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
- 代码中检查并请求权限:
if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, REQUEST_CODE_ALL_FILES); }
方案二:使用存储访问框架(SAF,推荐)
这是Google推荐的方式,通过让用户主动选择要访问的文件或文件夹来获取访问权限,符合Android 13的权限规范,无需申请特殊权限:
- 启动文件夹选择界面:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent, REQUEST_CODE_PICK_FOLDER);
- 在
onActivityResult中处理返回的Uri,并申请持久访问权限(避免每次重启应用都需要重新选择):
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_PICK_FOLDER && resultCode == RESULT_OK) { Uri treeUri = data.getData(); // 申请持久权限 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 后续通过ContentResolver操作该Uri对应的文件夹 DocumentFile pickedFolder = DocumentFile.fromTreeUri(this, treeUri); } }
注意:应用重装后,持久权限会失效,需要用户重新选择文件夹。
方案三:针对媒体文件的权限适配(仅适用于媒体类文件)
如果你的应用仅需要访问图片、视频、音频等媒体文件,Android 13拆分了原有的存储权限,只需申请对应媒体类型的权限:
- 在
AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
- 代码中动态请求这些权限即可,无需使用旧的
READ_EXTERNAL_STORAGE。
内容的提问来源于stack exchange,提问作者Rishabh Gupta
相关产品推荐
相关产品推荐

