diff --git a/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt b/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt index 40e167b..19f6f3c 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt @@ -173,8 +173,9 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope: } val attachment = notification.attachment val image = attachment.contentUri != null && supportedImage(attachment.type) && previewableImage(attachmentFileStat) - maybeRenderAttachmentImage(context, attachment, image) - maybeRenderAttachmentBox(context, notification, attachment, attachmentFileStat, image) + val bitmap = if (image) attachment.contentUri?.readBitmapFromUriOrNull(context) else null + maybeRenderAttachmentImage(context, bitmap) + maybeRenderAttachmentBox(context, notification, attachment, attachmentFileStat, bitmap) } private fun maybeRenderIcon(context: Context, notification: Notification, iconStat: FileInfo?) { @@ -238,8 +239,8 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope: return button } - private fun maybeRenderAttachmentBox(context: Context, notification: Notification, attachment: Attachment, attachmentFileStat: FileInfo?, image: Boolean) { - if (image) { + private fun maybeRenderAttachmentBox(context: Context, notification: Notification, attachment: Attachment, attachmentFileStat: FileInfo?, bitmap: Bitmap?) { + if (bitmap != null) { attachmentBoxView.visibility = View.GONE return } @@ -348,13 +349,12 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope: } } - private fun maybeRenderAttachmentImage(context: Context, attachment: Attachment, image: Boolean) { - if (!image) { + private fun maybeRenderAttachmentImage(context: Context, bitmap: Bitmap?) { + if (bitmap == null) { attachmentImageView.visibility = View.GONE return } try { - val bitmap = attachment.contentUri?.readBitmapFromUri(context) ?: throw Exception("uri empty") attachmentImageView.setImageBitmap(bitmap) attachmentImageView.setOnClickListener { val loadImage = { view: ImageView, image: Bitmap -> view.setImageBitmap(image) } diff --git a/app/src/main/java/io/heckel/ntfy/util/Util.kt b/app/src/main/java/io/heckel/ntfy/util/Util.kt index 6bc5267..d987e41 100644 --- a/app/src/main/java/io/heckel/ntfy/util/Util.kt +++ b/app/src/main/java/io/heckel/ntfy/util/Util.kt @@ -419,11 +419,16 @@ fun View.ripple(scope: CoroutineScope) { } } - fun Uri.readBitmapFromUri(context: Context): Bitmap { val resolver = context.applicationContext.contentResolver val bitmapStream = resolver.openInputStream(this) - return BitmapFactory.decodeStream(bitmapStream) + val bitmap = BitmapFactory.decodeStream(bitmapStream) + if (bitmap.byteCount > 100 * 1024 * 1024) { + // If the Bitmap is too large to be rendered (100 MB), it will throw a RuntimeException downstream. + // This workaround throws a catchable exception instead. See issue #474. From https://stackoverflow.com/a/53334563/1440785 + throw Exception("Bitmap too large to draw on Canvas (${bitmap.byteCount} bytes)") + } + return bitmap } fun String.readBitmapFromUri(context: Context): Bitmap { diff --git a/fastlane/metadata/android/en-US/changelog/29.txt b/fastlane/metadata/android/en-US/changelog/29.txt index 26c7710..ef5587c 100644 --- a/fastlane/metadata/android/en-US/changelog/29.txt +++ b/fastlane/metadata/android/en-US/changelog/29.txt @@ -9,6 +9,7 @@ Bug fixes + maintenance: * Fix auto-delete if some icons do not exist anymore (#506) * Fix notification icon color (#480, thanks to @s-h-a-r-d for reporting) * Fix topics do not re-subscribe to Firebase after restoring from backup (#511) +* Fix crashes from large images (#474, thanks to @daedric7 for reporting) * Add donate button (no ticket) Additional translations: