From 0dc5b05c4367c9ea9b47516004a28b4abb45a25a Mon Sep 17 00:00:00 2001 From: Abhijeet Shukla Date: Mon, 3 Feb 2025 11:33:48 +0530 Subject: [PATCH] feat: add gallery button on qr to pick images --- quickie/src/main/AndroidManifest.xml | 3 +- .../g00fy2/quickie/QRScannerActivity.kt | 69 +++++++++++++++++++ .../quickie_rounded_rectangle_button.xml | 14 ++++ .../res/layout/quickie_scanner_activity.xml | 11 +++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 quickie/src/main/res/drawable/quickie_rounded_rectangle_button.xml diff --git a/quickie/src/main/AndroidManifest.xml b/quickie/src/main/AndroidManifest.xml index cf62fb9d..242cb9ea 100644 --- a/quickie/src/main/AndroidManifest.xml +++ b/quickie/src/main/AndroidManifest.xml @@ -7,7 +7,8 @@ android:required="false"/> - + + + uri?.let { analyzeImageFromGallery(it) } + } internal var errorDialog: Dialog? = null set(value) { field = value @@ -68,6 +77,7 @@ internal class QRScannerActivity : AppCompatActivity() { setupEdgeToEdgeUI() applyScannerConfig() + setupGalleryButton() analysisExecutor = Executors.newSingleThreadExecutor() @@ -81,6 +91,64 @@ internal class QRScannerActivity : AppCompatActivity() { } } + private fun setupGalleryButton() { + binding.selectFromGalleryButton.setOnClickListener { + launchGalleryPicker() + } + } + private val storagePermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> + if (granted) { + galleryLauncher.launch(IMAGE_MIME_TYPE) + } else { + onFailure(Exception("Storage permission required to select images")) + } + } + private fun launchGalleryPicker() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED) { + galleryLauncher.launch(IMAGE_MIME_TYPE) + } else { + storagePermissionLauncher.launch(Manifest.permission.READ_MEDIA_IMAGES) + } + } else { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + galleryLauncher.launch(IMAGE_MIME_TYPE) + } else { + storagePermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) + } + } + } + + private fun analyzeImageFromGallery(imageUri: Uri) { + try { + val image = InputImage.fromFilePath(this, imageUri) + val options = BarcodeScannerOptions.Builder() + .setBarcodeFormats(barcodeFormats.sum()) + .build() + + val scanner = BarcodeScanning.getClient(options) + + binding.overlayView.isLoading = true + + scanner.process(image) + .addOnSuccessListener { barcodes -> + binding.overlayView.isLoading = false + if (barcodes.isNullOrEmpty()) { + onFailure(Exception("No QR code found in the image")) + } else { + onSuccess(barcodes.first()) + } + } + .addOnFailureListener { e -> + binding.overlayView.isLoading = false + onFailure(e) + } + } catch (e: Exception) { + binding.overlayView.isLoading = false + onFailure(e) + } + } + override fun onDestroy() { super.onDestroy() analysisExecutor.shutdown() @@ -216,6 +284,7 @@ internal class QRScannerActivity : AppCompatActivity() { const val EXTRA_RESULT_TYPE = "quickie-type" const val EXTRA_RESULT_PARCELABLE = "quickie-parcelable" const val EXTRA_RESULT_EXCEPTION = "quickie-exception" + const val IMAGE_MIME_TYPE="image/*" const val RESULT_MISSING_PERMISSION = RESULT_FIRST_USER + 1 const val RESULT_ERROR = RESULT_FIRST_USER + 2 } diff --git a/quickie/src/main/res/drawable/quickie_rounded_rectangle_button.xml b/quickie/src/main/res/drawable/quickie_rounded_rectangle_button.xml new file mode 100644 index 00000000..d2cc4b54 --- /dev/null +++ b/quickie/src/main/res/drawable/quickie_rounded_rectangle_button.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quickie/src/main/res/layout/quickie_scanner_activity.xml b/quickie/src/main/res/layout/quickie_scanner_activity.xml index 9b379f8d..85a3260d 100644 --- a/quickie/src/main/res/layout/quickie_scanner_activity.xml +++ b/quickie/src/main/res/layout/quickie_scanner_activity.xml @@ -19,4 +19,15 @@ android:visibility="invisible" tools:visibility="visible" /> +