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 (которая
// 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
.
Дох. Может быть, кто-то еще сделает что-то глупое, как я, и это может помочь.