如何将条码扫描器限制为一次?

Gon*_*n3s 5 kotlin android-jetpack-compose google-mlkit

我尝试使用 Jetpack Compose 和 Google ML Kit 编写条形码扫描仪代码。我将 ImageAnalysis 与 STRATEGY_KEEP_ONLY_LATEST 一起使用,并调用 BarCodeAnalyzer 类来初始化和创建条形码扫描仪。

但是当我扫描条形码时,我的代码检测到两次相同的条形码并打开两个屏幕。

那么如何暂停扫描呢?或者当我发现条形码时停止图像分析?

Android视图

AndroidView(
    factory = { context ->
        val previewView = PreviewView(context)
        val preview = Preview.Builder().build()
        val selector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()
        preview.setSurfaceProvider(previewView.surfaceProvider)
        val imageAnalysis = ImageAnalysis.Builder()
            .setTargetResolution(
                Size(
                    previewView.width,
                    previewView.height
                )
            )
            .setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST)
            .build()
        imageAnalysis.setAnalyzer(
            ContextCompat.getMainExecutor(context),
            BarCodeAnalyzer { result ->
                code = result
                navController.navigate(
                    Screen.FormProduct.route + "?barcode=$code"
                )
            }
        )

        try {
            cameraProviderFuture.get().bindToLifecycle(
                lifecycleOwner,
                selector,
                preview,
                imageAnalysis
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
        previewView
    },
    modifier = Modifier.fillMaxSize()
)
Run Code Online (Sandbox Code Playgroud)

条码分析仪

class BarCodeAnalyzer(
    private val onBarCodeScanned: (String) -> Unit,
) : ImageAnalysis.Analyzer {

    var currentTimestamp: Long = 0

    @SuppressLint("UnsafeOptInUsageError")
    override fun analyze(imageProxy: ImageProxy) {
        currentTimestamp = System.currentTimeMillis()
        val options = BarcodeScannerOptions.Builder()
            .setBarcodeFormats(
                Barcode.FORMAT_EAN_13,
                Barcode.FORMAT_EAN_8
            )
            .build()

        val image = imageProxy.image

        if (image != null) {
            val inputImage = InputImage.fromMediaImage(image, imageProxy.imageInfo.rotationDegrees)

            val scanner = BarcodeScanning.getClient(options)

            scanner.process(inputImage)
                .addOnSuccessListener { barcodes ->
                    if (barcodes.isNotEmpty()) {
                        barcodes.firstOrNull()?.rawValue?.let { barcode ->
                            Log.i(TAG, "Barcode : $barcode")
                            onBarCodeScanned(barcode)
                        }
                    }
                }
                .addOnCompleteListener {
                    imageProxy.close()
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢。

Gon*_*n3s 2

我找到了一个解决方案,在我的 BarCodeAnalyzer 中,我创建了一个变量firstCall,在 true 处初始化,然后在创建条形码的地方,我将firstCall 传递给 false,如下所示:

class BarCodeAnalyzer(
    private val onBarCodeScanned: (String) -> Unit,
) : ImageAnalysis.Analyzer {

    private var firstCall = true

    ...

    scanner.process(inputImage)
        .addOnSuccessListener { barcodes ->
             if (barcodes.isNotEmpty()) {
                 if (firstCall) {
                      firstCall = false
                       barcodes.firstOrNull()?.rawValue?.let { barcode ->
                       onBarCodeScanned(barcode)
                 }
             }
         }
    }

   ...
}

Run Code Online (Sandbox Code Playgroud)