diff --git a/CHANGELOG.md b/CHANGELOG.md index 4723e9d..a0c8579 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 The changes documented here do not include those from the original repository. +## [2.0.0] + +### 2025-08-22 + +**BREAKING CHANGE:** The signature of `handleActivityResult` has changed - the onSuccess now returns `OSBARCScanResult` instead of just a string with the scanned code. + +- Add **hint** parameter to scan for specific barcode formats +- Return the format of the scanned code inside the scan result. + ## [1.2.1] ### 20205-08-18 diff --git a/docs/README.md b/docs/README.md index cb115bb..8eb894c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -46,7 +46,7 @@ In your app-level gradle file, import the OSBarcodeLib library like so: ```gradle dependencies { - implementation("com.github.outsystems:osbarcode-android:1.0.0@aar") + implementation("com.github.outsystems:osbarcode-android:2.0.0@aar") } ``` @@ -72,7 +72,7 @@ A method that triggers the barcode reader/scanner, opening a new activity with t - **scanOrientation**: An integer indicating which scan orientation to use - portrait, landscape, or adaptive. - **scanButton**: A boolean that will display a scan button on the barcode reader. If true, scanning will only be triggered when pressing the button instead of automatically when framing the barcode. A second click on the button disables scannning. - **scanText**: A string that contains the text to be displayed on the scan button. It will only be shown if **scanButton** is set to true. - - **hint**: An integer that holds a hint to what type of barcode to look for. **This parameter isn't being used yet**. + - **hint**: An integer that holds a hint to what type of barcode to look for. - **androidScanningLibrary**: A string which determines what barcode library to use - ML Kit or ZXing. #### Usage @@ -89,7 +89,7 @@ fun handleActivityResult( requestCode: Int, resultCode: Int, intent: Intent?, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: (OSBARCError) -> Unit ) ``` diff --git a/pom.xml b/pom.xml index 4d0a0cd..0de09bf 100644 --- a/pom.xml +++ b/pom.xml @@ -7,5 +7,5 @@ 4.0.0 io.ionic.libs ionbarcode-android - 1.2.1 + 2.0.0 diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCBarcodeAnalyzer.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCBarcodeAnalyzer.kt index f238a1b..9b49da3 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCBarcodeAnalyzer.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCBarcodeAnalyzer.kt @@ -6,6 +6,7 @@ import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageProxy import com.outsystems.plugins.barcode.controller.helper.OSBARCImageHelperInterface import com.outsystems.plugins.barcode.model.OSBARCError +import com.outsystems.plugins.barcode.model.OSBARCScanResult import com.outsystems.plugins.barcode.view.ui.theme.SizeRatioHeight import com.outsystems.plugins.barcode.view.ui.theme.SizeRatioWidth import java.lang.Exception @@ -17,7 +18,7 @@ import java.lang.Exception class OSBARCBarcodeAnalyzer( private val scanLibrary: OSBARCScanLibraryInterface, private val imageHelper: OSBARCImageHelperInterface, - private val onBarcodeScanned: (String) -> Unit, + private val onBarcodeScanned: (OSBARCScanResult) -> Unit, private val onScanningError: (OSBARCError) -> Unit ): ImageAnalysis.Analyzer { diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCController.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCController.kt index cff4957..81aaefe 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCController.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCController.kt @@ -3,8 +3,10 @@ package com.outsystems.plugins.barcode.controller import android.app.Activity import android.content.Intent import android.util.Log +import androidx.core.content.IntentCompat import com.outsystems.plugins.barcode.model.OSBARCError import com.outsystems.plugins.barcode.model.OSBARCScanParameters +import com.outsystems.plugins.barcode.model.OSBARCScanResult import com.outsystems.plugins.barcode.view.OSBARCScannerActivity /** @@ -46,15 +48,17 @@ class OSBARCController { requestCode: Int, resultCode: Int, intent: Intent?, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: (OSBARCError) -> Unit ) { when (requestCode) { SCAN_REQUEST_CODE -> { when (resultCode) { Activity.RESULT_OK -> { - val result = intent?.extras?.getString(SCAN_RESULT) - if (result.isNullOrEmpty()) { + val result: OSBARCScanResult? = intent?.let { + IntentCompat.getSerializableExtra(intent, SCAN_RESULT, OSBARCScanResult::class.java) + } + if (result == null || result.text.isEmpty()) { onError(OSBARCError.SCANNING_GENERAL_ERROR) return } diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCMLKitWrapper.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCMLKitWrapper.kt index 6fa7a5e..a3ae3e1 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCMLKitWrapper.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCMLKitWrapper.kt @@ -3,8 +3,11 @@ package com.outsystems.plugins.barcode.controller import android.graphics.Bitmap import android.util.Log import androidx.camera.core.ImageProxy +import com.google.mlkit.vision.barcode.common.Barcode import com.outsystems.plugins.barcode.controller.helper.OSBARCMLKitHelperInterface import com.outsystems.plugins.barcode.model.OSBARCError +import com.outsystems.plugins.barcode.model.OSBARCScanResult +import com.outsystems.plugins.barcode.model.OSBARCScannerHint /** * Wrapper class that implements the OSBARCScanLibraryInterface @@ -25,18 +28,20 @@ class OSBARCMLKitWrapper(private val helper: OSBARCMLKitHelperInterface): OSBARC override fun scanBarcode( imageProxy: ImageProxy, imageBitmap: Bitmap, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: (OSBARCError) -> Unit ) { try { helper.decodeImage(imageProxy, imageBitmap, { barcodes -> - var result: String? = null - if (barcodes.isNotEmpty()) { - result = barcodes.first().rawValue - } - if (!result.isNullOrEmpty()) { - onSuccess(result) + barcodes.firstOrNull()?.let { barcode -> + val result = OSBARCScanResult( + text = barcode.rawValue ?: "", + format = barcode.format.toOSBARCScannerHint() + ) + if (result.text.isNotEmpty()) { + onSuccess(result) + } } }, { @@ -49,4 +54,22 @@ class OSBARCMLKitWrapper(private val helper: OSBARCMLKitHelperInterface): OSBARC } } + private fun Int?.toOSBARCScannerHint(): OSBARCScannerHint = when (this) { + Barcode.FORMAT_QR_CODE -> OSBARCScannerHint.QR_CODE + Barcode.FORMAT_AZTEC -> OSBARCScannerHint.AZTEC + Barcode.FORMAT_CODABAR -> OSBARCScannerHint.CODABAR + Barcode.FORMAT_CODE_39 -> OSBARCScannerHint.CODE_39 + Barcode.FORMAT_CODE_93 -> OSBARCScannerHint.CODE_93 + Barcode.FORMAT_CODE_128 -> OSBARCScannerHint.CODE_128 + Barcode.FORMAT_DATA_MATRIX -> OSBARCScannerHint.DATA_MATRIX + Barcode.FORMAT_ITF -> OSBARCScannerHint.ITF + Barcode.FORMAT_EAN_13 -> OSBARCScannerHint.EAN_13 + Barcode.FORMAT_EAN_8 -> OSBARCScannerHint.EAN_8 + Barcode.FORMAT_PDF417 -> OSBARCScannerHint.PDF_417 + Barcode.FORMAT_UPC_A -> OSBARCScannerHint.UPC_A + Barcode.FORMAT_UPC_E -> OSBARCScannerHint.UPC_E + + // Formats not supported by ML Kit → map to UNKNOWN + else -> OSBARCScannerHint.UNKNOWN + } } \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCScanLibraryInterface.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCScanLibraryInterface.kt index 6b2bd15..a5524b0 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCScanLibraryInterface.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCScanLibraryInterface.kt @@ -3,6 +3,7 @@ package com.outsystems.plugins.barcode.controller import android.graphics.Bitmap import androidx.camera.core.ImageProxy import com.outsystems.plugins.barcode.model.OSBARCError +import com.outsystems.plugins.barcode.model.OSBARCScanResult /** * Interface that provides the signature of the scanBarcode method @@ -11,7 +12,7 @@ fun interface OSBARCScanLibraryInterface { fun scanBarcode( imageProxy: ImageProxy, imageBitmap: Bitmap, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: (OSBARCError) -> Unit ) } \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCZXingWrapper.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCZXingWrapper.kt index 9fe2a19..9b738a3 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCZXingWrapper.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/OSBARCZXingWrapper.kt @@ -5,6 +5,7 @@ import android.util.Log import androidx.camera.core.ImageProxy import com.outsystems.plugins.barcode.controller.helper.OSBARCZXingHelperInterface import com.outsystems.plugins.barcode.model.OSBARCError +import com.outsystems.plugins.barcode.model.OSBARCScanResult /** * Wrapper class that implements the OSBARCScanLibraryInterface @@ -25,7 +26,7 @@ class OSBARCZXingWrapper(private val helper: OSBARCZXingHelperInterface) : OSBAR override fun scanBarcode( imageProxy: ImageProxy, imageBitmap: Bitmap, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: (OSBARCError) -> Unit ) { try { diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCMLKitHelper.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCMLKitHelper.kt index 6287665..b5b1709 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCMLKitHelper.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCMLKitHelper.kt @@ -7,21 +7,51 @@ import com.google.mlkit.vision.barcode.BarcodeScannerOptions import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.common.InputImage +import com.outsystems.plugins.barcode.model.OSBARCScannerHint +import org.jetbrains.annotations.VisibleForTesting /** * Helper class that implements the OSBARCMLKitHelperInterface * to scan an image using the ML Kit library. * It encapsulates all the code related with the ML Kit library. */ -class OSBARCMLKitHelper: OSBARCMLKitHelperInterface { +class OSBARCMLKitHelper(private val hint: OSBARCScannerHint?): OSBARCMLKitHelperInterface { companion object { private const val LOG_TAG = "OSBARCMLKitHelper" + + @VisibleForTesting + internal fun OSBARCScannerHint?.toMLKitBarcodeFormat(): Int? = when (this) { + OSBARCScannerHint.QR_CODE -> Barcode.FORMAT_QR_CODE + OSBARCScannerHint.AZTEC -> Barcode.FORMAT_AZTEC + OSBARCScannerHint.CODABAR -> Barcode.FORMAT_CODABAR + OSBARCScannerHint.CODE_39 -> Barcode.FORMAT_CODE_39 + OSBARCScannerHint.CODE_93 -> Barcode.FORMAT_CODE_93 + OSBARCScannerHint.CODE_128 -> Barcode.FORMAT_CODE_128 + OSBARCScannerHint.DATA_MATRIX -> Barcode.FORMAT_DATA_MATRIX + OSBARCScannerHint.MAXICODE -> null // not supported by ML Kit + OSBARCScannerHint.ITF -> Barcode.FORMAT_ITF + OSBARCScannerHint.EAN_13 -> Barcode.FORMAT_EAN_13 + OSBARCScannerHint.EAN_8 -> Barcode.FORMAT_EAN_8 + OSBARCScannerHint.PDF_417 -> Barcode.FORMAT_PDF417 + OSBARCScannerHint.RSS_14 -> null // not supported by ML Kit + OSBARCScannerHint.RSS_EXPANDED -> null // not supported by ML Kit + OSBARCScannerHint.UPC_A -> Barcode.FORMAT_UPC_A + OSBARCScannerHint.UPC_E -> Barcode.FORMAT_UPC_E + OSBARCScannerHint.UPC_EAN_EXTENSION -> null // not supported by ML Kit + OSBARCScannerHint.UNKNOWN -> null + null -> null + } } private val scanner by lazy { - val options = BarcodeScannerOptions.Builder() - .enableAllPotentialBarcodes() - .build() + val options = BarcodeScannerOptions.Builder().apply { + val format = hint.toMLKitBarcodeFormat() + if (format != null) { + setBarcodeFormats(format) + } else { + enableAllPotentialBarcodes() + } + }.build() BarcodeScanning.getClient(options) } @@ -51,5 +81,4 @@ class OSBARCMLKitHelper: OSBARCMLKitHelperInterface { onError() } } - } \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelper.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelper.kt index f95e38e..45927db 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelper.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelper.kt @@ -3,23 +3,38 @@ package com.outsystems.plugins.barcode.controller.helper import android.graphics.Bitmap import android.graphics.Matrix import android.util.Log +import com.google.zxing.BarcodeFormat import com.google.zxing.BinaryBitmap +import com.google.zxing.DecodeHintType import com.google.zxing.MultiFormatReader import com.google.zxing.NotFoundException import com.google.zxing.RGBLuminanceSource import com.google.zxing.common.HybridBinarizer +import com.outsystems.plugins.barcode.model.OSBARCScanResult +import com.outsystems.plugins.barcode.model.OSBARCScannerHint /** * Helper class that implements the OSBARCZXingHelperInterface * to scan an image using the ZXing library. * It encapsulates all the code related with the ZXing library. */ -class OSBARCZXingHelper: OSBARCZXingHelperInterface { +class OSBARCZXingHelper(private val hint: OSBARCScannerHint?): OSBARCZXingHelperInterface { companion object { private const val LOG_TAG = "OSBARCZXingHelper" } + private val reader: MultiFormatReader by lazy { + val format = hint.toZXingBarcodeFormat() + MultiFormatReader().apply { + if (format != null) { + setHints( + mapOf(DecodeHintType.POSSIBLE_FORMATS to setOf(format)) + ) + } + } + } + /** * Rotates a bitmap, provided with the rotation degrees. * @param bitmap - Bitmap object to rotate @@ -51,14 +66,19 @@ class OSBARCZXingHelper: OSBARCZXingHelperInterface { */ override fun decodeImage( pixels: IntArray, width: Int, height: Int, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: () -> Unit ) { try { val source = RGBLuminanceSource(width, height, pixels) val binaryBitmap = BinaryBitmap(HybridBinarizer(source)) - val result = MultiFormatReader().decodeWithState(binaryBitmap) - onSuccess(result.text) + val result = reader.decodeWithState(binaryBitmap) + onSuccess( + OSBARCScanResult( + text = result.text, + format = result.barcodeFormat.toOSBARCScannerHint() + ) + ) } catch (e: NotFoundException) { // keep trying, no barcode was found in this camera frame e.message?.let { Log.d(LOG_TAG, it) } @@ -66,7 +86,49 @@ class OSBARCZXingHelper: OSBARCZXingHelperInterface { e.message?.let { Log.e(LOG_TAG, it) } onError() } + } + private fun OSBARCScannerHint?.toZXingBarcodeFormat(): BarcodeFormat? = when (this) { + OSBARCScannerHint.QR_CODE -> BarcodeFormat.QR_CODE + OSBARCScannerHint.AZTEC -> BarcodeFormat.AZTEC + OSBARCScannerHint.CODABAR -> BarcodeFormat.CODABAR + OSBARCScannerHint.CODE_39 -> BarcodeFormat.CODE_39 + OSBARCScannerHint.CODE_93 -> BarcodeFormat.CODE_93 + OSBARCScannerHint.CODE_128 -> BarcodeFormat.CODE_128 + OSBARCScannerHint.DATA_MATRIX -> BarcodeFormat.DATA_MATRIX + OSBARCScannerHint.MAXICODE -> BarcodeFormat.MAXICODE + OSBARCScannerHint.ITF -> BarcodeFormat.ITF + OSBARCScannerHint.EAN_13 -> BarcodeFormat.EAN_13 + OSBARCScannerHint.EAN_8 -> BarcodeFormat.EAN_8 + OSBARCScannerHint.PDF_417 -> BarcodeFormat.PDF_417 + OSBARCScannerHint.RSS_14 -> BarcodeFormat.RSS_14 + OSBARCScannerHint.RSS_EXPANDED -> BarcodeFormat.RSS_EXPANDED + OSBARCScannerHint.UPC_A -> BarcodeFormat.UPC_A + OSBARCScannerHint.UPC_E -> BarcodeFormat.UPC_E + OSBARCScannerHint.UPC_EAN_EXTENSION -> BarcodeFormat.UPC_EAN_EXTENSION + OSBARCScannerHint.UNKNOWN -> null + null -> null } + private fun BarcodeFormat?.toOSBARCScannerHint(): OSBARCScannerHint = when (this) { + BarcodeFormat.QR_CODE -> OSBARCScannerHint.QR_CODE + BarcodeFormat.AZTEC -> OSBARCScannerHint.AZTEC + BarcodeFormat.CODABAR -> OSBARCScannerHint.CODABAR + BarcodeFormat.CODE_39 -> OSBARCScannerHint.CODE_39 + BarcodeFormat.CODE_93 -> OSBARCScannerHint.CODE_93 + BarcodeFormat.CODE_128 -> OSBARCScannerHint.CODE_128 + BarcodeFormat.DATA_MATRIX -> OSBARCScannerHint.DATA_MATRIX + BarcodeFormat.MAXICODE -> OSBARCScannerHint.MAXICODE + BarcodeFormat.ITF -> OSBARCScannerHint.ITF + BarcodeFormat.EAN_13 -> OSBARCScannerHint.EAN_13 + BarcodeFormat.EAN_8 -> OSBARCScannerHint.EAN_8 + BarcodeFormat.PDF_417 -> OSBARCScannerHint.PDF_417 + BarcodeFormat.RSS_14 -> OSBARCScannerHint.RSS_14 + BarcodeFormat.RSS_EXPANDED -> OSBARCScannerHint.RSS_EXPANDED + BarcodeFormat.UPC_A -> OSBARCScannerHint.UPC_A + BarcodeFormat.UPC_E -> OSBARCScannerHint.UPC_E + BarcodeFormat.UPC_EAN_EXTENSION -> OSBARCScannerHint.UPC_EAN_EXTENSION + + else -> OSBARCScannerHint.UNKNOWN + } } \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelperInterface.kt b/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelperInterface.kt index a482d79..3fad533 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelperInterface.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/controller/helper/OSBARCZXingHelperInterface.kt @@ -1,6 +1,7 @@ package com.outsystems.plugins.barcode.controller.helper import android.graphics.Bitmap +import com.outsystems.plugins.barcode.model.OSBARCScanResult /** * Interface that provides the signature of the type's methods. @@ -11,7 +12,7 @@ interface OSBARCZXingHelperInterface { pixels: IntArray, width: Int, height: Int, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: () -> Unit ) } \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanParameters.kt b/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanParameters.kt index 502efb2..aaee198 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanParameters.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanParameters.kt @@ -12,6 +12,6 @@ data class OSBARCScanParameters( @SerializedName("scanOrientation") val scanOrientation: Int?, @SerializedName("scanButton") val scanButton: Boolean, @SerializedName("scanText") val scanText: String, - @SerializedName("hint") val hint: Int?, + @SerializedName("hint") val hint: OSBARCScannerHint?, @SerializedName("androidScanningLibrary") val androidScanningLibrary: String? ) : Serializable \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanResult.kt b/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanResult.kt new file mode 100644 index 0000000..44abf8e --- /dev/null +++ b/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScanResult.kt @@ -0,0 +1,8 @@ +package com.outsystems.plugins.barcode.model + +import java.io.Serializable + +data class OSBARCScanResult( + val text: String, + val format: OSBARCScannerHint = OSBARCScannerHint.UNKNOWN +): Serializable diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScannerHint.kt b/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScannerHint.kt new file mode 100644 index 0000000..37ff388 --- /dev/null +++ b/src/main/kotlin/com/outsystems/plugins/barcode/model/OSBARCScannerHint.kt @@ -0,0 +1,22 @@ +package com.outsystems.plugins.barcode.model + +enum class OSBARCScannerHint { + QR_CODE, + AZTEC, + CODABAR, + CODE_39, + CODE_93, + CODE_128, + DATA_MATRIX, + MAXICODE, + ITF, + EAN_13, + EAN_8, + PDF_417, + RSS_14, + RSS_EXPANDED, + UPC_A, + UPC_E, + UPC_EAN_EXTENSION, + UNKNOWN +} \ No newline at end of file diff --git a/src/main/kotlin/com/outsystems/plugins/barcode/view/OSBARCScannerActivity.kt b/src/main/kotlin/com/outsystems/plugins/barcode/view/OSBARCScannerActivity.kt index a79cf29..ee5f2b4 100644 --- a/src/main/kotlin/com/outsystems/plugins/barcode/view/OSBARCScannerActivity.kt +++ b/src/main/kotlin/com/outsystems/plugins/barcode/view/OSBARCScannerActivity.kt @@ -90,6 +90,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.content.ContextCompat +import androidx.core.content.IntentCompat import androidx.core.view.WindowCompat import androidx.window.layout.WindowMetricsCalculator import com.outsystems.plugins.barcode.R @@ -100,6 +101,7 @@ import com.outsystems.plugins.barcode.controller.helper.OSBARCMLKitHelper import com.outsystems.plugins.barcode.controller.helper.OSBARCZXingHelper import com.outsystems.plugins.barcode.model.OSBARCError import com.outsystems.plugins.barcode.model.OSBARCScanParameters +import com.outsystems.plugins.barcode.model.OSBARCScanResult import com.outsystems.plugins.barcode.view.ui.theme.ActionButtonsDistance import com.outsystems.plugins.barcode.view.ui.theme.BarcodeScannerTheme import com.outsystems.plugins.barcode.view.ui.theme.ButtonsBackgroundGray @@ -166,7 +168,7 @@ class OSBARCScannerActivity : ComponentActivity() { cameraExecutor = Executors.newSingleThreadExecutor() - val parameters = intent.extras?.getSerializable(SCAN_PARAMETERS) as OSBARCScanParameters + val parameters = IntentCompat.getSerializableExtra(intent, SCAN_PARAMETERS, OSBARCScanParameters::class.java)!! // possibly lock orientation, the screen is adaptive by default if (parameters.scanOrientation == ORIENTATION_PORTRAIT) { @@ -183,8 +185,8 @@ class OSBARCScannerActivity : ComponentActivity() { barcodeAnalyzer = OSBARCBarcodeAnalyzer( OSBARCScanLibraryFactory.createScanLibraryWrapper( parameters.androidScanningLibrary ?: "", - OSBARCZXingHelper(), - OSBARCMLKitHelper() + OSBARCZXingHelper(parameters.hint), + OSBARCMLKitHelper(parameters.hint) ), OSBARCImageHelper(), { result -> @@ -920,7 +922,7 @@ class OSBARCScannerActivity : ComponentActivity() { ) == PackageManager.PERMISSION_GRANTED } - private fun processReadSuccess(result: String) { + private fun processReadSuccess(result: OSBARCScanResult) { // we only want to process the scan result if scanning is active if (isScanning) { val resultIntent = Intent() diff --git a/src/test/kotlin/com/outsystems/plugins/barcode/ScanCodeTests.kt b/src/test/kotlin/com/outsystems/plugins/barcode/ScanCodeTests.kt index 2fd2aec..5d366ed 100644 --- a/src/test/kotlin/com/outsystems/plugins/barcode/ScanCodeTests.kt +++ b/src/test/kotlin/com/outsystems/plugins/barcode/ScanCodeTests.kt @@ -7,6 +7,7 @@ import android.media.Image import android.os.Bundle import androidx.camera.core.ImageInfo import androidx.camera.core.ImageProxy +import androidx.core.content.IntentCompat import com.outsystems.plugins.barcode.controller.OSBARCBarcodeAnalyzer import com.outsystems.plugins.barcode.controller.OSBARCController import com.outsystems.plugins.barcode.controller.OSBARCScanLibraryFactory @@ -17,10 +18,15 @@ import com.outsystems.plugins.barcode.mocks.OSBARCZXingHelperMock import com.outsystems.plugins.barcode.mocks.OSBARCScanLibraryMock import com.outsystems.plugins.barcode.model.OSBARCError import com.outsystems.plugins.barcode.model.OSBARCScanParameters +import com.outsystems.plugins.barcode.model.OSBARCScanResult +import com.outsystems.plugins.barcode.model.OSBARCScannerHint +import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.fail import org.junit.Before import org.junit.Test +import org.mockito.Mock +import org.mockito.MockedStatic import org.mockito.Mockito import java.nio.ByteBuffer @@ -34,6 +40,7 @@ class ScanCodeTests { private lateinit var mockByteBuffer: ByteBuffer private lateinit var mockImageInfo: ImageInfo private lateinit var planes: Array + private lateinit var mockIntentCompat: MockedStatic private lateinit var imageHelperMock: OSBARCImageHelperInterface private lateinit var mockBitmap: Bitmap @@ -41,10 +48,10 @@ class ScanCodeTests { companion object { private const val SCAN_REQUEST_CODE = 112 private const val INVALID_REQUEST_CODE = 113 - private const val INVALID_RESULT_CODE = 9 private const val GENERAL_ERROR_CODE = 4 - private const val SCAN_RESULT = "scanResult" - private const val RESULT_CODE = "myCode" + private const val SCAN_RESULT_KEY = "scanResult" + private val SCAN_RESULT = OSBARCScanResult("scanResult", OSBARCScannerHint.ITF) + private val RESULT_CODE = OSBARCScanResult("myCode", OSBARCScannerHint.QR_CODE) } @Before @@ -66,6 +73,12 @@ class ScanCodeTests { imageHelperMock = OSBARCImageHelperMock() mockBitmap = Mockito.mock(Bitmap::class.java) + mockIntentCompat = Mockito.mockStatic(IntentCompat::class.java) + } + + @After + fun after() { + mockIntentCompat.close() } @Test @@ -77,7 +90,7 @@ class ScanCodeTests { 1, false, "", - 1, + OSBARCScannerHint.QR_CODE, "zxing" ) barcodeController.scanCode(mockActivity, parameters) @@ -85,11 +98,15 @@ class ScanCodeTests { @Test fun givenResultOKAndBarcodeValidWhenHandleScanResultThenSuccess() { - Mockito.doReturn(mockBundle).`when`(mockIntent).extras - Mockito.doReturn(RESULT_CODE).`when`(mockBundle).getString(SCAN_RESULT) + mockIntentCompat + .`when` { + IntentCompat.getSerializableExtra(mockIntent, SCAN_RESULT_KEY, OSBARCScanResult::class.java) + } + .thenReturn(RESULT_CODE) val barcodeController = OSBARCController() - barcodeController.handleActivityResult(SCAN_REQUEST_CODE, Activity.RESULT_OK, mockIntent, + barcodeController.handleActivityResult( + SCAN_REQUEST_CODE, Activity.RESULT_OK, mockIntent, { assertEquals(RESULT_CODE, it) }, @@ -131,8 +148,11 @@ class ScanCodeTests { @Test fun givenStringNullWhenHandleScanResultThenGeneralError() { - Mockito.doReturn(mockBundle).`when`(mockIntent).extras - Mockito.doReturn(null).`when`(mockBundle).getString(SCAN_RESULT) + mockIntentCompat + .`when` { + IntentCompat.getSerializableExtra(mockIntent, SCAN_RESULT_KEY, OSBARCScanResult::class.java) + } + .thenReturn(null) val barcodeController = OSBARCController() barcodeController.handleActivityResult(SCAN_REQUEST_CODE, Activity.RESULT_OK, mockIntent, @@ -148,8 +168,11 @@ class ScanCodeTests { @Test fun givenInvalidRequestCodeWhenHandleScanResultThenGeneralError() { - Mockito.doReturn(mockBundle).`when`(mockIntent).extras - Mockito.doReturn(null).`when`(mockBundle).getString(SCAN_RESULT) + mockIntentCompat + .`when` { + IntentCompat.getSerializableExtra(mockIntent, SCAN_RESULT_KEY, OSBARCScanResult::class.java) + } + .thenReturn(null) val barcodeController = OSBARCController() barcodeController.handleActivityResult(INVALID_REQUEST_CODE, Activity.RESULT_OK, mockIntent, @@ -165,8 +188,11 @@ class ScanCodeTests { @Test fun givenInvalidResultCodeWhenHandleScanResultThenGeneralError() { - Mockito.doReturn(mockBundle).`when`(mockIntent).extras - Mockito.doReturn(null).`when`(mockBundle).getString(SCAN_RESULT) + mockIntentCompat + .`when` { + IntentCompat.getSerializableExtra(mockIntent, SCAN_RESULT_KEY, OSBARCScanResult::class.java) + } + .thenReturn(null) val barcodeController = OSBARCController() barcodeController.handleActivityResult(SCAN_REQUEST_CODE, GENERAL_ERROR_CODE, mockIntent, @@ -182,8 +208,11 @@ class ScanCodeTests { @Test fun givenResultOKAndBarcodeEmptyWhenHandleScanResultThenScanningError() { - Mockito.doReturn(mockBundle).`when`(mockIntent).extras - Mockito.doReturn("").`when`(mockBundle).getString(SCAN_RESULT) + mockIntentCompat + .`when` { + IntentCompat.getSerializableExtra(mockIntent, SCAN_RESULT_KEY, OSBARCScanResult::class.java) + } + .thenReturn(OSBARCScanResult("", OSBARCScannerHint.UNKNOWN)) val barcodeController = OSBARCController() barcodeController.handleActivityResult(SCAN_REQUEST_CODE, Activity.RESULT_OK, mockIntent, @@ -576,7 +605,7 @@ class ScanCodeTests { "mlkit", OSBARCZXingHelperMock(), OSBARCMLKitHelperMock().apply { - scanResult = "" + scanResult = SCAN_RESULT.copy(text = "") success = true barcodesEmpty = false } diff --git a/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCMLKitHelperMock.kt b/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCMLKitHelperMock.kt index 7f7bf28..73ca31d 100644 --- a/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCMLKitHelperMock.kt +++ b/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCMLKitHelperMock.kt @@ -3,13 +3,15 @@ package com.outsystems.plugins.barcode.mocks import android.graphics.Bitmap import androidx.camera.core.ImageProxy import com.google.mlkit.vision.barcode.common.Barcode +import com.outsystems.plugins.barcode.controller.helper.OSBARCMLKitHelper.Companion.toMLKitBarcodeFormat import com.outsystems.plugins.barcode.controller.helper.OSBARCMLKitHelperInterface +import com.outsystems.plugins.barcode.model.OSBARCScanResult import org.mockito.Mockito class OSBARCMLKitHelperMock: OSBARCMLKitHelperInterface { var success = true - var scanResult: String? = null + var scanResult: OSBARCScanResult? = null var exception = false var barcodesEmpty = true @@ -27,7 +29,8 @@ class OSBARCMLKitHelperMock: OSBARCMLKitHelperInterface { } if (success) { - Mockito.doReturn(scanResult).`when`(mockBarcode).rawValue + Mockito.doReturn(scanResult?.text).`when`(mockBarcode).rawValue + Mockito.doReturn(scanResult?.format?.toMLKitBarcodeFormat()).`when`(mockBarcode).format onSuccess(mutableListOf(mockBarcode)) } else if (!exception) { diff --git a/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCScanLibraryMock.kt b/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCScanLibraryMock.kt index b1445a0..beee5ce 100644 --- a/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCScanLibraryMock.kt +++ b/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCScanLibraryMock.kt @@ -4,21 +4,23 @@ import android.graphics.Bitmap import androidx.camera.core.ImageProxy import com.outsystems.plugins.barcode.controller.OSBARCScanLibraryInterface import com.outsystems.plugins.barcode.model.OSBARCError +import com.outsystems.plugins.barcode.model.OSBARCScanResult +import com.outsystems.plugins.barcode.model.OSBARCScannerHint class OSBARCScanLibraryMock: OSBARCScanLibraryInterface { - var resultCode = "" + var resultCode = OSBARCScanResult("", OSBARCScannerHint.UNKNOWN) var success = true var exception = false var error: OSBARCError = OSBARCError.SCANNING_GENERAL_ERROR override fun scanBarcode( imageProxy: ImageProxy, imageBitmap: Bitmap, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: (OSBARCError) -> Unit ) { if (success) { - onSuccess("myCode") + onSuccess(OSBARCScanResult("myCode", OSBARCScannerHint.QR_CODE)) } else if (!exception) { onError(error) diff --git a/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCZXingHelperMock.kt b/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCZXingHelperMock.kt index 6b12777..af22e54 100644 --- a/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCZXingHelperMock.kt +++ b/src/test/kotlin/com/outsystems/plugins/barcode/mocks/OSBARCZXingHelperMock.kt @@ -2,11 +2,13 @@ package com.outsystems.plugins.barcode.mocks import android.graphics.Bitmap import com.outsystems.plugins.barcode.controller.helper.OSBARCZXingHelperInterface +import com.outsystems.plugins.barcode.model.OSBARCScanResult +import com.outsystems.plugins.barcode.model.OSBARCScannerHint import org.mockito.Mockito class OSBARCZXingHelperMock: OSBARCZXingHelperInterface { - var scanResult = "" + var scanResult = OSBARCScanResult("", OSBARCScannerHint.UNKNOWN) var success = true var exception = false @@ -18,7 +20,7 @@ class OSBARCZXingHelperMock: OSBARCZXingHelperInterface { pixels: IntArray, width: Int, height: Int, - onSuccess: (String) -> Unit, + onSuccess: (OSBARCScanResult) -> Unit, onError: () -> Unit ) { if (success) {