uni-app uni-barcode-scanning 插件源码解析camera 组件 scanCode 扫码模式的 UTS 原生实现【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app本文围绕 uni-app 开源仓库中的 uni-barcode-scanning UTS 插件系统讲解它如何支撑 camera 组件modescanCode扫码模式在 Android/iOS 平台的落地从 UTS 语言与 UTS 插件的基本概念到utssdk双端目录组织、App 启动期注入扫描器、帧数据驱动的实时扫码链路、相册图片扫码、自动变焦与亮度检测等源码级细节。读完本文你将掌握该插件的完整调用链、双端扫码算法差异、依赖与配置约束并能基于仓库示例快速接入或二次开发扫码能力。插件定位为 camera 组件补齐原生扫码能力uni-barcode-scanning 是一个典型的 UTS 插件其唯一职责是实现 camera 组件的mode属性值为scanCode时的扫码功能且仅 Android/iOS 平台支持。在 camera 组件文档 中mode支持normal | scanCode两种取值scanCode模式在 Android 4.71、iOS 4.71 起可用Web 与 HarmonyOS 标记为不支持x。在 package.json 的uni_modules.hook配置中app-android: true、app-ios: true、app-harmony: false与 readme 中“仅 Android/iOS 平台支持”的声明完全一致——该插件通过 App 生命周期钩子Hook在双端启动时向 uni-camera 注册原生扫码实现而鸿蒙平台未开启钩子。从依赖关系看该插件依赖uni-framework、uni-camera、uni-getSystemInfo三个 uni_modules见 package.json。其中uni-camera 是核心依赖camera 组件的组件层实现位于 uni-camera/components/camera/camera.uvue而扫码的“识别引擎”则通过本插件注入。插件自身只做“识别”这一件事取景、预览、闪光灯、缩放等相机能力全部复用 uni-camera。UTS 语言基础插件为什么用 UTS 编写本插件全部业务逻辑使用 UTSuni type script编写。UTS 是一门跨平台、高性能、强类型的现代编程语言可以被编译为不同平台的语言| 目标平台 | 编译产物语言 | | -- | -- | | Android | Kotlin | | iOS | Swift | | HarmonyOS | ArkTS | | Web / 小程序 | JavaScript |UTS 采用与 TypeScript 基本一致的语法规范支持绝大部分 ES6 API。为了跨端UTS 做了一些约束与平台增补过去在 JS 引擎下运行支持的语法大部分在 UTS 处理下可以平滑迁移到 Kotlin 和 Swift但存在无法抹平的部分需要使用条件编译。与 uni-app 的条件编译类似UTS 也支持条件编译写在条件编译块内的代码可以调用平台特有的扩展语法——这一点在本插件的 app-ios/index.uts 中体现得尤为明显例如UTSiOS.keyword(internal)、argumentLabel(_)等 iOS 专属修饰符。更进一步的语言规范、与 TS 的差异及插件开发规范可参阅仓库内文档UTS 语言介绍、UTS 与 TS 的差异、UTS 插件开发文档、UTS 插件原生语言混编开发文档。UTS 插件与 utssdk 目录组织UTS 插件是一种特定的 uni_modules 插件核心目的是允许 uni-app/uni-app x 开发者使用 UTS 语法调用扩展 API封装原生系统 API 或三方 SDK。其实现代码主要位于utssdk 目录下并按平台分离组织| 目录/文件 | 目标平台 | 实现语言 | 作用描述 | | -- | -- | -- | -- | | utssdk/app-android | Android | UTS, Kotlin, Java | 存放 UTS 插件在 Android 平台上的具体实现源码 | | utssdk/app-ios | iOS | UTS, Swift | 存放 UTS 插件在 iOS 平台上的具体实现源码 | | utssdk/app-harmony | HarmonyOS (鸿蒙) | UTS, ArkTS | 存放 UTS 插件在 HarmonyOS 平台上的具体实现源码 | | utssdk/*.uts | 多平台共用 | UTS | 存放使用 UTS 语言编写的、可供所有平台共用的实现源码 |对照本插件 utssdk 目录实际结构如下uni-barcode-scanning/ ├── package.json # 插件元信息id、版本、依赖、平台钩子 ├── readme.md # 插件说明文档 ├── changelog.md # 变更日志 ├── ThirdPartyNotices.txt # 第三方依赖声明 └── utssdk/ ├── app-android/ │ ├── index.uts # Android 平台 UTS 入口注册 AndroidScanner 实现 │ ├── Scanner.kt # Android 原生扫码引擎Kotlin基于 ML Kit │ └── config.json # Android 依赖与最低版本配置 ├── app-ios/ │ ├── index.uts # iOS 平台 UTS 入口注册 IosScanner 实现 │ ├── Scanner.swift # iOS 原生扫码引擎Swift基于 ML Kit │ └── config.json # iOS 依赖与最低版本配置 ├── interface.uts # 多平台共用接口当前为空占位 └── unierror.uts # 错误定义当前为空占位其中平台实现采用“UTS 入口 原生代码”的混编方式UTS 文件负责类型桥接与回调适配原生文件负责真正的图像识别计算这正是 UTS 插件原生语言混编开发文档 所描述的混合开发模式。插件运行机制从 camera 组件到原生扫码引擎的完整调用链将 uni-barcode-scanning 集成进项目后modescanCode的 camera 组件会在运行时触发如下链路Android 侧源码见 uni-camera/utssdk/app-android/index.utsApp 启动期注册扫描器插件通过 AppHookProxy 的onCreate创建AndroidScannerImpl并调用 uni-camera 导出的initAndroidScanner(androidScanner)完成注册。iOS 侧对应 AppHookProxy 的applicationDidFinishLaunchingWithOptions中调用initIosScanner。组件进入扫码模式camera 组件的setScanCode(true)启动帧分析源码每一帧通过onAndroidCameraOriginalFrame拿到原始帧ImageProxy组装AndroidFrameScannerOptions后调用getAndroidScanner().processScanBarCode(options)。插件执行识别AndroidScannerImpl.processScanBarCodeindex.uts将 UTS 侧的 options 翻译成 Kotlin 调用交给Scanner.processScanBarCode(...)Scanner.kt做帧预处理与 ML Kit 识别。结果回传识别成功/失败通过AndroidScannerListener回调返回uni-camera 在 onScanSuccess 中把结果封装为UniNativeViewEvent(scancode, ...)派发给组件层最终触发页面上的scancode事件。接口契约定义在 uni-camera 的 interface.uts 中包括BarcodeInformation{ result, scanType, charset, rawData, scanArea }其中scanArea为[left, top, width, height]数组AndroidScannerListener/IosScannerListeneronScanSuccess(barcodeInformation, screenShot)、onScanFailure(error)、needZoom()、onLight(light)四个回调AndroidScanner/IosScannerprocessScanBarCode视频帧与processScanBarCodeWithPhoto相册图片两个方法。Android 平台实现深度解析Scanner.ktAndroid 端核心是 Scanner.kt基于Google ML Kit barcode-scanning实现依赖与版本见 config.json{ minSdkVersion: 21, dependencies: [ androidx.camera:camera-core:1.4.1, com.google.mlkit:barcode-scanning:17.3.0, com.github.albfernandez:juniversalchardet:2.0.4 ] }即最低支持 Android 5.0API 21引入 CameraX 用于帧处理、ML Kit 用于识别、juniversalchardet 用于字节字符集探测。帧率控制与亮度检测实时扫码对性能敏感源码通过双重闸门控制分析频率Scanner.kt#L52-L78private val isProcessing AtomicBoolean(false) // 控制帧率 private var lastAnalysisTime 0L // 时间戳限制 val currentTime System.currentTimeMillis() val filterOut currentTime - lastAnalysisTime 200 || !isProcessing.compareAndSet(false, true) if (filterOut) { imageProxy.close() // 确保立即关闭未使用的 imageProxy return }时间戳闸门距上次分析不足 200ms 的帧直接丢弃原子布尔闸门上一帧仍在识别中异步未完成时丢弃新帧被丢弃的imageProxy会被立即close()防止 CameraX 缓冲池耗尽导致崩溃。亮度检测读取图像 Y 平面亮度平面计算平均灰度平均值小于500~255 量程时通过onLight(true)通知上层“光线不足”便于页面提示用户开灯Scanner.kt#L99-L106。帧预处理旋转、裁剪与缩放识别前对每帧做三件事Scanner.kt#L80-L96imageProxy.toBitmap()转 Bitmap再按rotationDegrees旋转纠正方向若指定了宽高按目标宽高比居中裁剪图像过高裁高、过宽裁宽保证送入识别的区域与预览取景框一致bitmap.scale(width, height)缩放到与预览相同的尺寸既保证识别框准确又控制计算量。ML Kit 识别与扫码类型映射识别入口_processScanBarCodeScanner.kt#L184-L276构建BarcodeScannerOptions并启用enableAllPotentialBarcodes()扫描“潜在码”用于辅助自动变焦判断。扫码类型通过getScanTypeFromStrings映射Scanner.kt#L410-L431scanType为空数组时返回FORMAT_ALL_FORMATS识别全部格式可指定DATA_MATRIX、PDF417、QR_CODE按位或叠加。识别结果按 getBarcodeFormatStr 映射为统一字符串覆盖QR_CODE、AZTEC、CODABAR、CODE_39、CODE_93、CODE_128、DATA_MATRIX、EAN_8、EAN_13、ITF、PDF_417、UPC_A、UPC_E。自动变焦autoZoom逻辑源码实现了“先识别到码、再读内容”的两段式放大策略Scanner.kt#L206-L235当autoZoom开启且某帧检测到条形码但rawBytes为空内容太模糊时置needZoom true并跳过该码处理完整帧后若仍为needZoom回调scannerCallback?.needZoom()由上层驱动 camera 组件放大画面直到能读出内容为止一旦某个码读出了有效rawBytesneedZoom被重置为false。多码同帧与截图返回同一帧识别出多个二维码时视频帧场景除返回全部BarcodeInformation外还会把当前帧 Bitmap 包装为ScreenShot一并回调Scanner.kt#L237-L256上层可据此做“多码选择”交互识别到单个码时screenShot为null。相册图片扫码processScanBarCodeWithPhoto走独立入口支持三类路径前缀Scanner.kt#L116-L149/storage、/data开头的绝对路径 → 转file://content://→ 直接解析相册选图常见场景file://→ 去掉前缀后按文件解析。文件不存在时在主线程回调onScanFailure(file not found)。图片场景下若一个码都没扫到、或扫到的码均无有效rawData会回调onScanFailure(no barcode found)与视频帧的“容忍空内容”策略不同。图片扫码完成后也会在addOnCompleteListener中统一close()扫描器与帧。字符集与原始数据rawData条形码原始字节经Base64 编码后以字符串形式返回charset通过 juniversalchardet 的UniversalDetector对原始字节做编码探测Scanner.kt#L434-L439使中文等非 ASCII 内容的解码更可靠scanArea识别框坐标Android 侧除以屏幕像素密度density将物理像素换算为逻辑像素后再交给上层见 index.uts 中的ratio换算。iOS 平台实现深度解析Scanner.swiftiOS 端核心是 Scanner.swift同样基于Google ML KitGoogleMLKit/BarcodeScanning依赖与版本见 config.json{ deploymentTarget: 12, simulatorArchitectures: [ x86_64 ], frameworks: [ AVFoundation.framework, CoreImage.framework ], dependencies-pods: [{ name: GoogleMLKit/BarcodeScanning, version: 6.0.0 }] }即最低支持 iOS 12通过 CocoaPods 引入 ML Kit使用 AVFoundation/CoreImage 处理相机帧。iOS 与 Android 的架构高度对称可逐项对照| 能力点 | AndroidScanner.kt | iOSScanner.swift | | -- | -- | -- | | 帧率控制 |AtomicBoolean 200ms 时间戳 | 自实现AtomicBooleanL14-L43 200ms 时间戳 | | 亮度检测 | Y 平面平均灰度 50 | BGRA 像素按Y 0.299R 0.587G 0.114B采样归一化 0.15 判定光线不足L375-L423 | | 帧预处理 | Bitmap 旋转 居中裁剪 scale |CMSampleBuffer→ CIImage 按目标宽高比居中裁剪 缩放L447-L541 | | 识别 |BarcodeScanning.getClient(options)|BarcodeScanner.barcodeScanner(options:)| | 自动变焦 |rawBytes为空 →needZoom()|rawData为空 →needZoom()L177-L205 | | 多码截图 | 返回ScreenShot(bitmap)| 返回ScreenShot(image)| | 图片扫码 | Uri 多前缀解析 |file://前缀剥离 FileManager校验L118-L138 | | 字符集 | juniversalchardet |NSString.stringEncoding(for:)探测后转 IANA 名L296-L310 |iOS 侧getScanTypeL234-L261接受的字符串为小写驼峰风格qrCode、datamatrix、pdf417为空时返回.all——与 Android 侧QR_CODE等大写风格不同二次开发时需留意双端差异。此外 iOS 的 UTS 入口将图片扫码放到后台队列异步执行index.uts避免阻塞主线程结果统一DispatchQueue.main.async回主线程回调。数据模型与页面事件扫码结果最终通过scancode事件到达页面。camera 组件文档docs/component/camera.md定义了事件类型UniCameraScanCodeEvent其detail为UniCameraScanCodeEventDetail属性如下| 名称 | 类型 | 必填 | | :- | :- | :- | | type | string | 否 | | result | string | 否 | | rawData | string | 否 | | charSet | string | 否 | | scanArea | Arraynumber | 否 |对照插件内部BarcodeInformation结构interface.uts可看出完整映射链BarcodeInformation{result, scanType, charset, rawData, scanArea} │ ├────────────┘ └───┘ └──┘ └──┘ │ 对应事件 detailtype、result、charSet、rawData、scanArea即scanType如QR_CODE对外暴露为detail.typecharset暴露为detail.charSet。uni-camera 组件层在派发事件时同时携带scanCodeStatus1表示识别成功、0表示失败见 app-android/index.uts#L409-L415。实战示例接入 scanCode 扫码页面仓库示例 camera-scan-code.uvue 演示了最简接入方式——无需 import 任何插件 API只需声明modescanCode并监听scancodetemplate view styleflex:1 camera stylewidth: 100%; height: 300px; :resolutionhigh :modescanCode scancodehandleScanCode /camera view classcamera-scan-code-back-wrap button typedefault clicknavigateBack返回正常模式/button /view view classcamera-scan-code-table view classcamera-scan-code-table-pair view classcamera-scan-code-table-pair-labeltext类型/text/view view classcamera-scan-code-table-pair-valuetext{{ result?.type ?? }}/text/view /view view classcamera-scan-code-table-pair camera-scan-code-table-top-line view classcamera-scan-code-table-pair-labeltext结果/text/view view classcamera-scan-code-table-pair-valuetext{{ result?.result ?? }}/text/view /view /view /view /template script setup languts type CameraScanCodeResult { type : string | null; result : string | null; } const result ref(null as CameraScanCodeResult | null) function navigateBack() { uni.navigateBack() } function handleScanCode(ev : UniCameraScanCodeEvent) { const deatil ev.detail; result.value { type: deatil.type, result: deatil.result } as CameraScanCodeResult } /script接入步骤归纳在 uni-app x 项目中引入本插件uni_modules 方式确保uni-camera等依赖一并安装页面模板中使用camera :modescanCode并按需配置resolution、device-position、flash等属性监听scancode从ev.detail取type、result、rawData、charSet、scanArea需要自动变焦、亮度提示、相册图片扫码等高级能力时可在 camera 上下文 APIuni.createCameraContext()基础上扩展或直接以本插件暴露的processScanBarCodeWithPhoto系列方法为基础封装该方法接收filePath与scanType支持本地图片路径与相册content://路径。使用限制与注意事项平台限制扫码模式仅 Android/iOS 可用Web、小程序、HarmonyOS 不支持参见 camera 组件文档 平台标记与 package.json 的app-harmony: false。版本门槛Android 要求minSdkVersion 21Android 5.0iOS 要求deploymentTarget 12iOS 12组件scanCode模式在 Android/iOS 4.71 版本起可用。依赖体积双端均依赖 Google ML Kitbarcode-scanning首次构建会引入较大原生库需保证网络与构建环境可正常拉取iOS 通过 CocoaPodsAndroid 通过 Gradle。帧数据生命周期Android 侧ImageProxy无论是否被分析都必须在回调内close()源码已处理但二次开发自定义扫描器时务必遵循否则可能触发 CameraX 崩溃。扫码类型参数差异Android 接受QR_CODE/PDF417/DATA_MATRIX大写iOS 接受qrCode/pdf417/datamatrix驼峰不传则默认识别全部格式。自动变焦依赖内容读取autoZoom生效的前提是“检测到码但读不出内容”对已经能读出内容的近距离场景不会触发放大这是源码中的设计取舍。参考文档仓库内camera 组件文档modescanCode 与 scancodeuni.createCameraContext APIUTS 语言介绍UTS 与 TS 的差异UTS 插件开发文档UTS 插件原生语言混编开发文档UTS 插件 Android 平台开发注意事项UTS 插件 iOS 平台开发注意事项UTS 插件 HarmonyOS 平台开发注意事项【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考