如何在Android Studio中用CameraView仅识别应用内定义的二维码(无第三方库)
实现仅识别预定义二维码的CameraView扫描功能(无第三方库)
核心思路
用官方Jetpack CameraX的CameraView组件采集画面,搭配Google ML Kit条码扫描(官方组件,非第三方库)识别二维码,仅对预定义内容做响应,直接忽略其他无关二维码。
步骤1:配置权限与布局
添加相机权限到
AndroidManifest.xml:<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />布局中添加CameraView:
<androidx.camera.view.CameraView android:id="@+id/cameraView" android:layout_width="match_parent" android:layout_height="match_parent" app:cameraLensFacing="back" />
步骤2:定义有效二维码内容集合
把需要识别的二维码内容存入集合,用于后续校验:
private val VALID_QR_CONTENTS = setOf( "MY_APP_VALID_CODE_001", "https://myapp.com/verify/123", "USER_AUTH_TOKEN_456" )
步骤3:初始化条码扫描器
仅启用二维码格式识别,避免识别其他条码类型:
private lateinit var barcodeScanner: BarcodeScanner private fun initBarcodeScanner() { val scanOptions = BarcodeScannerOptions.Builder() .setBarcodeFormats(Barcode.FORMAT_QR_CODE) .build() barcodeScanner = BarcodeScanning.getClient(scanOptions) }
步骤4:创建二维码分析器
实现ImageAnalysis.Analyzer,负责逐帧分析画面、识别并校验二维码:
private val qrAnalyzer = ImageAnalysis.Analyzer { imageProxy -> val mediaImage = imageProxy.image ?: run { imageProxy.close() return@Analyzer } // 将相机帧转换为ML Kit可处理的输入格式 val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) barcodeScanner.process(inputImage) .addOnSuccessListener { barcodes -> barcodes.forEach { barcode -> barcode.rawValue?.let { qrContent -> // 校验内容是否在预定义集合中 if (VALID_QR_CONTENTS.contains(qrContent)) { // 识别到有效二维码,执行业务逻辑 runOnUiThread { Toast.makeText(this, "扫描到有效二维码:$qrContent", Toast.LENGTH_SHORT).show() // 可选:停止扫描,避免重复触发 cameraView.stop() } } // 无效内容直接忽略,不做任何响应 } } } .addOnCompleteListener { // 必须关闭imageProxy,否则会阻塞后续帧处理 imageProxy.close() } }
步骤5:绑定CameraView与分析器
在Activity生命周期中完成权限校验和组件绑定:
private val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted -> if (isGranted) { cameraView.start() bindAnalyzerToCamera() } else { Toast.makeText(this, "需要相机权限才能扫描二维码", Toast.LENGTH_SHORT).show() } } override fun onStart() { super.onStart() initBarcodeScanner() if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED ) { cameraView.bindToLifecycle(this) bindAnalyzerToCamera() } else { requestPermissionLauncher.launch(Manifest.permission.CAMERA) } } private fun bindAnalyzerToCamera() { ProcessCameraProvider.getInstance(this).addOnSuccessListener { provider -> val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA // 配置分析器,只保留最新帧,避免卡顿 val imageAnalysis = ImageAnalysis.Builder() .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), qrAnalyzer) // 绑定生命周期、相机选择器、分析器和预览 provider.bindToLifecycle( this, cameraSelector, imageAnalysis, cameraView.preview ) } }
步骤6:添加官方依赖
在build.gradle(Module level)中添加CameraX和ML Kit的官方依赖:
dependencies { // CameraX 核心组件 implementation "androidx.camera:camera-core:1.2.3" implementation "androidx.camera:camera-lifecycle:1.2.3" // CameraView 预览组件 implementation "androidx.camera:camera-view:1.0.0-alpha34" // ML Kit 条码扫描 implementation "com.google.mlkit:barcode-scanning:17.2.0" }
关键注意事项
- 所有UI操作必须切换到主线程执行,避免崩溃。
- 处理完每一帧后必须调用
imageProxy.close(),否则会导致相机帧队列阻塞、出现卡顿。 - 如果需要持续扫描有效二维码,不要调用
cameraView.stop(),可添加防抖逻辑(比如1秒内不重复识别同一内容)。
内容的提问来源于stack exchange,提问作者CrazyProgrammer
相关产品推荐
相关产品推荐

