【问题标题】:Firebase Barcode scanner using Jetpack compose not working使用 Jetpack compose 的 Firebase 条码扫描仪无法正常工作
【发布时间】:2021-10-18 15:10:00
【问题描述】:

尝试将条形码扫描仪迁移到 Jetpack compose 并将相机和 ML Kit 依赖项更新到最新版本。

当前正确显示相机视图,但未扫描条形码。
ImageAnalysis 分析器只运行一次。

代码

@Composable
fun CameraPreview(
    data: CameraPreviewData,
) {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current

    AndroidView(
        modifier = Modifier
            .fillMaxSize(),
        factory = { AndroidViewContext ->
            PreviewView(AndroidViewContext).apply {
                this.scaleType = PreviewView.ScaleType.FILL_CENTER
                layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
                // Preview is incorrectly scaled in Compose on some devices without this
                implementationMode = PreviewView.ImplementationMode.COMPATIBLE
            }
        },
        update = { previewView ->
            val cameraSelector: CameraSelector = CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                .build()
            val cameraExecutor: ExecutorService = Executors.newSingleThreadExecutor()
            val cameraProviderFuture: ListenableFuture<ProcessCameraProvider> =
                ProcessCameraProvider.getInstance(context)

            cameraProviderFuture.addListener({
                val preview: Preview = Preview.Builder()
                    .build()
                    .also {
                        // Attach the viewfinder's surface provider to preview use case
                        it.setSurfaceProvider(previewView.surfaceProvider)
                    }
                val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
                val barcodeAnalyser = BarcodeAnalyser { barcodes ->
                    barcodes.forEach { barcode ->
                        barcode.rawValue?.let { barcodeValue ->
                            logError("Barcode value detected: ${barcodeValue}.")
                            // Other handling code
                        }
                    }
                }
                val imageAnalysis: ImageAnalysis = ImageAnalysis.Builder()
                    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                    .build()
                    .also {
                        it.setAnalyzer(cameraExecutor, barcodeAnalyser)
                    }

                try {
                    cameraProvider.unbindAll()
                    cameraProvider.bindToLifecycle(
                        lifecycleOwner,
                        cameraSelector,
                        preview,
                        imageAnalysis
                    )
                } catch (exception: Exception) {
                    logError("Use case binding failed with exception : $exception")
                }
            }, ContextCompat.getMainExecutor(context))
        },
    )
}

条码分析仪

class BarcodeAnalyser(
    private val onBarcodesDetected: (barcodes: List<Barcode>) -> Unit,
) : ImageAnalysis.Analyzer {
    private var lastAnalyzedTimestamp = 0L

    override fun analyze(
        imageProxy: ImageProxy,
    ) {
        logError("Inside analyze")
        val currentTimestamp = System.currentTimeMillis()
        if (currentTimestamp - lastAnalyzedTimestamp >= TimeUnit.SECONDS.toMillis(1)) {

            imageProxy.image?.let { imageToAnalyze ->
                val options = BarcodeScannerOptions.Builder()
                    .setBarcodeFormats(Barcode.FORMAT_ALL_FORMATS)
                    .build()
                val barcodeScanner = BarcodeScanning.getClient(options)
                val imageToProcess =
                    InputImage.fromMediaImage(imageToAnalyze, imageProxy.imageInfo.rotationDegrees)

                barcodeScanner.process(imageToProcess)
                    .addOnSuccessListener { barcodes ->
                        if (barcodes.isNotEmpty()) {
                            logError("Scanned: $barcodes")
                            onBarcodesDetected(barcodes)
                            imageProxy.close()
                        } else {
                            logError("No barcode scanned")
                        }
                    }
                    .addOnFailureListener { exception ->
                        logError("BarcodeAnalyser: Something went wrong with exception: $exception")
                        imageProxy.close()
                    }
            }
            lastAnalyzedTimestamp = currentTimestamp
        }
    }
}

参考文献

【问题讨论】:

  • 只有在出现错误或找到代码时才调用imageProxy.close()。但是,如果一切正常并且框架中没有任何代码,条形码扫描器也会调用addOnSuccessListener 回调。在您关闭代理之前,分析器不会提供新帧
  • 谢谢@AdrianK,它成功了:)

标签: android barcode-scanner android-jetpack-compose firebase-mlkit android-camerax


【解决方案1】:

感谢阿德里安的评论。

在进行以下更改后它工作了。

条码分析仪

  1. addOnSuccessListeneraddOnFailureListener 中删除了imageProxy.close()。添加到addOnCompleteListener
  2. 在 else 条件下也添加了 imageProxy.close()
class BarcodeAnalyser(
    private val onBarcodesDetected: (barcodes: List<Barcode>) -> Unit,
) : ImageAnalysis.Analyzer {
    private var lastAnalyzedTimestamp = 0L

    override fun analyze(
        imageProxy: ImageProxy,
    ) {
        logError("Inside analyze")
        val currentTimestamp = System.currentTimeMillis()
        if (currentTimestamp - lastAnalyzedTimestamp >= TimeUnit.SECONDS.toMillis(1)) {

            imageProxy.image?.let { imageToAnalyze ->
                // ...Same code

                barcodeScanner.process(imageToProcess)
                    .addOnSuccessListener { barcodes ->
                        if (barcodes.isNotEmpty()) {
                            logError("Scanned: $barcodes")
                            onBarcodesDetected(barcodes)
                            // imageProxy.close()
                        } else {
                            logError("No barcode scanned")
                        }
                    }
                    .addOnFailureListener { exception ->
                        logError("BarcodeAnalyser: Something went wrong with exception: $exception")
                        // imageProxy.close()
                    }
                    .addOnCompleteListener {
                        imageProxy.close()
                    }
            }
            lastAnalyzedTimestamp = currentTimestamp
        } else {
            imageProxy.close()
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多