Android 11不使用MANAGE_EXTERNAL_STORAGE如何获取外部存储全部图片视频
适配Android 11+媒体资源读取的正确实现方案
如果你的应用仅需要读取公共目录下的图片、视频类媒体资源,完全不需要申请MANAGE_EXTERNAL_STORAGE权限,基于分区存储规则使用MediaStore加对应媒体权限即可实现需求,具体适配方案如下:
权限适配规则
- Android 13(API 33+):无需申请旧版存储权限,仅需要申请对应细分媒体权限
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO - Android 11~12L(API 30~32):仅需要申请
READ_EXTERNAL_STORAGE权限,无需申请存储管理权限和写入权限(写入自有媒体文件无需权限,修改其他应用创建的媒体文件走单独授权流程) - Android 10及以下:保留原有读写存储权限逻辑即可
清单文件权限声明
<!-- Android 13+ 媒体权限 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- Android 12及以下 读取存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android 10及以下 写入存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <!-- 无需声明MANAGE_EXTERNAL_STORAGE权限 -->
修正后的权限校验代码
private boolean checkMediaPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // Android 13及以上 int readImgPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES); int readVideoPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VIDEO); return readImgPermission == PackageManager.PERMISSION_GRANTED && readVideoPermission == PackageManager.PERMISSION_GRANTED; } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // Android 11~12L int readStoragePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); return readStoragePermission == PackageManager.PERMISSION_GRANTED; } else { // Android 10及以下 int readPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); int writePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED; } }
MediaStore全量查询图片/视频代码示例
// 定义需要查询的媒体字段 String[] projection = new String[]{ MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.MIME_TYPE, MediaStore.Files.FileColumns.DATE_ADDED, MediaStore.Files.FileColumns.SIZE }; // 过滤条件:仅查询图片、视频类型文件 String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + " IN (?,?)"; String[] selectionArgs = new String[]{ String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE), String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO) }; // 排序规则:按文件添加时间倒序 String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC"; // 执行查询 try (Cursor cursor = getContentResolver().query( MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, sortOrder )) { if (cursor != null) { while (cursor.moveToNext()) { long mediaId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)); String fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME)); // 拼接可直接访问的媒体Uri,可直接加载到ImageView、播放器中 Uri mediaUri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), mediaId); // 此处添加你的业务处理逻辑 } } } catch (Exception e) { e.printStackTrace(); }
注意事项
- 如果业务仅需要用户选择部分媒体文件,无需全量扫描,更推荐调用系统原生相册选择器,无需申请任何权限,适配成本更低
- Android 11+如果需要修改/删除其他应用创建的媒体文件,走系统弹窗授权即可,无需申请存储管理权限
- 仅文件管理器、备份类工具等需要访问全量任意文件的应用才允许申请
MANAGE_EXTERNAL_STORAGE,普通媒体类应用申请该权限会被谷歌应用商店拒绝上架
内容的提问来源于stack exchange,提问作者Syed Fahad Hussain
相关产品推荐
相关产品推荐

