所以我使用 Google ML Kit 通过 Jetpack Compose 扫描 QR 条形码。
这是
PreviewView
的实现
@Composable
fun preview() {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val cameraController = remember { LifecycleCameraController(context) }
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { _ ->
PreviewView(context).apply {
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
scaleType = FILL_START
implementationMode = COMPATIBLE
}.also {
cameraController.apply {
isPinchToZoomEnabled = false
imageAnalysisTargetSize = OutputSize(RATIO_16_9)
imageAnalysisBackpressureStrategy = STRATEGY_KEEP_ONLY_LATEST
setImageAnalysisAnalyzer(getMainExecutor(context)) { imageProxy ->
val scanner = BarcodeScanning.getClient(
BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_AZTEC,
Barcode.FORMAT_DATA_MATRIX,
Barcode.FORMAT_PDF417
)
.build()
)
imageProxy.image?.let { image ->
scanner.process(
InputImage.fromMediaImage(
image,
imageProxy.imageInfo.rotationDegrees
)
)
.addOnSuccessListener { barcodes ->
barcodes.forEach { barcode ->
// onQrCodeScanned(true, barcode.rawValue.orEmpty())
return@forEach
}
}.addOnFailureListener { error ->
// onQrCodeScanned(false, error.localizedMessage.orEmpty())
}.addOnCompleteListener {
imageProxy.close()
}
} ?: imageProxy.close()
}
}
cameraController.bindToLifecycle(lifecycleOwner)
it.controller = cameraController
}
)
}
使用这样的代码,对于大多数二维码来说都可以正常工作。
但是有一个二维码使用这种实现,应用程序无法检测到。
就是这张图:
即使放大到非常接近图片,应用程序仍然无法检测到二维码。但我尝试过其他扫描 QR 应用程序和在线应用程序,例如 https://scanqr.org/#scan 。而且它可以检测QR
我可以做些什么来改进 ML Kit 的二维码检测吗?或者我必须添加什么配置?
将 FILL_START 替换为 PreviewView.ScaleType.FILL_START 以正确设置缩放类型。然后将RATIO_16_9的值修改为Ratio.R_16_9。 然后正确使用 ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST STRATEGY_KEEP_ONLY_LATEST。 修改 PreviewView 初始化方法以使用 apply 来优雅地设置属性。 这是完整的代码:
@Composable
fun preview() {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val cameraController = remember { LifecycleCameraController(context) }
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { _ ->
val previewView = PreviewView(context).apply {
layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
scaleType = PreviewView.ScaleType.FILL_START
implementationMode = PreviewView.ImplementationMode.COMPATIBLE
}
cameraController.apply {
isPinchToZoomEnabled = false
imageAnalysisTargetSize = OutputSize(Ratio.R_16_9)
imageAnalysisBackpressureStrategy = ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
setImageAnalysisAnalyzer(getMainExecutor(context)) { imageProxy ->
val scanner = BarcodeScanning.getClient(
BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_AZTEC,
Barcode.FORMAT_DATA_MATRIX,
Barcode.FORMAT_PDF417
)
.build()
)
imageProxy.image?.let { image ->
scanner.process(
InputImage.fromMediaImage(
image,
imageProxy.imageInfo.rotationDegrees
)
).addOnSuccessListener { barcodes ->
barcodes.forEach { barcode ->
}
}.addOnFailureListener { error ->
}.addOnCompleteListener {
imageProxy.close()
}
} ?: imageProxy.close()
}
}
cameraController.bindToLifecycle(lifecycleOwner)
previewView.controller = cameraController
previewView
}
)
}