从最近文件选择器返回错误Uri,如何获取正确的Uri?
解决从「最近」获取的媒体URI转换为外部存储路径URI的问题
问题本质
你拿到的content://com.android.providers.media.documents/document/image%3A1000000040是媒体库ID型URI,它指向媒体库中索引的条目,仅关联媒体ID而非实际文件路径;而你需要的content://com.android.externalstorage.documents/document/primary%3ADCIM%2Fx%2F24538c.png是外部存储路径型URI,基于文件在外部存储的真实路径生成。直接转File再转回URI无效,因为File只能拿到本地路径,无法直接映射到externalstorage的URI格式。
解决步骤
1. 通过媒体URI查询文件绝对路径
利用ContentResolver查询媒体库,获取对应文件的真实路径:
public String getMediaFilePath(Context context, Uri mediaUri) { String filePath = null; // 针对图片,视频/音频替换为MediaStore.Video.Media.DATA/MediaStore.Audio.Media.DATA String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(mediaUri, projection, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); filePath = cursor.getString(columnIndex); } cursor.close(); } return filePath; }
2. 从绝对路径构建外部存储URI
拿到文件路径后,拆分存储卷和相对路径,生成目标格式的URI:
public Uri getExternalStorageUri(String filePath) { String volumeName = "primary"; // 默认主存储 // 去除主存储根路径,保留相对路径 String relativePath = filePath.replace("/storage/emulated/0/", ""); // 编码路径并拼接成目标URI String encodedPath = Uri.encode(volumeName + ":" + relativePath); return Uri.parse("content://com.android.externalstorage.documents/document/" + encodedPath); }
3. 完整调用示例
Uri mediaUri = Uri.parse("content://com.android.providers.media.documents/document/image%3A1000000040"); String filePath = getMediaFilePath(context, mediaUri); if (filePath != null) { Uri targetUri = getExternalStorageUri(filePath); // 此时targetUri就是你需要的外部存储路径型URI }
注意事项
- Android 10及以上版本,
MediaStore.Media.DATA字段可能返回空或受限,可改用MediaStore.Images.Media.RELATIVE_PATH结合存储卷信息构建路径。 - 需确保已申请
READ_EXTERNAL_STORAGE权限(Android 13+需单独申请图片/视频/音频的读取权限)。
内容的提问来源于stack exchange,提问作者Dev4fuN
相关产品推荐
相关产品推荐

