Android 11不使用SAF访问/sdcard/Download下文件的问题求助
问题根因
Android 11(API 30)及以上版本的分区存储规则对普通存储权限做了限制:你申请的READ_EXTERNAL_STORAGE仅能授权访问公共目录下的三类媒体文件(图片、音频、视频),json、js等非媒体文件,以及其他应用生成的非媒体文件,即便放在Download等公共目录下,普通存储权限也没有读取权限,这就是你只能枚举到文件夹、看不到普通文件的原因。
符合谷歌规范的解决方案
你需要申请官方提供的所有文件访问权限(MANAGE_EXTERNAL_STORAGE),该权限是API 30以上专门面向需要全量文件访问能力的应用推出的合规方案,不需要用到legacy storage:
实现步骤
- 在
AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- 动态触发权限申请:
首先判断当前是否已经拿到权限,未拿到的情况下跳转到系统授权页引导用户开启:
// 自定义请求码常量 val REQUEST_MANAGE_STORAGE = 1001 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { // 跳转到对应应用的所有文件访问权限设置页 val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.data = Uri.parse("package:${packageName}") startActivityForResult(intent, REQUEST_MANAGE_STORAGE) } else { // 已拿到权限,直接执行你的拷贝逻辑即可 executeFileCopy() } } else { // API 30以下版本,申请READ_EXTERNAL_STORAGE权限后即可正常使用File API requestReadStoragePermission() }
- 用户完成授权回到应用后,你原先的File读写、枚举逻辑不需要做任何修改,即可正常读取Download等公共目录下的所有文件和文件夹。
注意事项
- 该权限的申请需要符合Google Play的上架政策:只有应用的核心功能必须依赖全量文件访问(如文件管理器、数据备份工具等)才能申请,不符合场景的申请会被Google Play驳回上架。如果你的应用核心功能不需要全量文件访问,建议优先调整逻辑使用MediaStore或者SAF方案实现。
- 如果你只需要访问本应用自身写入到公共目录的非媒体文件,可以通过
MediaStore.Downloads集合查询对应文件,不需要申请该权限。
内容的提问来源于stack exchange,提问作者SOSparachuter1
相关产品推荐
相关产品推荐

