Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Zxing Library with Jetpack compose

I am trying to implement qr scanner using zxing library. For this, i have added a button on screen, and on click of it, i am launching scanner as below

Button(
        onClick = {
            val intentIntegrator = IntentIntegrator(context)
            intentIntegrator.setPrompt(QrScanLabel)
            intentIntegrator.setOrientationLocked(true)
            intentIntegrator.initiateScan()
        },
        modifier = Modifier
            .fillMaxWidth()
    ) {
        Text(
            text = QrScanLabel
        )
    }

but, it launches an intent, which expects onActivityResult method to get back the results. And Jetpack compose uses rememberLauncherForActivityResult like below

val intentLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartIntentSenderForResult()
    ) {
        if (it.resultCode != RESULT_OK) {
            return@rememberLauncherForActivityResult
        }
        ...
    }

but how do we integrate both things together here?

like image 354
Bharat Kumar Avatar asked Mar 02 '26 10:03

Bharat Kumar


2 Answers

Since zxing-android-embedded:4.3.0 there is a ScanContract, which can be used directly from Compose:

val scanLauncher = rememberLauncherForActivityResult(
    contract = ScanContract(),
    onResult = { result -> Log.i(TAG, "scanned code: ${result.contents}") }
)

Button(onClick = { scanLauncher.launch(ScanOptions()) }) {
    Text(text = "Scan barcode")
}
like image 123
gmk57 Avatar answered Mar 06 '26 04:03

gmk57


I make a provisional solution with same library: Gradle dependencies:

implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
implementation 'com.google.zxing:core:3.4.0'

My new Screen with jetpack compose and camera capture, that works for my app:

@Composable
fun AdminClubMembershipScanScreen(navController: NavHostController) {
    val context = LocalContext.current
    var scanFlag by remember {
        mutableStateOf(false)
    }

    val compoundBarcodeView = remember {
        CompoundBarcodeView(context).apply {
            val capture = CaptureManager(context as Activity, this)
            capture.initializeFromIntent(context.intent, null)
            this.setStatusText("")
            capture.decode()
            this.decodeContinuous { result ->
                if(scanFlag){
                    return@decodeContinuous
                }
                scanFlag = true
                result.text?.let { barCodeOrQr->
                    //Do something and when you finish this something
                    //put scanFlag = false to scan another item
                    scanFlag = false
                }
                //If you don't put this scanFlag = false, it will never work again.
                //you can put a delay over 2 seconds and then scanFlag = false to prevent multiple scanning 
                
            }
        }
    }

    AndroidView(
        modifier = Modifier,
        factory = { compoundBarcodeView },
    )
}
like image 34
Jose Pose S Avatar answered Mar 06 '26 05:03

Jose Pose S



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!