You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 13中替换非自有文件失败:写入时遇FileNotFoundException

解决Android 13中替换原媒体文件时的FileNotFoundException问题

问题根源

你不需要先删除原文件再写入——调用MediaStore.createDeleteRequest删除后,原URI对应的媒体条目已从系统媒体库中移除,此时该URI不再指向任何有效资源,自然无法打开输出流。另外,你用了"wt"文本模式打开输出流,这会损坏二进制图片数据,也是潜在问题。

正确解决方案:直接覆盖原文件

跳过删除步骤,直接打开原URI的输出流,以二进制模式写入编辑后的内容即可:

// 移除原删除请求代码,直接执行以下写入逻辑
context.contentResolver.openOutputStream(outputUri, "w")?.use { output ->
    val buffer = ByteArray(4096)
    var length: Int
    while (inputStream.read(buffer).also { length = it } > 0) {
        output.write(buffer, 0, length)
    }
    output.flush()
}

关键注意事项

  • 模式选择:用"w"(二进制覆盖模式)替代"wt"(文本模式),图片是二进制文件,文本模式会导致数据解析错误。
  • 权限说明:
    • 若编辑的是自己应用拍摄的图片:Android 13及以上无需额外权限,应用默认拥有自身创建媒体文件的读写权限。
    • 若编辑其他应用的图片:需申请READ_MEDIA_IMAGES权限,并确保已获取用户授权。

特殊场景:删除后重新创建(非替换需求)

如果确实需要删除原文件后创建新文件,不能复用旧URI,需重新插入新的媒体条目获取新URI:

// 删除原文件(保留你的删除请求代码)
val intentSender = MediaStore.createDeleteRequest(contentResolver, uriList).intentSender
deleteRequestResult.launch(IntentSenderRequest.Builder(intentSender).build())

// 删除完成后插入新条目获取新URI
val values = ContentValues().apply {
    put(MediaStore.Images.Media.DISPLAY_NAME, "edited_photo.jpg")
    put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
    put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM)
}
val newUri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)

// 写入新URI
newUri?.let { uri ->
    context.contentResolver.openOutputStream(uri, "w")?.use { output ->
        val buffer = ByteArray(4096)
        var length: Int
        while (inputStream.read(buffer).also { length = it } > 0) {
            output.write(buffer, 0, length)
        }
        output.flush()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:27:54