From c6218d47ffb09182ddc83b0375dbe96f5e43e6ff Mon Sep 17 00:00:00 2001 From: rosenberg_ptr Date: Mon, 8 Apr 2024 09:32:32 +0200 Subject: [PATCH] Fix bitmap exception crash --- .../CunningDocumentScannerPlugin.kt | 29 +++++++++---------- .../fallback/DocumentScannerActivity.kt | 19 ++++++++++-- .../fallback/utils/ImageUtil.kt | 16 +++++----- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/android/src/main/kotlin/biz/cunning/cunning_document_scanner/CunningDocumentScannerPlugin.kt b/android/src/main/kotlin/biz/cunning/cunning_document_scanner/CunningDocumentScannerPlugin.kt index 86ed879..ef6589a 100644 --- a/android/src/main/kotlin/biz/cunning/cunning_document_scanner/CunningDocumentScannerPlugin.kt +++ b/android/src/main/kotlin/biz/cunning/cunning_document_scanner/CunningDocumentScannerPlugin.kt @@ -79,7 +79,8 @@ class CunningDocumentScannerPlugin : FlutterPlugin, MethodCallHandler, ActivityA // check for errors val error = data?.extras?.getString("error") if (error != null) { - throw Exception("error - $error") + pendingResult?.error("ERROR", "error - $error", null) + return@ActivityResultListener true } // get an array with scanned document file paths @@ -92,19 +93,16 @@ class CunningDocumentScannerPlugin : FlutterPlugin, MethodCallHandler, ActivityA }?.toList() // trigger the success event handler with an array of cropped images - this.pendingResult?.success(successResponse) + pendingResult?.success(successResponse) return@ActivityResultListener true } Activity.RESULT_CANCELED -> { // user closed camera - this.pendingResult?.success(emptyList()) + pendingResult?.success(emptyList()) return@ActivityResultListener true } - - else -> { - return@ActivityResultListener false - } + else -> return@ActivityResultListener false } } else { when (resultCode) { @@ -112,13 +110,17 @@ class CunningDocumentScannerPlugin : FlutterPlugin, MethodCallHandler, ActivityA // check for errors val error = data?.extras?.getString("error") if (error != null) { - throw Exception("error - $error") + pendingResult?.error("ERROR", "error - $error", null) + return@ActivityResultListener true } // get an array with scanned document file paths val croppedImageResults = data?.getStringArrayListExtra("croppedImageResults")?.toList() - ?: throw Exception("No cropped images returned") + ?: let { + pendingResult?.error("ERROR", "No cropped images returned", null) + return@ActivityResultListener true + } // return a list of file paths // removing file uri prefix as Flutter file will have problems with it @@ -127,19 +129,16 @@ class CunningDocumentScannerPlugin : FlutterPlugin, MethodCallHandler, ActivityA }.toList() // trigger the success event handler with an array of cropped images - this.pendingResult?.success(successResponse) + pendingResult?.success(successResponse) return@ActivityResultListener true } Activity.RESULT_CANCELED -> { // user closed camera - this.pendingResult?.success(emptyList()) + pendingResult?.success(emptyList()) return@ActivityResultListener true } - - else -> { - return@ActivityResultListener false - } + else -> return@ActivityResultListener false } } } diff --git a/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/DocumentScannerActivity.kt b/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/DocumentScannerActivity.kt index d1a4517..fdad53a 100644 --- a/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/DocumentScannerActivity.kt +++ b/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/DocumentScannerActivity.kt @@ -80,7 +80,17 @@ class DocumentScannerActivity : AppCompatActivity() { } // get bitmap from photo file path - val photo: Bitmap = ImageUtil().getImageFromFilePath(originalPhotoPath) + val photo: Bitmap? = try { + ImageUtil().getImageFromFilePath(originalPhotoPath) + } catch (exception: Exception) { + finishIntentWithError("Unable to get bitmap: ${exception.localizedMessage}") + return@CameraUtil + } + + if (photo == null) { + finishIntentWithError("Document bitmap is null.") + return@CameraUtil + } // get document corners by detecting them, or falling back to photo corners with // slight margin if we can't find the corners @@ -313,7 +323,7 @@ class DocumentScannerActivity : AppCompatActivity() { val croppedImageResults = arrayListOf() for ((pageNumber, document) in documents.withIndex()) { // crop document photo by using corners - val croppedImage: Bitmap = try { + val croppedImage: Bitmap? = try { ImageUtil().crop( document.originalPhotoFilePath, document.corners @@ -323,6 +333,11 @@ class DocumentScannerActivity : AppCompatActivity() { return } + if (croppedImage == null) { + finishIntentWithError("Result of cropping is null") + return + } + // delete original document photo File(document.originalPhotoFilePath).delete() diff --git a/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/utils/ImageUtil.kt b/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/utils/ImageUtil.kt index 6af20ee..ef69f3d 100644 --- a/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/utils/ImageUtil.kt +++ b/android/src/main/kotlin/biz/cunning/cunning_document_scanner/fallback/utils/ImageUtil.kt @@ -15,16 +15,16 @@ import kotlin.math.sqrt class ImageUtil { - fun getImageFromFilePath(filePath: String): Bitmap { + fun getImageFromFilePath(filePath: String): Bitmap? { val rotation = getRotationDegrees(filePath) - var bitmap = BitmapFactory.decodeFile(filePath) + val bitmap = BitmapFactory.decodeFile(filePath) ?: return null - // Correct image rotation - if (rotation != 0) { + return if (rotation != 0) { val matrix = Matrix().apply { postRotate(rotation.toFloat()) } - bitmap = Bitmap.createBitmap(bitmap!!, 0, 0, bitmap.width, bitmap.height, matrix, true) + Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) + } else { + bitmap } - return bitmap!! } private fun getRotationDegrees(filePath: String): Int { @@ -41,8 +41,8 @@ class ImageUtil { } - fun crop(photoFilePath: String, corners: Quad): Bitmap { - val bitmap = getImageFromFilePath(photoFilePath) + fun crop(photoFilePath: String, corners: Quad): Bitmap? { + val bitmap = getImageFromFilePath(photoFilePath) ?: return null // Convert Quad corners to a float array manually val src = floatArrayOf(