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
相关产品推荐
相关产品推荐

