如何通过Android ContentResolver查询图库文件并区分图片与视频
核心修改说明
你原有代码存在3个核心问题:
- 仅查询了图片媒体库的URI,无法获取视频文件
- 投影字段缺少媒体类型字段,无法区分图片/视频
- 未对Cursor做资源回收,有内存泄漏风险
前置权限配置
首先在AndroidManifest.xml中声明存储权限:
- Android 12及以下:添加
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> - Android 13及以上:添加
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />和<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
注:所有版本都需要先动态申请存储权限,拿到授权后再执行媒体查询逻辑
修正后的完整代码
public List<MediaFileModel> getAllGalleryMedia() { List<MediaFileModel> galleryMedia = new ArrayList<>(); // 投影字段新增MIME_TYPE用于判断媒体类型 String[] projection = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.MIME_TYPE }; // 分别查询图片库和视频库 Uri[] mediaUris = { MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Video.Media.EXTERNAL_CONTENT_URI }; for (Uri uri : mediaUris) { // 用try-with-resources自动关闭Cursor,避免内存泄漏 try (Cursor cursor = getActivity().getContentResolver().query( uri, projection, null, null, null)) { if (cursor == null) continue; while (cursor.moveToNext()) { MediaFileModel next = new MediaFileModel(); // 获取绝对路径(API29+已废弃,自用低版本targetSDK可正常使用) String absPath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)); // 获取媒体类型 String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.MIME_TYPE)); Bitmap thumbnail = null; // 通过MIME类型前缀判断是图片还是视频 if (mimeType.startsWith("image/")) { thumbnail = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(absPath), 64, 64); } else if (mimeType.startsWith("video/")) { thumbnail = ThumbnailUtils.createVideoThumbnail(absPath, MediaStore.Images.Thumbnails.MINI_KIND); } next.setThumbnail(thumbnail); next.setAbsPath(absPath); galleryMedia.add(next); } } catch (Exception e) { e.printStackTrace(); } } return galleryMedia; }
补充说明
如果需要适配Android 10(API29)及以上版本,MediaStore.MediaColumns.DATA已经被官方废弃,不能直接通过路径访问文件,可以通过ContentResolver.openFileDescriptor()获取文件描述符来生成缩略图,不需要读取绝对路径也能实现需求。
内容的提问来源于stack exchange,提问作者hotmeatballsoup
相关产品推荐
相关产品推荐

