通过MediaStore API获取Uri供Glide加载报错 Android 8+适配问题
问题根因
报错的核心原因是拼接Uri时统一使用了MediaStore.Images.Media.EXTERNAL_CONTENT_URI作为基础地址,但你查询的是MediaStore.Files全文件表,非图片类型的条目(视频、音频、其他文档)的id拼到图片专属的Uri下不存在对应资源,Glide读取失败后会降级提取Uri的path部分当本地文件路径读取,最终触发无文件的报错。ContentUris.withAppendedId不会自动补全协议前缀,它只会在传入的基础Uri后拼接id,传入的基础Uri本身错误的话,最终生成的Uri自然无法被识别。
适配Android 8+的正确实现
不需要依赖已废弃的DATA字段,只需要在查询时额外获取媒体类型列,根据每个条目的实际类型匹配对应正确的基础Content Uri即可,代码如下:
val mediaList = mutableListOf<Uri>() val query = buildQuery(folderId, onlyImages) query?.use { cursor -> val columnIndexId = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID) val columnIndexMimeType = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.MIME_TYPE) val columnIndexDuration = cursor.getColumnIndexOrThrow(MediaStore.Video.VideoColumns.DURATION) // 新增获取媒体类型列索引 val columnIndexMediaType = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MEDIA_TYPE) while (cursor.moveToNext()) { val id = cursor.getLong(columnIndexId) // 按条目实际类型匹配基础Uri val baseUri = when (cursor.getInt(columnIndexMediaType)) { MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI else -> MediaStore.Files.getContentUri("external") } val contentUri = ContentUris.withAppendedId(baseUri, id) mediaList.add(contentUri) } } return mediaList
Glide加载注意事项
- 直接将上述逻辑生成的
content://开头的Uri传入Glide的load()方法即可,Glide原生支持通过ContentResolver读取该类型资源,不需要做额外的路径转换 - 不要做Uri到本地文件路径的转换,完全可以避开已废弃的DATA字段,Android 8至Android 14全版本可正常运行
- 自定义缓存逻辑时直接使用Uri本身作为缓存key即可,不需要提取路径字段
内容的提问来源于stack exchange,提问作者Eman
相关产品推荐
相关产品推荐

