如何通过MediaStore与Cursor访问指定自定义文件夹中的图片?
如何通过MediaStore访问指定文件夹的图片
要通过MediaStore+Cursor方式筛选指定文件夹(如/MyFolder/Images/)的图片,核心是在查询时添加文件夹路径过滤条件,同时需要适配不同Android版本的存储API差异,具体实现如下:
1. 核心思路
MediaStore的query方法支持通过selection参数添加过滤规则,针对不同Android版本,需使用不同字段匹配文件夹路径:
- Android 10(API 29)及以上:使用
RELATIVE_PATH字段(存储相对于外部存储根目录的相对路径) - Android 9(API 28)及以下:使用
DATA字段(存储图片的绝对路径)
2. 完整代码实现
步骤1:定义目标文件夹路径
// Android 9及以下:目标文件夹的绝对路径 String targetAbsPath = Environment.getExternalStorageDirectory().getPath() + "/MyFolder/Images/"; // Android 10及以上:目标文件夹的相对路径(注意结尾的斜杠) String targetRelPath = "MyFolder/Images/";
步骤2:构建查询条件
根据系统版本选择对应的过滤字段:
String selection; String[] selectionArgs; String[] projection = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA, MediaStore.Images.Media.RELATIVE_PATH, MediaStore.Images.Media.DATE_TAKEN }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10+:匹配相对路径 selection = MediaStore.Images.Media.RELATIVE_PATH + " LIKE ?"; // 添加%可匹配目标文件夹下的所有子文件夹;仅需当前文件夹则去掉% selectionArgs = new String[]{targetRelPath + "%"}; } else { // Android 9-:匹配绝对路径 selection = MediaStore.Images.Media.DATA + " LIKE ?"; selectionArgs = new String[]{targetAbsPath + "%"}; }
步骤3:执行查询并处理图片
Cursor cursor = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC" // 按拍摄时间倒序 ); if (cursor != null && cursor.moveToFirst()) { int idColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID); int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA); do { Bitmap bm = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10+:通过Content Uri加载图片(适配Scoped Storage) long imageId = cursor.getLong(idColumn); Uri imageUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageId); try (InputStream is = getContentResolver().openInputStream(imageUri)) { bm = BitmapFactory.decodeStream(is); } catch (IOException e) { e.printStackTrace(); } } else { // Android 9-:直接通过文件路径加载 String imagePath = cursor.getString(dataColumn); File imageFile = new File(imagePath); if (imageFile.exists()) { bm = BitmapFactory.decodeFile(imagePath); } } // 处理加载完成的Bitmap(例如显示到ImageView) if (bm != null) { // imageView.setImageBitmap(bm); } } while (cursor.moveToNext()); cursor.close(); }
3. 注意事项
- 权限要求:
- Android 12及以下:需要申请
READ_EXTERNAL_STORAGE权限 - Android 13及以上:需要申请
READ_MEDIA_IMAGES权限
需在Manifest中声明权限,并通过动态权限申请流程获取授权。
- Android 12及以下:需要申请
- 路径匹配规则:使用
LIKE ?加%可匹配目标文件夹下所有子文件夹的图片;仅需当前文件夹则去掉%(注意路径结尾的斜杠需保持一致)。 - Scoped Storage适配:Android 10及以上不建议直接使用文件路径访问,通过Content Uri+ContentResolver的方式更符合系统规范,避免权限问题。
内容的提问来源于stack exchange,提问作者CoolCoder
相关产品推荐
相关产品推荐

