Android如何将相册图片content Uri转换为完整路径(MediaStore.DATA已废弃)
Android MediaStore.Images.Media.DATA字段废弃后的正确实现方案
核心说明
Android 10(API 29)开始
MediaStore.Images.Media.DATA被正式废弃,官方不再提供直接获取媒体文件原始路径的稳定接口,对于其他应用生成的媒体资源,即便通过非正规方式拿到路径也会因权限限制无法读取。你的业务需求是上传图片到服务器,无需强行获取原始路径,通过ContentResolver操作文件流即可实现需求。
方案1:仅获取自身应用生成的媒体文件路径(适用范围有限)
如果要操作的图片是你的应用自身生成并存入公共相册的,可以用如下方式获取路径,该方式在Android 13上仍可正常工作,但不适用于其他应用生成的图片:
fun getMediaFilePath(context: Context, uri: Uri): String? { if (uri.scheme != ContentResolver.SCHEME_CONTENT) return uri.path // 仅适配应用自身生成的媒体资源 return try { context.contentResolver.query( uri, arrayOf(MediaStore.Images.Media.RELATIVE_PATH, MediaStore.Images.Media.DISPLAY_NAME), null, null, null )?.use { cursor -> if (cursor.moveToFirst()) { val relativePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.RELATIVE_PATH)) val displayName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)) "${Environment.getExternalStorageDirectory()}/$relativePath$displayName" } else null } } catch (e: Exception) { null } }
方案2:全版本通用方案(推荐,适配所有相册选中的图片)
不需要获取原始路径,直接将Content Uri的内容拷贝到应用私有缓存目录生成新的File对象,直接用这个File上传即可,无权限限制,适配所有Android版本:
fun uriToUploadFile(context: Context, uri: Uri): File? { return try { // 创建缓存文件,文件名可自定义,也可以解析使用原文件名 val tempFile = File(context.cacheDir, "upload_img_${System.currentTimeMillis()}.jpg") // 打开Uri对应的输入流 context.contentResolver.openInputStream(uri)?.use { inputStream -> // 将输入流拷贝到缓存文件 tempFile.outputStream().use { outputStream -> inputStream.copyTo(outputStream) } } tempFile.takeIf { it.exists() && it.length() > 0 } } catch (e: Exception) { null } }
注意事项
- 上传完成后主动删除临时缓存文件,避免占用用户存储
- 如果需要压缩图片,可以在流拷贝阶段加入压缩逻辑,减少上传体积
- 该方案不需要申请额外存储权限,仅使用应用自身私有缓存目录,合规性更高
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

