使用MediaStore读取安卓模拟器Downloads图片时Cursor返回大小为0如何解决
问题排查与修复方案
1. 首要检查:存储权限配置
不同安卓版本对公共存储的访问权限要求不同,这是Cursor返回为空的最常见原因:
- Android 13(API 33及以上):需动态申请
READ_MEDIA_IMAGES权限,原有READ_EXTERNAL_STORAGE权限已失效 - Android 10-12(API 29-32):两种方案二选一:
- 动态申请
READ_EXTERNAL_STORAGE权限 - 在AndroidManifest.xml的
<application>节点添加android:requestLegacyExternalStorage="true",临时启用旧版存储模型(该配置在Android13及以上无效)
- 动态申请
- Android 9及以下(API ≤28):动态申请
READ_EXTERNAL_STORAGE权限,仅在Manifest静态声明不生效
注意:必须等权限申请用户同意后,再执行MediaStore查询逻辑。
2. 修正代码逻辑问题
你的现有代码存在3处可导致查询为空/报错的问题:
- 查询的projection列和后续读取的列不匹配:你声明的projection仅包含
_ID和TITLE,但后续读取了DISPLAY_NAME列,会导致查询异常 - 未添加图片类型筛选:无筛选条件时查询所有类型文件,如果你要仅读取图片,建议添加MIME类型筛选
- URI拼接规则错误:Android Q及以上查询用的是
VOLUME_EXTERNAL_PRIMARY对应的URI,但拼接文件URI时固定用了旧的EXTERNAL_CONTENT_URI,会导致部分设备读取不到内容
修正后的参考代码:
// 先确认已获取对应存储权限后再执行以下代码 Uri collection; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); } else { collection = MediaStore.Downloads.EXTERNAL_CONTENT_URI; } // 补充需要用到的DISPLAY_NAME列 String[] projection = { MediaStore.MediaColumns._ID, MediaStore.MediaColumns.TITLE, MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.MIME_TYPE }; // 添加图片筛选条件,只查询图片类型文件 String selection = MediaStore.MediaColumns.MIME_TYPE + " LIKE ?"; String[] selectionArgs = new String[]{"image/%"}; Cursor cursor = null; try { cursor = getApplicationContext().getContentResolver().query(collection, projection, selection, selectionArgs, null); if (cursor == null || cursor.getCount() == 0) { // 可添加空数据提示逻辑 return; } int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID); int nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Downloads.DISPLAY_NAME); while (cursor.moveToNext()) { long id = cursor.getLong(idColumn); String name = cursor.getString(nameColumn); // 和查询用的collection保持一致拼接URI,适配不同安卓版本 Uri contentUri = ContentUris.withAppendedId(collection, id); // 这里仅示例,实际使用不要在循环里重复findViewById和赋值覆盖 ImageView imageView = findViewById(R.id.imageView); imageView.setImageURI(contentUri); } } catch (Exception e) { e.printStackTrace(); } finally { // 用完关闭Cursor避免内存泄漏 if (cursor != null) { cursor.close(); } }
3. 其他可能的异常场景
如果权限和代码都修正后还是查询不到数据,可排查以下情况:
- 目标图片是刚拷贝/下载到Download目录的,还没被系统媒体库扫描入库:可以手动触发媒体库扫描,或者重启设备后再测试
- 图片文件被其他应用设置了特殊权限,不允许第三方应用读取
- 部分定制ROM对公共存储访问做了额外限制,需要确认应用的存储权限开关已经手动打开
内容的提问来源于stack exchange,提问作者Alex Brito
相关产品推荐
相关产品推荐

