android - Jetpack Compose - 在 Image PIcker 后调整图像大小(ContentResolver 异常?)

我只是在用户从我的应用程序启动 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 的内容感到困惑。

呵呵。也许其他人会像我一样做一些愚蠢的事情,这会有所帮助。

相似文章

随机推荐

最新文章