我只是在用户从我的应用程序启动 Image Picker 并在本地设备上选择一个图像文件后尝试调整图像大小(处理来自 Dropbox 的远程图像或其他东西将是另一场战斗)虽然这对我有用以前,现在我得到这个例外:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1105296364, result=-1, data=Intent { dat=content://com.android.externalstorage.documents/document/primary:Download/20170307_223207_cropped.jpg flg=0x1 }} to activity {my.app/MainActivity}: java.io.FileNotFoundException: No content provider: /document/primary:Download/20170307_223207_cropped.jpg
在选择器中选择图像后会发生这种情况,因为我正在运行我的“处理”代码来定位图像、调整图像大小并将其复制到应用程序文件夹中的子文件夹。
就像我说的,这行得通,但我不确定现在出了什么问题。我已经通过 USB 调试在模拟器和我的 Galaxy S10 上试过了,结果是一样的。该图像位于模拟器以及我自己的设备上的本地存储“下载”文件夹中。
URI 看起来很奇怪(我的意思是图片只是在本地存储“下载”文件夹中)但我不是 URI 专家所以我认为它很好,因为这就是 Image Picker 返回的内容。
这是抛出异常的直接代码(特别是 ImageDecoder.decodeBitmap
调用):
private fun copyFileToAppDataFolder(
context: Context,
imageTempPath: String
): String {
// ensure we are sent at least a non-empty path
if (imageTempPath.isEmpty()) {
return ""
}
val appDataFolder = "${context.dataDir.absolutePath}/images/firearms"
var filename = imageTempPath.substringAfterLast("/", "")
if (filename.isNullOrBlank()) {
filename = imageTempPath.substringAfterLast("%2F", "")
}
// couldn't parse filename from Uri; exit
if (filename.isNullOrBlank()) {
return ""
}
// get a bitmap of the selected image so it can be saved in an outputstream
var selectedImage: Bitmap? = null
selectedImage = if (Build.VERSION.SDK_INT <= 28) {
MediaStore.Images.Media.getBitmap(context.contentResolver, Uri.parse(imageTempPath))
} else {
ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, Uri.parse(imageTempPath)))
}
if (selectedImage == null) {
return ""
}
val destinationImagePath: String = "$appDataFolder/$filename"
val destinationStream = FileOutputStream(destinationImagePath)
selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, destinationStream)
destinationStream.close()
return destinationImagePath
}
上面的函数是从我的 ViewModel 调用的(processFirearmImage
函数只是调用上面的函数),我从 image Picker 发送结果 URI 以及应用程序上下文:
// this event is fired when the Image Picker returns
is AddEditFirearmEvent.AssignedPicture -> {
val resizedImagePath = ShotTrackerUtility.processFirearmImage(
event.applicationContext, // this is from LocalContext.current in Composable
event.value // result uri from image picker
)
_firearmImageUrl.value = resizedImagePath
}
我不知道,大声笑。我不敢相信这是一件如此困难的事情,但关于这方面的信息似乎很少(尤其是对于 Compose,但即便如此)但我真的不考虑启动 Image Picker 并将生成的图像调整为那么奇怪。聪明人的任何帮助都会很棒。
回答1
远离编程问题然后回来有时似乎是最好的选择,大声笑。
我今晚回来,几分钟后注意到我向 ImageDecoder.createSource
方法发送了一个不正确的 Uri,这导致了异常。基本上这是发生了:
val imageTempPath = theUriReturnedFromImagePicker.path ?: ""
ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, Uri.parse(imageTempPath)))
它应该是:
val imageUrl = theUriReturnedFromImagePicker
ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, imageUri))
正如我在 OP 中提到的,这最初是有效的,但我必须稍微更改代码(主要是我发送给各种方法/类的参数)。我还使用 Uri.path
部分来获取所选图像的文件名,因此我忽略了和/或对发送到 ImageDecoder.createSource
的内容感到困惑。
呵呵。也许其他人会像我一样做一些愚蠢的事情,这会有所帮助。