Reputation: 177
I try to code a barcode scanner with Jetpack Compose and Google ML Kit. I use ImageAnalysis with the STRATEGY_KEEP_ONLY_LATEST and call a class BarCodeAnalyzer who initialize and create the barcodeScanner.
But when I scan a barcode, my code detect two time the same barcode and open two screens.
So how can I pause scan ? Or stop the imageAnalysis when I found a barcode ?
AndroidView
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()
)
BarCodeAnalyzer
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()
}
}
}
}
Thanks.
Upvotes: 5
Views: 1405
Reputation: 177
I found a solution, in my BarCodeAnalyzer I created a variable firstCall initialize at true then where a barcode was founded I pass firstCall to false like this :
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)
}
}
}
}
...
}
Upvotes: 2