targetSDK30适配Android11用SAF申请WhatsApp媒体权限后加载文件被拒
问题解决方案
根因说明
Android 11 起分区存储规则强制执行,你通过 Storage Access Framework 拿到的授权仅针对SAF返回的content://类型URI生效。你当前使用的本地File对象、Uri.fromFile()生成的file://格式URI不属于SAF授权范围,系统会直接拒绝访问,因此抛出EACCES权限错误。
加载图片修复步骤
- 废弃所有构造本地File对象、生成
file://URI加载图片的逻辑 - 直接使用SAF查询文件时获取到的
content://URI加载资源:// Glide加载直接传入content URI Glide.with(context) .load(contentUri) .into(imageView) // 直接调用setImageURI同样适用 imageView.setImageURI(contentUri) - 如果你通过
DocumentFile操作文件,直接调用DocumentFile#getUri()即可获取有效授权的content URI
后续写入、复制逻辑实现方案
文件写入
如果是修改SAF授权目录下的已有文件,直接通过ContentResolver打开输出流写入即可:
contentResolver.openOutputStream(targetContentUri, "w")?.use { outputStream -> // 写入对应数据即可 }
如果需要新建文件,通过DocumentFile#createFile()创建文件后拿到生成的content URI,再按上述逻辑写入即可。
文件复制
源文件和目标文件均在SAF授权范围内的话,分别打开对应输入流、输出流对接即可,无需申请额外文件路径权限:
contentResolver.openInputStream(sourceContentUri)?.use { inputStream -> contentResolver.openOutputStream(targetContentUri)?.use { outputStream -> inputStream.copyTo(outputStream) } }
权限持久化校验
确认你在用户完成目录授权后已经调用权限持久化方法,避免应用重启后权限失效:
// 用户授权完成的回调中执行 val uri = resultData.data ?: return val authFlags = resultData.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) contentResolver.takePersistableUriPermission(uri, authFlags)
额外说明
- targetSDKVersion >= 30时
requestLegacyExternalStorage配置已失效,无需再调整该配置 - 不要尝试使用私有API绕过分区存储直接访问
/sdcard/Android/media路径的本地File对象,不符合Google Play应用上架规则。
内容的提问来源于stack exchange,提问作者User
相关产品推荐
相关产品推荐

