如何使用ZXING与Jetpack Compose实现二维码扫描及现有代码问题修复
ZXING + Jetpack Compose 二维码扫描器实现方案
现有代码问题排查
- 未绑定
CaptureManager和相机视图的生命周期,缺少onResume/onPause/onDestroy对应回调,导致相机资源无法正常加载、出现泄露,预览不生效 - 未适配动态相机权限申请,Android 6.0及以上系统未授权时相机无法启动
- 同时调用
capture.decode()和decodeContinuous导致解码逻辑冲突,回调重复触发 - 直接在
remember中初始化CompoundBarcodeView,配置变更(如屏幕旋转)时会丢失相机状态,context as Activity的强转也存在崩溃风险
前置配置
- 模块级
build.gradle引入依赖:
dependencies { // ZXING 扫码核心库 implementation 'com.google.zxing:core:3.5.1' // ZXING 安卓视图封装库 implementation 'com.journeyapps:zxing-android-embedded:4.3.0' }
AndroidManifest.xml添加权限声明:
<!-- 相机权限 --> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera.any" android:required="false" />
完整实现代码
@Composable fun AdminClubMembershipScanScreen(navController: NavHostController) { val context = LocalContext.current val activity = LocalContext.current as Activity val lifecycleOwner = LocalLifecycleOwner.current var scanFlag by remember { mutableStateOf(false) } var hasCameraPermission by remember { mutableStateOf(false) } // 相机权限申请器 val cameraPermissionLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), onResult = { granted -> hasCameraPermission = granted } ) // 进入页面先申请权限 LaunchedEffect(key1 = Unit) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { hasCameraPermission = true } else { cameraPermissionLauncher.launch(Manifest.permission.CAMERA) } } if (hasCameraPermission) { val compoundBarcodeView = remember { CompoundBarcodeView(context).apply { setStatusText("") } } val captureManager = remember { CaptureManager(activity, compoundBarcodeView).apply { initializeFromIntent(activity.intent, null) decode() } } // 绑定生命周期回调 DisposableEffect(key1 = lifecycleOwner) { val observer = LifecycleEventObserver { _, event -> when (event) { Lifecycle.Event.ON_RESUME -> { compoundBarcodeView.resume() captureManager.onResume() } Lifecycle.Event.ON_PAUSE -> { compoundBarcodeView.pause() captureManager.onPause() } Lifecycle.Event.ON_DESTROY -> { captureManager.onDestroy() } else -> {} } } lifecycleOwner.lifecycle.addObserver(observer) // 扫码回调 compoundBarcodeView.decodeContinuous { result -> if (scanFlag) return@decodeContinuous scanFlag = true result.text?.let { barCodeOrQr -> // 此处处理扫码结果 // 处理完成后置为false即可重新扫描,可按需加延迟防抖 scanFlag = false } } onDispose { lifecycleOwner.lifecycle.removeObserver(observer) } } AndroidView( modifier = Modifier.fillMaxSize(), factory = { compoundBarcodeView } ) } else { // 权限未授予时的提示页面 Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(text = "请授予相机权限后使用扫码功能") } } }
功能优化说明
- 若需要识别一次后停止扫码,拿到结果后直接调用
compoundBarcodeView.pause()即可,不需要依赖scanFlag控制 - 若需要连续扫码,可在拿到结果后加1~2秒延迟再将
scanFlag置为false,避免同一张二维码被重复识别 - 可自定义
CompoundBarcodeView的扫描框样式、提示文字等属性,适配设计需求
内容的提问来源于stack exchange,提问作者Kyu-Ho Hwang
相关产品推荐
相关产品推荐

