compose 二维码扫描qrcode
扫描预览
@Composable
fun ScannerContent(modifier: Modifier, onScan: (String) -> Unit) {val lifecycleOwner = LocalLifecycleOwner.currentval context = LocalContext.currentvar cameraControl: CameraControl? by remember { mutableStateOf(null) }AndroidView(factory = { ctx ->PreviewView(ctx).apply {scaleType = PreviewView.ScaleType.FILL_CENTER}}, modifier = modifier, update = { previewView ->val cameraExecutor = Executors.newSingleThreadExecutor()val cameraProviderFuture = ProcessCameraProvider.getInstance(context)cameraProviderFuture.addListener({val cameraProvider = cameraProviderFuture.get()val preview = Preview.Builder().build().also {it.setSurfaceProvider(previewView.surfaceProvider)}// 2. 创建 ImageAnalysis 用例(核心分析逻辑)val imageAnalysis = ImageAnalysis.Builder().setImageQueueDepth(1).setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // 仅保留最新帧.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888) // 输出格式.build().apply {setAnalyzer(cameraExecutor, BarcodeAnalyzer(onScan))}val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERAtry {cameraProvider.unbindAll()val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalysis)cameraControl = camera.cameraControl} catch (e: Exception) {Log.e("QRScanner", "Camera Bind Error", e)}}, ContextCompat.getMainExecutor(context))})
}
图像分析采用
"com.google.mlkit:barcode-scanning"
class BarcodeAnalyzer(private val onScan: (String) -> Unit) : ImageAnalysis.Analyzer {val options = BarcodeScannerOptions.Builder().setBarcodeFormats(Barcode.FORMAT_QR_CODE) // 仅扫描标准二维码.build()private val scanner = BarcodeScanning.getClient()@OptIn(ExperimentalGetImage::class)override fun analyze(imageProxy: ImageProxy) {val mediaImage = imageProxy.image ?: run {imageProxy.close()return}if (mediaImage.format != ImageFormat.YUV_420_888) {imageProxy.close()return}val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)scanner.process(image).addOnSuccessListener { barcodes ->barcodes.firstOrNull()?.rawValue?.let { result ->onScan(result)}}.addOnCompleteListener {imageProxy.close()}}
}