Android 11+如何通过作用域存储访问/sdcard/Android/media文件夹
Android 11+ 无需MANAGE_EXTERNAL_STORAGE访问其他应用Android/media目录媒体文件方案
核心原理
Android 11(API 30)引入的作用域存储规则中,应用申请媒体读取权限后,可通过系统媒体库(MediaStore)读取所有其他应用存储在公共存储区域的媒体类文件(图片/视频/音频)。而第三方应用存放在/storage/emulated/0/Android/media/对应包名下的媒体文件会自动被系统收录到MediaStore,因此无需申请全文件管理权限即可访问。
前置权限配置
在AndroidManifest.xml中根据目标SDK版本声明对应权限:
- targetSdk ≤ 32:仅需声明读取外部存储权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- targetSdk ≥ 33:需声明对应细粒度媒体权限
<!-- 读取图片权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- 读取视频权限 --> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
应用运行时主动申请上述权限,用户授权后即可执行后续查询操作。
通过MediaStore查询目标目录媒体文件(以WhatsApp状态目录为例)
不要直接使用File API访问目标路径(Android 11+会直接触发权限错误),而是通过ContentResolver查询MediaStore,过滤相对路径即可拿到.Statuses目录下的所有图片、视频文件:
查询代码示例(Kotlin)
// 要查询的目标相对路径 val targetRelativePath = "Android/media/com.whatsapp/WhatsApp/Media/.Statuses/" // 查询的列信息 val projection = arrayOf( MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.MIME_TYPE, MediaStore.MediaColumns.SIZE, MediaStore.MediaColumns.DATE_MODIFIED ) // 查询条件:匹配相对路径 val selection = "${MediaStore.MediaColumns.RELATIVE_PATH} = ?" val selectionArgs = arrayOf(targetRelativePath) // 先查图片 val imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI contentResolver.query(imageUri, projection, selection, selectionArgs, null)?.use { cursor -> while (cursor.moveToNext()) { val fileId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)) val fileUri = ContentUris.withAppendedId(imageUri, fileId) // 拿到fileUri即可读取文件内容、显示图片等 } } // 再查视频,逻辑和图片一致 val videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI contentResolver.query(videoUri, projection, selection, selectionArgs, null)?.use { cursor -> while (cursor.moveToNext()) { val fileId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)) val fileUri = ContentUris.withAppendedId(videoUri, fileId) // 处理视频文件 } }
备用方案:存储访问框架(SAF)授权
如果部分设备或特殊目录下MediaStore查询不到内容,可以引导用户手动授权目标文件夹访问权限,授权后可持久化访问该目录下的所有文件,同样不需要全文件管理权限:
- 调用系统文件选择器,定位到
/storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/.Statuses/目录 - 用户确认授权后,拿到对应目录的Uri,通过
DocumentFile即可访问目录下的所有文件 - 调用
takePersistableUriPermission方法持久化权限,下次启动应用无需重复授权
注意事项
- 该方案仅支持读取媒体类文件,非媒体格式的文件无法通过MediaStore获取
- 仅做读取操作无需额外权限,如果需要修改、删除其他应用的媒体文件,需要额外申请
WRITE_EXTERNAL_STORAGE(targetSdk≤32)或者触发用户交互确认 - 不要尝试直接通过File路径读写Android目录下的文件,所有操作必须基于MediaStore返回的Uri或者SAF授权拿到的Uri执行
内容的提问来源于stack exchange,提问作者Shrinidhi K
相关产品推荐
相关产品推荐

