
年初写了一篇CameraX的使用文章,帮到了一些朋友,也收到了一些建议。正值最近了解到华为ScanKit在扫码场景下的优秀表现,决定集成该方案,并进行一些功能改进。
之前做的Demo略显简陋,本次改进也对UI进行了调整。主要是给顶部操作栏添加了半透明背景,同时给切换按钮添加了半透明边框以提高对比度。另外对拍摄和录制场景的一些配色做了改动。

1. 华为ScanKit是什么
ScanKit可以提供便捷的二维码与条形码扫描、解析、生成能力,帮助您快速构建应用内的扫码功能。
它拥有诸多优势,包括支持多达13种码格式,在反光、污损、畸变、模糊等复杂场景下亦能良好识别,在远距离扫码的情况下能自适应放大码体,还支持多码识别功能等等。
ScanKit给开发者提供了四种集成模式,包括固定扫码界面的Default View Mode,自定义扫码界面的Customized View Mode,以及完全由开发者自定义画面和扫码流程的Bitmap Mode和MultiProcessor Mode。
前两种模式的扫码流程均由ScanKit控制,其内部采用Camera1实现。如果要集成到CameraX上的话,只能选择后两种模式。MultiProcessor Mode适用于多码识别的场景,本次先集成单码识别的Bitmap Mode。
华为ScanKit更加详细的资料可查阅官网:
https://developer.huawei.com/consumer/cn/hms/huawei-scankit
以及易冬大神的完整演示:
https://juejin.cn/post/6967890062423883783
2. 扫码方案的选择
之前的扫码方案采用的是Zxing,本次集成ScanKit之后,为了对比学习将Zxing的使用也进行了保留。在点击扫码按钮之后,底部会弹出扫码方案的选择Fragment,选择之后通过ViewModel将对应的方案告知CameraX的ImageAnalysis。

※ Google的ML Kit是一个更为强大的OCR解决方案,后面也将集成进来
大家可能比较关心ScanKit相较于Zxing的优势,可以参考如下这篇测评文章:
https://developer.huawei.com/consumer/cn/forum/topic/0201248342859390343?fid=18
这篇文章里提到ScanKit在远距离扫码、码体倾斜、模糊扫码等场景下的识别速度和成功率都要优于Zxing。大家也可以使用本文的Demo,分别选择Zxing和ScanKit两个方案,实际对比一下扫码体验。
3. 集成ScanKit
在project的gradle文件里添加ScanKit的仓库地址,app的gradle文件里添加依赖,即可快速集成。※Demo依赖了识别能力更为出色的scanplus依赖包
// build.gradle
buildscript {
repositories {
...
mavenCentral()
maven {url 'https://developer.huawei.com/repo/'}
}
}
allprojects {
repositories {
...
mavenCentral()
maven {url 'https://developer.huawei.com/repo/'}
}
}
// app/build.gradle
dependencies {
...
// Huawei scan kit
implementation 'com.huawei.hms:scanplus:1.3.2.300'
}
3.1 ImageProxy转换Bitmap
CameraX图像分析ImageAnalysis回传的图像实例ImageProxy是YUV格式的,需要先通过YuvImage将其转换为Bitmap,之后再调用ScanKit的Bitmap扫码模式。
private fun proxyToBitmap(image: ImageProxy): Bitmap {
val planes: Array<ImageProxy.PlaneProxy> = image.planes
val yBuffer: ByteBuffer = planes[0].buffer
val uBuffer: ByteBuffer = planes[1].buffer
val vBuffer: ByteBuffer = planes[2].buffer
val ySize: Int = yBuffer.remaining()
val uSize: Int = uBuffer.remaining()
val vSize: Int = vBuffer.remaining()
val nv21 = ByteArray(ySize + uSize + vSize)
yBuffer.get(nv21, 0, ySize)
vBuffer.get(nv21, ySize, vSize)
uBuffer.get(nv21, ySize + vSize, uSize)
val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)
val out = ByteArrayOutputStream()
yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 75, out)
val imageBytes = out.toByteArray()
val opt = BitmapFactory.Options()
opt.inPreferredConfig = Bitmap.Config.ARGB_8888
var bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size, opt)
return bitmap
}
3.2 调用Bitmap扫码模式
创建下ScanKit专用的扫码参数,并将转换得到的Bitmap实例传递给ScanUtil,即可开始识别。返回的识别结果包括内容、坐标、四角位置等信息,被封装到HmsScan对象里。ScanUtil识别完成后实际返回的是HmsScan数组,其第一个元素即为单码的识别结果。HmsScan对象的originalValue属性则是解析出来的内容。
class HuaweiScanAnalysis: RealTimeAnalysis {
override fun analyzeContent(imageProxy: ImageProxy, context: Context): AnalysisResult {
val bitmap = proxyToBitmap(imageProxy)
imageProxy.close()
// 创建ScanKit扫码的参数
val options = HmsScanAnalyzerOptions.Creator()
.setHmsScanTypes(HmsScan.ALL_SCAN_TYPE)
.setPhotoMode(false)
.create()
// 得到扫码结果
val result = ScanUtil.decodeWithBitmap

本文介绍如何集成华为ScanKit提升CameraX扫码性能,包括UI优化、集成步骤及手势支持等,提供丰富的代码示例。
最低0.47元/天 解锁文章
6662





