更新记录
0.3.6(2026-11-14)
- 优化 iOS 全屏扫码控制层与按钮显示。
- 修复 iOS 原生日志字段转换异常。
- 修复 iOS 全屏扫码布局约束导致的崩溃。
- 示例页支持点击整张能力卡片触发试用。
平台兼容性
uni-app(4.84)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | 0.3.6 | √ | 0.3.6 | 6.0 | 0.3.6 | 15 | 0.3.6 | 20 | 0.3.6 |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
uni-app x(4.84)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 | 微信小程序 |
|---|---|---|---|---|---|---|---|---|
| × | × | 6.0 | 0.3.6 | 15 | 0.3.6 | 20 | 0.3.6 | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| √ | × | × | √ |
安澜扫码(anlan-scan)使用说明
本文面向业务开发者,说明如何在 uni-app / uni-app x 项目中接入 anlan-scan。插件当前版本为 0.3.6。
问题反馈:如果在试用或使用过程中遇到问题,请将错误日志贴到插件市场评论区,或发送到沟通群中,两种方式都可以。看到后会及时回复。
1. 功能概览
anlan-scan 提供统一的跨端原生扫码接口,支持:
- 二维码与常见条形码识别
- 全屏原生扫码
- 相册图片识别
- 连续扫码和同帧多码返回
- 前后摄像头切换、手电筒、缩放和点击对焦
- 识别成功提示音、震动和画面抓取
- 页面内嵌入式相机预览
- 自定义扫码框、颜色、文案和交互显隐
- 原生日志回传、读取、复制和清空
扫码内容默认只在设备本地处理,不会由插件上传到业务服务器。
2. 平台与版本
| 平台 | 全屏扫码 | 相册识别 | 连续扫码 | 抓图 | 页面内预览 |
|---|---|---|---|---|---|
| Android | 支持 | 支持 | 支持 | 支持 | 支持 |
| iOS | 支持 | 支持 | 支持 | 支持 | 支持 |
| HarmonyOS | 支持 | 支持 | 受系统扫码页限制 | 暂不支持 | 暂不支持 |
版本要求:
- HBuilderX 最低版本:
5.09 - uni-app / uni-app x 最低版本:
4.84.0 - Android 最低版本:Android 5.0(API 21)
- iOS 最低部署版本:iOS 15.0
- HarmonyOS 蒸汽模式:API 20 及以上
3. 安装与原生基座
插件位于:
uni_modules/anlan-scan
如果项目尚未放入该目录,可将插件目录完整复制到项目的 uni_modules 下。
重要:重新制作自定义基座
插件包含 Android、iOS 和 HarmonyOS 原生代码。首次接入或修改插件原生源码、原生依赖后,需要重新制作自定义调试基座或正式安装包。
只修改业务侧传入的颜色、文案、显隐、尺寸等参数时,不需要重新制作基座。
在标准基座中调用插件时,HBuilderX 可能提示原生配置或三方 SDK 不生效。这是标准基座不含当前插件原生实现的正常表现。
4. 全屏扫码
4.1 最小示例
import {
startScan,
ScanOptions
} from '@/uni_modules/anlan-scan'
startScan({
scannerId: 'main',
formats: ['all'],
continuous: false,
onResult: (result) => {
console.log(result.results[0]?.value)
},
onError: (error) => {
console.error(error.errMsg, error.errCode)
}
} as ScanOptions)
startScan 会打开插件提供的原生扫码页面。单次模式下,识别成功后页面自动关闭;连续模式下,页面保持打开并通过 onResult 多次返回结果。
4.2 带界面配置的示例
import {
startScan,
ScanOptions,
ScanUiConfig
} from '@/uni_modules/anlan-scan'
const ui = {
colors: {
primary: '#2F6BFF',
mask: '#99000000',
title: '#FFFFFF',
tip: '#D1D5DB',
actionBackground: '#66000000',
actionText: '#FFFFFF',
success: '#22C55E'
},
titleText: '扫描商品码',
tipText: '请将二维码或条形码放入框内',
showAlbumButton: true,
showTorchButton: true,
showScanFrameBorder: false,
showScanFrameCorners: true,
showScanLine: true
} as ScanUiConfig
startScan({
scannerId: 'product',
formats: ['qrCode', 'ean13', 'code128'],
enableAlbum: true,
enableTorch: false,
vibrateOnScan: true,
ui,
onResult: (result) => {
const first = result.results[0]
if (first != null) {
console.log(first.value, first.format)
}
},
onError: (error) => {
if (error.errCode != 9010008) {
console.error(error)
}
}
} as ScanOptions)
5. 相册识别
import {
pickImageAndScan,
ScanOptions
} from '@/uni_modules/anlan-scan'
pickImageAndScan({
scannerId: 'album',
formats: ['all'],
returnAllResults: true,
onResult: (result) => {
result.results.forEach((item) => {
console.log(item.value)
})
},
onError: (error) => {
console.error(error.errMsg)
}
} as ScanOptions)
相册图片只在设备本地读取和识别。若用户取消选择图片,可能返回用户取消错误。
6. 连续扫码
startScan({
scannerId: 'batch',
formats: ['all'],
continuous: true,
continuousIntervalMs: 500,
vibrateOnScan: true,
onResult: (result) => {
const value = result.results[0]?.value
if (value != null) {
console.log('扫描到:', value)
}
}
} as ScanOptions)
连续模式下:
onResult可被多次调用。continuousIntervalMs控制相邻结果回调的最小间隔。- 用户关闭页面或调用
destroyScanner后,本次扫码会话结束。 complete表示会话结束,不代表每次都识别成功。
7. 页面内嵌入式预览
7.1 模板
<template>
<view class="scanner-host">
<anlan-scan
id="embedded-scanner"
scanner-id="embedded-demo"
:formats="['all']"
:auto-start="true"
:continuous="false"
:vibrate-on-scan="true"
@ready="onReady"
@scan="onScan"
@error="onError"
@statechange="onStateChange"
@log="onLog"
/>
</view>
</template>
7.2 处理事件
function onScan(event: UniNativeViewEvent): void {
const detail = event.detail as UTSJSONObject
const result = detail['result'] as UTSJSONObject | null
if (result == null) return
const results = result['results'] as Array<UTSJSONObject> | null
if (results == null || results.length == 0) return
const first = results[0] as UTSJSONObject
console.log(first['value'] as string | null)
}
function onError(event: UniNativeViewEvent): void {
console.error('embedded scan error', event.detail)
}
function onReady(event: UniNativeViewEvent): void {
console.log('embedded scanner ready', event.detail)
}
function onStateChange(event: UniNativeViewEvent): void {
console.log('embedded scanner state', event.detail)
}
宿主页面需要为组件容器设置明确宽高,例如:
.scanner-host {
width: 100%;
height: 420px;
overflow: hidden;
border-radius: 16px;
}
组件支持 start、stop、pause、resume、dispose、applyTorchEnabled、applyZoomRatio、setScanFormats 和 getState 等实例方法。
8. 主要参数
8.1 扫码参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
scannerId |
string |
default |
扫码会话标识,不同场景建议使用不同值 |
formats |
ScanFormat[] |
['all'] |
要识别的码制 |
minBarcodeLength |
number |
0 |
条形码最小长度 |
returnAllResults |
boolean |
false |
是否返回同一帧中的全部结果 |
continuous |
boolean |
false |
是否开启连续扫码 |
continuousIntervalMs |
number |
0 |
连续结果的最短回调间隔 |
captureOnSuccess |
boolean |
false |
是否保存识别成功时的画面 |
enableAlbum |
boolean |
false |
是否允许从相册识别 |
enableTorch |
boolean |
false |
是否默认开启手电筒 |
zoomRatio |
number |
1.0 |
初始缩放倍率 |
nearFocusLock |
boolean |
false |
是否启用近距离扫描优化 |
autoZoom |
boolean |
false |
是否自动尝试调整缩放 |
beepOnScan |
boolean |
false |
识别成功时是否播放提示音 |
vibrateOnScan |
boolean |
false |
识别成功时是否震动 |
支持的码制:
all, qrCode, aztec, codabar, code39, code93, code128,
dataMatrix, ean8, ean13, itf, pdf417, upcA, upcE
8.2 界面参数
通过 ui 字段传入:
| 参数 | 说明 |
|---|---|
colors.primary |
扫码框、扫描线和手电高亮颜色 |
colors.mask |
扫码框外遮罩颜色 |
colors.title / colors.tip |
标题与提示文字颜色 |
colors.actionBackground / colors.actionText |
操作按钮背景和文字颜色 |
colors.success |
识别成功描边颜色 |
titleText / tipText |
标题与提示文案 |
closeText / albumText |
关闭和相册按钮的无障碍说明 |
showTitle / showTip |
是否显示标题和提示 |
showCloseButton / showAlbumButton |
是否显示关闭和相册按钮 |
showTorchButton |
是否允许显示手电按钮 |
showMaskOverlay |
是否显示框外遮罩 |
showScanFrameBorder |
是否显示完整扫码框边框 |
showScanFrameCorners |
是否显示四角 |
showScanLine |
是否显示扫描线 |
frameWidthRatio / frameHeightRatio |
扫码框宽高比例 |
frameTopRatio |
扫码框距顶部比例 |
frameCornerRadius / frameCornerLength |
圆角和四角线段长度 |
initialCameraFacing |
back 或 front |
allowCameraSwitch |
是否允许切换前后摄像头 |
enableTapToFocus |
是否允许点击预览区域对焦 |
颜色支持 #RRGGBB 或 #AARRGGBB。九位颜色统一按 #AARRGGBB 解析。
8.3 配色默认值
插件没有 preset 模板参数,全屏扫码页直接使用宿主传入的颜色:
| 参数 | 默认兜底值 | 使用位置 |
|---|---|---|
colors.primary |
#FFFFFF |
扫码框四角、扫描线、可选完整边框、手电开启状态 |
colors.mask |
#99000000 |
扫码框外的遮罩 |
colors.title |
#FFFFFF |
顶部标题 |
colors.tip |
#D1D5DB |
扫码框下方提示 |
colors.actionBackground |
#66000000 |
顶部和底部图标按钮的圆形底色 |
colors.actionText |
#FFFFFF |
按钮图标和底部按钮文字 |
colors.success |
#22C55E |
识别成功描边 |
界面使用原生图标控件:顶部关闭和相册为圆形图标按钮,底部手电和摄像头切换为圆形图标加短文字。设备没有闪光灯时,手电按钮会自动隐藏。扫描框默认显示四角,完整边框可通过 showScanFrameBorder: true 开启。
8.4 完整界面参数示例
startScan({
scannerId: 'brand',
ui: {
colors: {
primary: '#2F6BFF',
mask: '#99000000',
title: '#FFFFFF',
tip: '#D1D5DB',
actionBackground: '#66000000',
actionText: '#FFFFFF',
success: '#22C55E'
},
titleText: '扫描商品码',
tipText: '请将二维码或条形码放入框内',
closeText: '关闭',
albumText: '相册',
torchOnText: '关闭手电',
torchOffText: '打开手电',
cameraSwitchText: '前后摄像头',
showTitle: true,
showCloseButton: true,
showAlbumButton: true,
showTorchButton: true,
showTip: true,
showMaskOverlay: true,
showScanFrameBorder: false,
showScanFrameCorners: true,
showScanLine: true,
frameWidthRatio: 0.76,
frameHeightRatio: 0.28,
frameTopRatio: 0.27,
frameCornerRadius: 14,
frameCornerLength: 24,
frameBorderWidth: 2.5,
scanLineThickness: 2,
scanLineDurationMs: 1800,
successFlashMs: 220,
closeDelayMs: 260,
topBarInsetDp: 12,
bottomBarInsetDp: 24,
tipGapDp: 14,
actionGapDp: 18,
initialCameraFacing: 'back',
allowCameraSwitch: true,
enableTapToFocus: true
}
} as ScanOptions)
9. 结果结构
onResult 接收到 ScanFrameResult:
type ScanFrameResult = {
scannerId: string
timestamp: number
frameIndex: number
results: Array<ScanResultItem>
imagePath?: string | null
imageWidth?: number | null
imageHeight?: number | null
}
单个结果:
type ScanResultItem = {
value: string
format: ScanFormat
rawType: string
cornerPoints?: Array<number> | null
bounds?: ScanRect | null
center?: ScanPoint | null
normalizedBounds?: ScanRect | null
normalizedCenter?: ScanPoint | null
}
业务代码应始终先判断 results.length,不要直接访问不存在的结果。
10. 生命周期与控制接口
import {
stopScan,
pauseScan,
resumeScan,
setTorchEnabled,
setZoomRatio,
setScanFormats,
destroyScanner
} from '@/uni_modules/anlan-scan'
setTorchEnabled({ scannerId: 'main', enabled: true })
setZoomRatio({ scannerId: 'main', zoomRatio: 1.5 })
setScanFormats({ scannerId: 'main', formats: ['qrCode'] })
pauseScan({ scannerId: 'main' })
resumeScan({ scannerId: 'main' })
stopScan({ scannerId: 'main' })
destroyScanner({ scannerId: 'main' })
业务页面卸载时,建议调用 destroyScanner 清理仍存在的扫码会话和原生资源。
11. 原生日志
通过 onLog 接收实时日志:
startScan({
scannerId: 'debug',
onLog: (entry) => {
console.log(
`[${entry.level.toUpperCase()}][${entry.stage}] ${entry.message}`,
entry.details
)
}
} as ScanOptions)
也可以主动读取:
import {
getDebugLogs,
getDebugTrace,
clearDebugTrace
} from '@/uni_modules/anlan-scan'
console.log(getDebugLogs())
console.log(getDebugTrace())
clearDebugTrace()
插件在内存中最多保留 500 条日志。日志可能包含扫码原文等业务敏感信息,只应在排查问题时复制或上传。
12. 错误码
| 错误码 | 含义 |
|---|---|
9010001 |
平台不支持 |
9010002 |
相机权限被拒绝 |
9010003 |
相机不可用 |
9010004 |
未识别到有效码 |
9010005 |
参数无效 |
9010006 |
相册不可用 |
9010007 |
相册识别失败 |
9010008 |
用户取消 |
9010009 |
不支持的能力组合 |
9010010 |
闪光灯不可用 |
9010011 |
缩放参数无效 |
9010012 |
扫码会话不存在 |
9010013 |
抓图失败 |
用户主动关闭扫码页时通常返回 9010008,业务侧一般不需要向用户显示错误提示。
13. 权限与数据处理
插件可能申请以下系统权限:
- 相机:扫描二维码和条形码
- 相册:选择图片进行本地识别
- 闪光灯:控制手电筒
- 震动:识别成功时提供触觉反馈
数据处理说明:
- 扫码内容、相册图片和相机画面默认仅在设备本地处理。
- 插件不向业务服务器上传扫码内容或图片。
- 开启
captureOnSuccess后,识别画面保存在 App 临时目录,后续处理由宿主业务决定。 - Android 使用 Google ML Kit 在设备本地识别,适用其官方数据处理条款。
- iOS 使用 Apple Vision 在设备本地识别。
- HarmonyOS 使用系统 Scan Kit。
14. 常见问题
标准基座中提示插件能力不可用
请制作包含 anlan-scan 的自定义基座。修改原生代码或原生依赖后也必须重新制作。
相机权限被拒绝
检查宿主 App 的系统权限配置和用户授权状态。iOS 需要在原生配置中声明相机、相册用途;Android 需要声明相机权限。
模拟器显示相机不可用
部分 iOS 模拟器没有可用摄像头,扫码相机无法正常启动。应在真机上完成相机、相册和闪光灯相关验收。
识别框显示但无法识别
扫描框只作为视觉引导,实际识别覆盖预览画面,但应保证二维码或条形码清晰、完整、不过曝,并尝试靠近或调整拍摄距离。
修改颜色后需要重新打包吗
通过 ui 参数修改颜色、文案、显隐、位置和尺寸不需要重新制作基座。修改插件原生源码或第三方 SDK 时才需要重新打包。
15. 开发验收建议
- 使用正式 App ID 制作自定义基座。
- 在至少一台 Android 真机和一台 iOS 真机上验收相机流程。
- 验收首次授权拒绝与再次授权场景。
- 验收单次扫码、连续扫码、相册识别和多码返回。
- 验收页面退出、后台切换和重复进入后的资源释放。
- HarmonyOS 重点验收系统 Scan Kit 页面和权限流程。
- 发布前检查
readme.md、更新日志、隐私声明和权限说明。
16. 实现结构
interface.uts定义跨端 API、结果、UI 配置和错误码。ui.uts合并宿主传入的颜色、文案、显隐和尺寸参数。- Android
AnlanScanActivity.kt负责 CameraX 预览、ML Kit 识别、权限、相册和全屏扫码页。 - Android
AnlanScanControlView.kt绘制统一图标的原生操作按钮。 - iOS
AnlanScanViewController.swift负责 AVFoundation、Vision、全屏布局和操作按钮。 - HarmonyOS
index.uts通过系统 Scan Kit 打开扫码页面。
17. 重新打包
Android 使用 CameraX 与 ML Kit,iOS 使用相机、相册和 Vision。修改插件原生源码或第三方依赖后,必须重新制作自定义调试基座或正式安装包。页面级颜色、文案、显隐、位置和尺寸可以随前端资源更新,不需要重新制作基座。

收藏人数:
购买源码授权版(
试用
使用 HBuilder 导入示例项目
赞赏(0)
下载 598
赞赏 1
下载 12765318
赞赏 1959
赞赏
京公网安备:11010802035340号