为什么我从外部存储加载图片时获取到的Cursor为空?
问题原因
你遇到的android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0报错本质是MediaStore查询返回的Cursor为空,且你在Cursor位置还处于初始索引-1的状态下就尝试读取列值。结合你的场景,常见触发原因和对应解决方法如下:
排查&解决步骤
存储权限适配错误
不同安卓版本读取公共媒体需要的权限不同,需对应配置:- API ≤32(安卓12及以下):需要在清单文件声明
READ_EXTERNAL_STORAGE权限,且动态申请用户授权 - API ≥33(安卓13及以上):
READ_EXTERNAL_STORAGE已废弃,需要声明并动态申请READ_MEDIA_IMAGES权限
未获得对应权限时,MediaStore查询会直接返回空Cursor。
- API ≤32(安卓12及以下):需要在清单文件声明
模拟器媒体库未刷新
你手动存入模拟器目录的图片不会自动同步到MediaStore数据库,需要先触发媒体库更新:要么重启模拟器,要么调用系统媒体扫描广播,也可以先打开系统自带相册,确认你存入的图片能在相册中正常显示后再调试你的代码。代码潜在问题修正
你当前代码存在查询URI和拼接URI不统一的问题:API29以上你查询用的是VOLUME_EXTERNAL对应的URI,拼接图片URI时却固定用了旧的EXTERNAL_CONTENT_URI,虽然不会直接导致Cursor为空,但后续加载图片可能出现异常。同时建议增加Cursor非空校验,避免异常。
修正后的参考代码
private suspend fun loadImages(): List<Image> { return withContext(Dispatchers.IO) { val queryUri = if(Build.VERSION.SDK_INT >= 29) { MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL) } else { MediaStore.Images.Media.EXTERNAL_CONTENT_URI } requireActivity().contentResolver.query( queryUri, arrayOf(MediaStore.Images.Media._ID), null, null, "${MediaStore.Images.Media.DATE_ADDED} ASC" )?.use { cursor -> val photos = mutableListOf<Image>() // 先判断Cursor有数据再操作 if (cursor.count > 0) { val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID) while (cursor.moveToNext()) { val id = cursor.getLong(idColumn) // 用查询时的URI拼接,避免URI不匹配 val contentUri = ContentUris.withAppendedId(queryUri, id) photos.add(Image(id, contentUri)) } } photos } ?: emptyList() } }
内容的提问来源于stack exchange,提问作者Łukasz Orzechowski
相关产品推荐
相关产品推荐

