Barcode Scanning — 一种使用移动设备摄像头读取和解码条形码的技术。与需要专用硬件的激光扫描器不同,摄像头扫描器可在任何带摄像头的智能手机上工作。在移动开发中,Barcode Scanning 通过 ML Kit Barcode Scanning (Google)、AVFoundation (Apple)、ZXing (开源) 或 Scandit (商业 SDK) 实现。据 Google ML Kit, 2025 数据,该库每天处理 20 多亿次扫描,准确率达 98.5%。
要点
Barcode Scanning — 使用摄像头对条形码进行光学识别的过程。算法捕获图像、在图像中定位条码(定位)、对其解码(数据提取)并返回字符串值。现代 SDK 可以扫描任意方向、任意大小和任意光照条件下的条码——用户只需将摄像头对准即可。
条码格式 分为两组:1D(线性)——EAN-13、UPC-A、Code 128、Code 39、ITF、Codabar——可容纳最多 20–30 个字符,用于商品和物流;2D(矩阵)——QR Code、Data Matrix、PDF417、Aztec——可容纳最多 3000 多个字符,用于链接、票据和文档。ML Kit 支持 14 种格式——涵盖所有常见的一维和二维格式。
Data Matrix — 一种二维条码,与 QR 类似但更紧凑。用于工业(零件标记)、电子机票(IATA BCBP)和医疗样本。Data Matrix 最多可容纳 2335 个字符,可印制在很小的表面上——最小可达 2x2 毫米。与 QR 不同,Data Matrix 没有定位图案(finder patterns,角部的方块),需要更精确的相机校准。
| 格式 | 类型 | 最大数据 | 用途 |
|---|---|---|---|
| EAN-13 | 1D | 13 位数字 | 商店商品 |
| QR Code | 2D | 4296 个字符 | 链接、支付、票据 |
| Data Matrix | 2D | 2335 个字符 | 工业、医疗 |
| PDF417 | 2D | 2710 个字符 | 文档、登机牌 |
| Code 128 | 1D | 80 个字符 | 物流、运输 |
QR Code — 移动应用中最流行的二维格式。可包含 URL、文本、vCard、WiFi 配置、支付信息(UPI、SBP)。QR Code 有 40 个版本(从 21x21 到 177x177 模块)和 4 个纠错级别(L:7%、M:15%、Q:25%、H:30%)。对于移动应用,请使用版本 2–10(25x25 – 57x57 模块)——在尺寸和数据之间取得最佳平衡。
ML Kit Barcode Scanning — Android 应用的主要 SDK。ML Kit 会自动在图像上找到所有条码(与要求条码位于中心的 ZXing 不同)。API 返回 Barcode 对象,包含 rawValue(文本内容)、format(条码类型)、boundingBox 和 cornerPoints(条码的 4 个角点)。ML Kit 支持单次扫描(single-scan,单帧)和连续扫描(continuous-scan,视频流)。
多码模式 — ML Kit 可以在同一张图像上检测多个条码。通过 BarcodeScannerOptions.Builder() 启用。多码模式下返回 Barcode 列表。用于库存盘点(扫描成批商品)、识别桌面上的多个 QR 码。默认情况下多码模式关闭——仅在需要时启用,因为它会使扫描速度降低 20–30%。
// ML Kit 条码扫描多码模式
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE,
Barcode.FORMAT_EAN_13,
Barcode.FORMAT_DATA_MATRIX
)
.enableAllPotentialBarcodes()
.build()
val scanner = BarcodeScanning.getClient(options)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
barcodes.forEach { barcode ->
val type = barcode.valueType // URL、文本、电话...
val rawValue = barcode.rawValue
val displayValue = barcode.displayValue
}
}
格式过滤 — 必做的优化。setBarcodeFormats() 用于限制 ML Kit 将查找的格式。如果应用只扫描 QR 码——请指定 FORMAT_QR_CODE。这样可排除其他格式的解码算法,将扫描速度提高 2–3 倍。对于零售扫描器——FORMAT_EAN_13 | FORMAT_UPC_A。对于物流——FORMAT_CODE_128 | FORMAT_CODE_39 | FORMAT_PDF417。
ZXing (Zebra Crossing) — 基于 Java(Android)的开源库,有 Swift、React Native、Flutter 移植版。在 ML Kit 出现之前,ZXing 是扫描的事实标准。支持所有流行格式,可在任何设备上运行(包括无 Google Play 的华为设备),不需要 Google Play Services。缺点:比 ML Kit 慢 2–3 倍,无法找到画面边缘的条码,不支持多码。
ML Kit 与 ZXing — ML Kit 在速度、准确性和用户体验上更胜一筹。即使条码只占画面的 10% 且位于角落,ML Kit 也能检测到。ZXing 则要求条码占画面的 50–80% 且位于中心。ML Kit 使用神经网络(MobileNetV2-SSD)定位条码,ZXing 使用经典二值化和查找定位图案。据 Google(2025)数据,ML Kit 准确率达 98.5%,而 ZXing 为 92%。
| 特性 | ML Kit | ZXing |
|---|---|---|
| 准确度 | 98.5% | 92% |
| 速度 | 15–30 毫秒 | 50–150 毫秒 |
| 多码 | 支持 | 不支持 |
| Google Play | 需要 | 不需要 |
| 角落条码 | 可检测 | 不可检测 |
何时选择 ZXing:如果应用必须在华为设备(无 Google Play Services)、Android Go(内存受限)上运行,或者需要完全离线的无 Play Services 工作。对于其他所有情况——ML Kit 更快、更准、更易集成,并通过多码和边缘检测提供更好的用户体验。
// ZXing Core:简易扫描器
val reader = MultiFormatReader()
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.test)
val source = RGBLuminanceSource(bitmap)
val binarizer = HybridBinarizer(source)
val binaryBitmap = BinaryBitmap(binarizer)
try {
val result = reader.decode(binaryBitmap)
Log.d("ZXing", result.text)
} catch (e: NotFoundException) {
// 未找到条码
}
Scandit 作为替代方案 — 商业 SDK,准确率 99.5%,速度 10–20 毫秒。使用自有神经网络,不需要 Google Play Services。价格——每月 $400 起(2019 年)。Scandit 在零售和物流领域占主导地位(Walmart、FedEx)。对于大多数移动应用,ML Kit 已足够——只有高吞吐量扫描的企业级任务才值得使用 Scandit。
Apple AVFoundation 通过 AVCaptureMetadataOutput 提供原生的 Barcode Scanning。从 iOS 7 开始,AVFoundation 支持扫描 QR 码,从 iOS 8 开始支持所有 EAN、UPC、Code 128、PDF417 格式。AVFoundation 无需安装额外 SDK——它是 Foundation 的一部分。在 A12 及以上芯片上通过 Apple Neural Engine 进行扫描——速度 10–20 毫秒,功耗极低。
AVFoundation 的优点:零依赖、自动处理相机方向、内置浅色/深色模式支持、支持后台运行(使用 background modes)。AVFoundation 会自动针对扫描调整自动对焦和曝光——开发者只需订阅 captureOutput 委托即可。缺点:设置项比 ML Kit 少——无法启用多码或格式过滤。
import AVFoundation
class BarcodeScannerController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
private var captureSession: AVCaptureSession!
override func viewDidLoad() {
let metadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: .main)
metadataOutput.metadataObjectTypes = [.qr, .ean13, .code128]
}
func metadataOutput(_ output: AVCaptureMetadataOutput,
didOutput objects: [AVMetadataObject],
from connection: AVCaptureConnection) {
guard let code = objects.first as? AVMetadataMachineReadableCodeObject else { return }
print(code.stringValue ?? "")
}
}
iOS 上的 ML Kit 与 AVFoundation:ML Kit 提供更多控制——可配置格式、启用多码、按置信度过滤条码。AVFoundation——在旧设备上更快(开销更小),但在 iOS 15 以下不支持 Data Matrix、Aztec、PDF417。对于 iOS 15 及以上版本,ML Kit 更优。对于 iOS 12–14,请使用 AVFoundation,并对不支持的格式回退到 ML Kit。
Scandit — 面向零售、物流和医疗保健的商业 Barcode Scanning SDK。Scandit 使用自有神经网络,这些网络基于 1000 多万张各种条件下的条码图像训练而成:眩光、损坏、低光照、最大 45° 倾斜、反光。Scandit 可在最远 15 米距离(仓库中的 PDF417)以及在圆形表面(罐子、瓶子)上扫描条码。
Scandit 的功能:SparkScan(用于快速连续扫描的单次扫描)、MatrixScan(多码 + 已扫描条码的 AR 高亮)、PickList(按条码搜索商品并确认)。Scandit 支持 50 多种格式,包括 GS1 DataBar 和 Composite Codes。速度——每个条码 10–15 毫秒。准确度——标准光照下 99.5%,低光照下 97%。
// Scandit MatrixScan(需要 SDK 许可证)
val barcodeTracking = BarcodeTracking
.forDataCaptureContext(context)
.addListener(this)
.build()
barcodeTracking.addSessionListener { session, _ ->
session.trackedBarcodes.forEach { (trackingId, barcode) ->
val data = barcode.data
val symbolCount = barcode.symbolCount
}
}
Scandit 与 ML Kit:Scandit 收费(每月 $400 以上),但提供企业级功能:SparkScan(企业设备上的硬件按钮)、MatrixScan(用于高亮的 AR 叠加层)、PickList(语音确认)。ML Kit 免费,足以满足 90% 的移动应用:商店扫描器、QR 阅读器、票务应用。Scandit 仅适合搭配 Zebra/Honeywell 设备的物流终端。
Barcode Scanning 优化 包括相机、分辨率和 SDK 的配置。基本原则:像素越少,扫描越快。对于 ML Kit,最佳分辨率为视频 480p(640x480)、照片 720p(1280x720)。提高到 1080p 会使处理速度降低 2–3 倍,且准确率没有提升。请使用带 ImageAnalysis 的 CameraX 自动管理分辨率。
对焦与曝光 对扫描质量至关重要。ML Kit 不会自动调节相机——开发者必须通过 Camera2 或 CameraX 启用连续自动对焦(continuous auto-focus)和连续自动曝光(continuous auto-exposure)。没有自动对焦时,模糊的条码会将准确率降至 60–70%。对于近距离扫描(5–15 厘米),如果相机支持,请使用微距模式。
自动变焦和取景框 — 面向用户的体验优化。自动变焦会在检测到条码时将其放大(就像 Google Lens 相机一样)。通过分析条码的 boundingBox 并缩放预览来实现。取景框——显示应将相机对准何处的图形框。为获得更好的体验,请显示找到的条码的 boundingBox,并在成功解码时以绿色高亮。
// CameraX + ML Kit:优化扫描器
class BarcodeAnalyzer(private val scanner: BarcodeScanner) :
ImageAnalysis.Analyzer {
override fun analyze(image: ImageProxy) {
if (image.image == null) { image.close(); return }
val mediaImage = InputImage.fromMediaImage(image.image, image.imageInfo.rotationDegrees)
scanner.process(mediaImage)
.addOnSuccessListener { barcodes ->
barcodes.firstOrNull()?.let {
// 振动 + 声音 + 条码高亮
}
}
.addOnCompleteListener { image.close() }
}
}
用户反馈:振动(HapticFeedback)、声音(MediaActionSound)、视觉高亮(Canvas/Overlay)。成功扫描后,在下一次扫描前添加 1000–1500 毫秒的延迟(限流)——这可以防止在同一个条码上重复触发。对于连续扫描(扫描成批商品),请采用 SparkScan 的方式:每次扫描都会记录并发声提示,延迟 300–500 毫秒。
常见问题
ML Kit Barcode Scanning — Android 的最佳选择:免费、准确率 98.5%、支持多码、可检测画面任意位置的条码。如果应用必须在无 Google Play 的华为设备上运行——请使用 ZXing(开源,准确率较低)。对于企业级物流——Scandit(付费,准确率 99.5%,SparkScan)。对于简单的 QR 扫描器,ZXing 或 ML Kit 就足够了。
ML Kit Barcode Scanning 支持 14 种格式:1D — EAN-8、EAN-13、UPC-A、UPC-E、Code 39、Code 93、Code 128、ITF、Codabar;2D — QR Code、Data Matrix、PDF417、Aztec。还支持 GS1 DataBar(RSS-14、RSS-Expanded)。完整列表见 Barcode.FORMAT_* 文档。要限制格式,请使用 setBarcodeFormats()——这可将扫描速度提高 2–3 倍。
将相机分辨率降低到 480p(640x480),启用连续自动对焦,将格式限制为所需格式(setBarcodeFormats),使用 FAST 性能模式。对于 ML Kit,只指定必要的格式——排除多余格式可将扫描速度提高 2–3 倍。对于 ZXing——使用 HybridBinarizer 代替 GlobalHistogramBinarizer(快 20%)。对于 AVFoundation——指定 metadataObjectTypes。
可以,所有本地 Barcode Scanning SDK(ML Kit、ZXing、AVFoundation、Scandit)都可以完全离线工作。ML Kit 仅在首次下载模型时(downloaded mode)需要联网,之后模型会缓存在设备上。AVFoundation——内置于 iOS,无需联网。ZXing——完全离线,无需 Play Services。云端扫描(Google Cloud Vision)不用于移动应用。
ML Kit 和 Scandit 借助神经网络算法内置了对损坏条码的修复能力。ML Kit 可修复最多 30% 的损坏条码(划痕、破损)。Scandit——由于针对有缺陷的条码进行了训练,可修复最多 50%。ZXing 几乎无法修复损坏的条码——需要清晰的图像。要扫描有缺陷的条码,请使用 Scandit 或采用 ACCURATE 性能模式的 ML Kit。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。