MLKitCodeScanner 拓展:离线条码 / 二维码识别

« 返回首页

logo MLKitCodeScanner 拓展

基于 Google ML Kit 捆绑(离线)模型的条码 / 二维码识别拓展。

两种用法:识别相册或素材里的图片,或者打开摄像头实时扫描。

为什么选它:

  • 完全离线。识别模型随 .aix 一起打包,设备不需要安装 Google Play 服务,断网也能用 —— 这对国内设备很关键。
  • 不用先”初始化”。识别器按需创建,拖进来设好属性就能直接调方法。
  • 认出内容类型。扫到网址、WiFi 配置、名片、短信等结构化二维码时,除通用事件外还会触发对应的专用事件,字段已经拆好,不用自己解析。

支持的条码格式:

类别 格式
二维码 QR Code、Data Matrix、PDF417、Aztec
一维条码 EAN-13、EAN-8、UPC-A、UPC-E、Code-39、Code-93、Code-128、ITF、Codabar

权限:摄像头(实时扫描用)、读取图片(识别图片文件用)。均在运行时自动申请。

打包架构:arm64-v8a + armeabi-v7a + x86 + x86_64(含模拟器)。

  • .aix 拓展下载:

cn.fun123.MLKit.CodeScanner.aix


快速上手

一、扫图片里的二维码

设计器里放一个 MLKitCodeScanner、一个按钮、一个标签,再放一个「图像选择器」用来选图。

when 图像选择器1.AfterPicking() {
  CodeScan1.RecognizeFromFile(图像选择器1.Selection)
}
when CodeScan1.GotBarcode(rawValue, format, valueType, displayValue, detailJson) {
  标签1.Text = rawValue
}
when CodeScan1.NoBarcodeFound(operation) {
  标签1.Text = "这张图里没有找到条码"
}

二、摄像头实时扫描

  1. 设计器里放一个垂直布局(或水平布局),把它的宽度设为「充满」、高度设为 300 像素 —— 这就是预览画面的位置。
  2. 选中 MLKitCodeScanner,把 预览容器(PreviewContainer) 属性选成刚才那个布局。
  3. 代码块里直接调 开始扫描:
when 按钮_开始.Click() {
  CodeScan1.StartScan()
}
when 按钮_停止.Click() {
  CodeScan1.StopScan()
}
when CodeScan1.GotBarcode(rawValue, format, valueType, displayValue, detailJson) {
  标签1.Text = rawValue
  标签2.Text = join("格式:", format, " 类型:", valueType)
}
when CodeScan1.ScanFailed(operation, errorMessage) {
  标签1.Text = join("出错(", operation, "):", errorMessage)
}

默认扫到第一个条码就自动关摄像头。想连续扫多个,把 连续识别(ContinuousScan)设为「真」—— 同一个条码在 1.5 秒内不会重复触发。

三、扫 WiFi 二维码并显示密码

扫到结构化二维码时,通用事件和专用事件都会触发,用哪个看需要。

when CodeScan1.GotWifi(ssid, password, encryption) {
  标签_SSID.Text = join("网络名:", ssid)
  标签_密码.Text = join("密码:", password)
  标签_加密方式.Text = join("加密方式:", encryption)
  CodeScan1.StopScan()
}

四、只扫二维码(提速)

条码格式认得越少,识别越快。只做二维码扫描时把 条码类型 属性设成 qr:

when Screen1.Initialize() {
  CodeScan1.Formats = "qr"
  CodeScan1.ContinuousScan = true
}

五、扫码开灯(暗环境)

when 按钮_闪光灯.Click() {
  if CodeScan1.Torch {
    CodeScan1.Torch = false
    按钮_闪光灯.Text = "开灯"
  } else {
    CodeScan1.Torch = true
    按钮_闪光灯.Text = "关灯"
  }
}

属性

Formats
要识别的条码类型,多个用英文逗号分隔,填 all 表示全部(默认)。 可选值:qr、datamatrix、pdf417、aztec、ean13、ean8、upca、upce、code39、code93、code128、itf、codabar。 只勾选实际需要的类型可以显著提升识别速度,例如做付款码扫描只填 qr。
PreviewContainer
用来显示摄像头预览画面的可见组件,一般选一个水平布局或垂直布局。 该布局需要有明确的宽高(例如宽度「充满」、高度 300 像素),否则可能看不到画面。 只有实时扫描才需要设置;只识别图片时可以留空。
ContinuousScan
实时扫描是否连续识别。 「假」(默认)= 扫到第一个条码就自动停止摄像头; 「真」= 持续扫描,适合连续扫多个条码,同一个条码在 1.5 秒内不会重复触发。
Torch
闪光灯(手电筒)开关,仅在实时扫描进行中有效。暗环境扫码时打开。
Scanning
只读。摄像头实时扫描是否正在进行。
Busy
只读。是否正在识别图片。识别期间再次调用识别方法会触发 ScanFailed。

事件

GotBarcode(rawValue,format,valueType,displayValue,detailJson)
扫到条码就会触发,任何类型都触发,是最常用的事件。
  • rawValue — 条码原始内容。
  • format — 条码格式,如 QR_CODE、EAN_13。
  • valueType — 内容类型,如 URL、WIFI、TEXT、PRODUCT、ISBN。
  • displayValue — 适合直接显示给用户的文本(ML Kit 已做过整理)。
  • detailJson — 结构化详情 JSON,含边界坐标 bounds、四角坐标 cornerPoints,以及该类型的全部字段。
GotUrl(title,url)
扫到网址类二维码。
GotWifi(ssid,password,encryption)
扫到 WiFi 配置二维码。encryption 为 OPEN、WPA 或 WEP。
GotContact(name,phone,email,organization,title,address,urls)
扫到名片(联系人)二维码。多个电话/邮箱只给第一个,完整列表见 detailJson;多个网址用英文逗号分隔。
GotEmail(address,subject,body,type)
扫到电子邮件二维码。type 为 WORK、HOME 或 UNKNOWN。
GotPhone(number,type)
扫到电话号码二维码。type 为 WORK、HOME、FAX、MOBILE 或 UNKNOWN。
GotSms(phoneNumber,message)
扫到短信二维码。
GotGeoPoint(latitude,longitude)
扫到地理位置二维码。
GotCalendarEvent(summary,description,location,start,end)
扫到日历事件二维码。时间为 yyyy-MM-dd HH:mm:ss 文本,缺省时为空。
GotDriverLicense(firstName,lastName,licenseNumber,birthDate,expiryDate)
扫到驾照 / 身份证件条码(主要是北美 PDF417 规范,国内证件一般不适用)。
NoBarcodeFound(operation)
图片里没有找到任何条码。operation 是发起识别的方法名。 只有图片识别会触发;实时扫描每帧扫不到是正常的,不会触发。
ScanFailed(operation,errorMessage)
识别或扫描失败。operation 是出错的方法名,便于定位。

方法

RecognizeFromFile(path)
识别图片文件中的条码。path 可以是素材文件名、设备绝对路径、file:// 或 content:// 地址 (「图像选择器」的 选中项 可以直接传进来)。 识别到条码触发 GotBarcode(一张图有多个条码会逐个触发),没找到触发 NoBarcodeFound。
RecognizeFromBase64(base64)
识别 Base64 图片中的条码。支持纯 Base64,也支持带 data:image/...;base64, 前缀的写法。
StartScan()
打开摄像头开始实时扫描,预览画面显示在 预览容器 属性指定的组件里。 没设 预览容器 会触发 ScanFailed 并给出提示。 App 退到后台会自动释放摄像头,回到前台自动恢复扫描。
StopScan()
停止实时扫描并移除预览画面。

运行环境:AI 伴侣联机需要 Android 11 及以上

本拓展的识别模型放在依赖库自带的 assets 里,AI 伴侣联机调试要把它挂进 AssetManager,用的是 Android 11(API 30)才有的 ResourcesLoader —— 这是系统提供的 唯一公开办法,更低版本没有等价 API。所以:

运行方式 Android 6 ~ 10 Android 11 及以上
打包 APK ✅ 正常 ✅ 正常
AI 伴侣联机 ❌ 模型加载不了 ✅ 正常

打包 APK 之所以不受限制,是因为模型在编译时就被并进了 APK 的 assets,装到手机上 就是 App 自己的资源,与系统版本无关。伴侣的 APK 是提前编好装在手机上的,运行时没法 往自己已安装的包里加文件,只能靠系统的运行时挂载 API。

低版本设备上想验证功能,直接打包 APK 测即可;要用伴侣边改边调,请换 Android 11+ 的设备。

常见问题

扫描界面一片空白 / 看不到画面。 预览容器 那个布局没有实际尺寸。给它明确的宽高(宽度「充满」、高度 300 像素以上),别用「自动」。

一维条码扫不出来。 一维条码需要横向占满取景框、离得近一些、光线足够。另外确认 条码类型 属性没有限制成只认二维码。

识别很慢 / 手机发烫。 把 条码类型 限定成实际需要的几种(例如只填 qr)。全类型识别每帧都要跑十几种解码器。

.aix 为什么有 12MB? 离线识别模型(4 个 CPU 架构)都打包在里面了,这是”不依赖 Google Play 服务”的代价。 如果只发布给有 GMS 的设备,理论上可以换用体积小得多的联网变体,但国内设备普遍没有 GMS,所以本拓展固定用离线方案。

能生成二维码吗? 不能,本拓展只做识别。生成二维码请用 App Inventor 自带的相关拓展或在线接口。

文档反馈