前兩篇文章介紹了使用Jetpack的CameraX庫的基本使用方法。
傳送門:
CameraX基本使用: http://www.itdecent.cn/p/c1955529dd4c
CameraController更方便的使用 :http://www.itdecent.cn/p/e2092b3ab531
之前在Android開發(fā)時(shí)掃描二維碼都是用Camera+zxing庫進(jìn)行開發(fā)。但是現(xiàn)在發(fā)現(xiàn)使用CameraController+MLKit庫進(jìn)行二維碼掃描更方便。
本篇文章是默認(rèn)已經(jīng)引入CameraX庫的基礎(chǔ)之上進(jìn)行開發(fā)的。引入CameraX庫的方法這里不再贅述。
其中MLKit庫的使用方法是參照了這篇文章進(jìn)行的修改:
https://juejin.cn/post/6950448798208376839 (來自 安和橋北的少年)
可以直接下載Demo:https://github.com/cgztzero/KotlinCameraXDemo
1.引入MLKit庫
implementation 'com.google.mlkit:barcode-scanning:16.1.1'
2.重寫圖片分析器
class QRCodeAnalyser(private val listener: (List<Barcode>, Int, Int) -> Unit) :
ImageAnalysis.Analyzer {
//配置當(dāng)前掃碼格式
private val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_AZTEC
).build()
//獲取解析器
private val detector = BarcodeScanning.getClient(options)
@SuppressLint("UnsafeExperimentalUsageError", "UnsafeOptInUsageError")
override fun analyze(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image ?: kotlin.run {
imageProxy.close()
return
}
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
detector.process(image)
.addOnSuccessListener { barCodes ->
Log.e("ztzt", "barCodes: ${barCodes.size}")
if (barCodes.size > 0) {
listener.invoke(barCodes, imageProxy.width, imageProxy.height)
//接收到結(jié)果后,就關(guān)閉解析
detector.close()
}
}
.addOnFailureListener { Log.e("ztzt", "Error: ${it.message}") }
.addOnCompleteListener { imageProxy.close() }
}
}
這里我們需要自己實(shí)現(xiàn)一個(gè)listener,在解析完二維碼時(shí)返回?cái)?shù)據(jù),讓我們自己做業(yè)務(wù)處理
3.CameraController設(shè)置ImageAnalysis.Analyzer
lifecycleCameraController = LifecycleCameraController(this)
lifecycleCameraController.bindToLifecycle(this)
lifecycleCameraController.imageCaptureFlashMode = ImageCapture.FLASH_MODE_AUTO
lifecycleCameraController.setImageAnalysisAnalyzer(
cameraExecutor,
QRCodeAnalyser { barcodes, imageWidth, imageHeight ->
if (barcodes.isEmpty()) {
return@QRCodeAnalyser
}
initScale(imageWidth, imageHeight)
val list = ArrayList<RectF>()
val strList = ArrayList<String>()
barcodes.forEach { barcode ->
barcode.boundingBox?.let { rect ->
val translateRect = translateRect(rect)
list.add(translateRect)
Log.e(
"ztzt", "left:${translateRect.left} +" +
" top:${translateRect.top} + right:${translateRect.right}" +
" + bottom:${translateRect.bottom}"
)
Log.e("ztzt", "barcode.rawValue:${barcode.rawValue}")
strList.add(barcode.rawValue ?: "No Value")
}
}
judgeIntent(strList)
binding.scanView.setRectList(list)
})
binding.previewView.controller = lifecycleCameraController
注意:由于一個(gè)畫面中可能有多個(gè)二維碼,所以在監(jiān)聽中我們需要循環(huán)解析返回的barcode
最后Demo奉上:
https://github.com/cgztzero/KotlinCameraXDemo
寫的不好,歡迎各位多多交流~