You need to enable JavaScript to run this app. 为什么File(uri.path)正常运行,uri.toFile()却报Uri lacks 'file' scheme错误
优惠活动
大模型
产品
解决方案
定价
更多

为什么File(uri.path)正常运行,uri.toFile()却报Uri lacks 'file' scheme错误

报错原因分析

你遇到的报错信息如下:

java.lang.IllegalArgumentException: Uri lacks 'file' scheme: content://***.provider/files/06082021_113127.jpg

核心原因

  • Uri.toFile()是Android Kotlin核心库(core-ktx)提供的扩展方法,仅支持scheme为file的Uri转换,源码逻辑就是先判断Uri的scheme值是否等于file,不匹配直接抛出你遇到的上述异常。
  • 你代码中调用FileProvider.getUriForFile()生成的Uri是content类型的scheme,这是Android系统为了文件共享安全设计的代理路径,不是本地文件的真实存储路径,自然不满足toFile()的调用要求。

隐藏问题说明

你代码中val test = uri?.path?.let { File(it) }的写法也是错误的:
content类型Uri的path字段返回的是ContentProvider的路径映射值,不是本地文件的真实路径,此时生成的File对象只是个空壳,无法正常读取到文件内容,只是因为路径最后一段恰好和文件名一致,所以打印name看起来正常,实际操作该文件会触发找不到文件的异常。


解决方案

分两种场景处理:

  1. 当前场景(自己生成的FileProvider Uri)
    你在生成Uri的时候已经持有了原始的本地File对象,直接把这个File存为全局变量即可,拍照成功后直接使用该File,不需要通过Uri转换,修改后代码参考:
private var uri: Uri? = null
// 新增全局变量保存原始File
private var captureImageFile: File? = null

binding.camera.setOnClickListener {
    val name = LocalDateTime.now().generateFileName()
    val file = File(requireContext().filesDir, "$name.jpg")
    // 保存File
    captureImageFile = file
    uri = FileProvider.getUriForFile(
        requireContext(),
        requireContext().packageName + ".provider",
        file
    )
    takePicture.launch(uri)
}

private val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean ->
    if (success) {
        // 直接使用保存的captureImageFile即可
        Log.e("image", "${captureImageFile?.name}")
    }
}
  1. 通用场景(拿到第三方提供的content Uri要转File)
    如果是其他应用分享/返回的content Uri,需要通过ContentResolver读取输入流,拷贝到自己应用可访问的目录下生成新的File:
fun uriToFile(context: Context, uri: Uri, targetFile: File): File? {
    return runCatching {
        context.contentResolver.openInputStream(uri)?.use { input ->
            targetFile.outputStream().use { output ->
                input.copyTo(output)
            }
        }
        targetFile
    }.getOrNull()
}

// 调用示例
val targetFile = File(context.cacheDir, "temp_image.jpg")
val convertedFile = uriToFile(context, contentUri, targetFile)

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 23:57:02