Flutter如何将content类型URI转换为Download目录的真实文件路径
解决方案
你之前使用uri_to_file拿到临时路径的核心原因是:该插件的默认逻辑是通过ContentResolver打开uri对应的文件输入流,将文件拷贝到应用私有目录后返回私有目录路径,本质是生成文件副本,不会返回原始存储路径。
针对content://media/external/audio/media/[id]这类MediaStore类型的content uri,直接通过ContentResolver查询媒体库存储的原始路径字段即可拿到Download目录下的真实文件地址,不需要拷贝文件。
具体实现方式
- 自定义MethodChannel实现(可控性最高,无额外性能损耗)
- 在Android原生端编写路径查询逻辑,核心是查询MediaStore的
DATA字段,示例Kotlin代码如下:
// 传入从Flutter端拿到的content uri字符串 val mediaUri = Uri.parse("content://media/external/audio/media/906") val cursor = contentResolver.query( mediaUri, arrayOf(MediaStore.MediaColumns.DATA), null, null, null ) cursor?.use { if (it.moveToFirst()) { // 该值即为公共存储下的真实文件路径,如/storage/emulated/0/Download/Music.mp3 val realFilePath = it.getString(it.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)) // 将realFilePath通过MethodChannel返回给Flutter端即可 } }- Flutter端通过MethodChannel将待转换的content uri字符串传递到Android端,接收返回的真实路径使用即可。
- 在Android原生端编写路径查询逻辑,核心是查询MediaStore的
- 使用现成插件实现:选择明确标注支持查询MediaStore真实路径、默认不做文件拷贝的路径处理插件即可,注意避开会自动生成临时副本的插件。
注意事项
*不要硬编码
/storage/emulated/0/这类路径前缀拼接路径,不同系统版本、不同厂商设备的公共存储根路径可能存在差异,必须通过系统ContentResolver查询获取路径,否则会出现路径匹配失败问题。
*对真实路径下的文件做读写操作前,需要申请对应存储权限:Android 13及以上版本申请READ_MEDIA_AUDIO权限,Android 12及以下版本申请READ_EXTERNAL_STORAGE权限。
*该查询方式仅适用于MediaStore类型的content uri,对于其他应用提供的、非媒体库类型的content uri,系统不会暴露原始路径,只能通过流拷贝的方式处理。
内容的提问来源于stack exchange,提问作者Mike Zero
相关产品推荐
相关产品推荐

