Jetpack Compose — изменение размера изображения после выбора изображения (исключение ContentResolver?)

Я просто пытаюсь изменить размер изображения после того, как пользователь запускает средство выбора изображений из моего приложения и выбирает файл изображения на локальном устройстве (обработка удаленного изображения из 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

Это происходит после того, как изображение выбрано в средстве выбора, потому что я запускаю свой код «обработки», чтобы найти изображение, изменить его размер и скопировать во вложенную папку в папке приложения.

Как я уже сказал, это сработало, но я не уверен, что сейчас не так. Я пробовал это на эмуляторе, а также на моем Galaxy S10 через USB-отладку, и результат тот же. Изображение находится в папке «Скачать» локального хранилища на эмуляторе, а также на моем собственном устройстве.

URI выглядит странно (я имею в виду, что изображение находится только в папке «Загрузить» локального хранилища), но я не эксперт URI, поэтому я предполагаю, что это нормально, потому что это то, что возвращает средство выбора изображений.

Вот немедленный код, который вызывает исключение (в частности, вызов):

      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 (которая функция просто вызывает указанную выше), где я отправляю 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, но даже так), но я действительно не считаю запуск средства выбора изображений и изменение размера полученного изображения настолько странным. Любая помощь будет велика от вас, умных людей.

1 ответ

Сделать шаг в сторону от проблем с программированием и вернуться иногда кажется лучшим выбором, лол.

Я вернулся сегодня вечером и через пару минут заметил, что отправляю неправильный 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.

Дох. Может быть, кто-то еще сделает что-то глупое, как я, и это может помочь.

Другие вопросы по тегам