更新记录
1.0.6(2026-09-08)
- 【iOS】修复连续扫码模式下从相册选图识别无结果的问题:图片中的二维码/条形码现会实时追加进连续扫码结果列表并更新计数,会话不中断
- 【iOS】连续扫码相册选图支持识别图片中的多个码(全部识别);未识别到码或图片加载失败时仅弹窗提示,不再终止整段连续扫码会话
1.0.5(2026-09-07)
- 【Android】连续扫码底层重构:移除自建 CameraX 管线与依赖,改用 HMS Scan Kit 自定义扫码视图 RemoteView,承载于插件注册的原生全屏 Activity(真实 Activity,自带进入过渡,规避浮层不出流与 CameraX desugar 崩溃)
- 【Android】连续扫码支持闪光灯按钮开关(高亮状态同步修复)、顶部按挖孔安全区适配头部、全屏沉浸布局
1.0.3(2026-09-03)
修复iOS 单次扫码后按钮触发问题,补全安卓连续扫码闪光灯控制
查看更多平台兼容性
uni-app(4.71)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | √ | 1.0.0 | √ | 1.0.0 | 5.0 | 1.0.0 | 12 | 1.0.0 | √ | 1.0.0 |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.71)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 | 微信小程序 |
|---|---|---|---|---|---|---|---|---|
| - | - | 5.0 | 1.0.0 | 12 | 1.0.0 | √ | 1.0.0 | - |
w-scankit
uni-app UTS 原生扫码插件 — 支持单次扫码、连续扫码、图片识码、多码识别,覆盖 Android / iOS / HarmonyOS NEXT 三端。
⚠️ 调试 / 运行前置:插件必须使用「自定义基座」
本插件含原生代码(UTS 插件),标准基座无法运行。真机调试请在 HBuilderX 中 「运行 → 运行到手机或模拟器 → 运行到 Android App 基座」选择/制作自定义调试基座后再运行。
另外,Android 连续扫码是插件注册的原生 Activity(内部基于 HMS Scan Kit RemoteView), 该 Activity 需在打包时合并进应用 manifest。若用本地「自定义调试基座」快速运行报
ActivityNotFoundException,属于基座未合并插件 manifest,请改用「云打包」或「Android Studio 离线打包」生成正式包验证。
目录
平台兼容性
| 平台 | 支持版本 | 底层实现 |
|---|---|---|
| Android | API 21+ | HMS ScanKit(单次扫码 / 识码);连续扫码基于 Scan Kit 自定义扫码视图 RemoteView,承载于插件注册的原生 Activity |
| iOS | iOS 12+ | AVFoundation + Vision |
| HarmonyOS NEXT | API 12+ | @kit.ScanKit(鸿蒙扫码服务) |
注意:小程序平台不支持本插件,请使用 uni-app 内置的
uni.scanCode()API。
功能特点
- ✅ 单次扫码 — 打开系统扫码界面,识别后自动返回结果
- ✅ 连续扫码 — 持续扫描,每次识别触发回调,手动结束返回全部结果
- ✅ 图片单码识别 — 从本地图片文件中识别单个二维码/条形码
- ✅ 图片多码识别 — 从本地图片文件中一次性识别所有二维码/条形码
- ✅ 闪光灯控制 — 打开 / 关闭 / 切换闪光灯
- ✅ 权限管理 — 检查与请求相机权限
- ✅ 多种码类型 — 支持 QR 码、EAN 系列、Code 系列、Data Matrix、Aztec、PDF417 等
- ✅ 三端统一 API — Android / iOS / HarmonyOS 调用方式完全一致
快速开始
1. 安装插件
在 HBuilderX 中,通过 uni_modules 市场搜索 w-scankit 并导入项目,或将 uni_modules/w-scankit/ 目录放入项目根目录下。
2. 基础用法
// 导入插件
import {
checkPermission,
requestPermission,
startScan,
scanImage,
startContinuousScan,
scanImageMulti,
openFlash,
closeFlash,
toggleFlash
} from '@/uni_modules/w-scankit';
// 单次扫码
startScan({
success(res) {
console.log('扫码结果:', res.text); // 码内容
console.log('码类型:', res.format); // 如 "QR_CODE"
},
fail(err) {
console.error('扫码失败:', err.message);
}
});
权限配置
Android
manifest.json 中已声明 android.permission.CAMERA 权限。运行时会动态请求。
iOS
manifest.json 中需配置相机使用描述:
{
"app-plus": {
"distribute": {
"ios": {
"privacyDescription": {
"NSCameraUsageDescription": "需要使用相机进行扫码"
}
}
}
}
}
HarmonyOS
config.json 中已配置:
{
"permissions": ["ohos.permission.CAMERA"]
}
API 文档
权限相关
checkPermission(): boolean
同步检查相机权限是否已授权。
返回值: true — 已授权,false — 未授权。
if (checkPermission()) {
startScan({ ... });
} else {
requestPermission({ ... });
}
requestPermission(options: RequestPermissionOptions): void
请求相机权限。
RequestPermissionOptions:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
success |
(granted: boolean) => void |
否 | 权限请求完成回调,true 表示已授权 |
fail |
(err: ScanError) => void |
否 | 请求失败回调 |
complete |
(res: any) => void |
否 | 完成回调(成功/失败均触发) |
扫码相关
startScan(options: ScanCodeOptions): void
打开系统扫码界面,单次扫码后自动关闭并返回结果。
ScanCodeOptions:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
vibrate |
boolean |
否 | true |
扫码成功时是否震动(仅 iOS 生效) |
showFlashButton |
boolean |
否 | true |
是否显示闪光灯按钮(仅 iOS 生效;Android 单次扫码走系统默认界面,不受控制) |
autoClose |
boolean |
否 | true |
扫码成功后是否自动关闭扫码界面(仅 iOS 生效) |
success |
(res: ScanResult) => void |
否 | — | 扫码成功回调 |
fail |
(err: ScanError) => void |
否 | — | 扫码失败/取消回调 |
complete |
(res: any) => void |
否 | — | 完成回调(成功/失败均触发) |
关于默认值:
vibrate/showFlashButton/autoClose缺省(不传)时按true处理;显式传false则关闭。接口层(ScanCodeOptions)这三个字段以any声明——因 UTS 编译到 iOS 后,若声明为boolean的可选字段,缺省会被 Swift 填充为false而无法区分「未传」与「显式关闭」,故底层用any保留空值、再由各端以?? true兜底为默认值true。调用方只需传boolean或不传即可,无需关心底层类型。
ScanResult:
| 字段 | 类型 | 说明 |
|---|---|---|
text |
string |
码内容(原始值) |
format |
string |
码类型,如 "QR_CODE"、"CODE_128" 等 |
图片识码
scanImage(options: ScanImageOptions): void
从本地图片文件中识别第一个二维码/条形码。
ScanImageOptions:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
imagePath |
string |
是 | 图片文件路径,支持 file:// 前缀或沙箱绝对路径 |
success |
(res: ScanResult) => void |
否 | 识别成功回调 |
fail |
(err: ScanError) => void |
否 | 识别失败回调 |
complete |
(res: any) => void |
否 | 完成回调 |
连续扫码
startContinuousScan(options: ScanContinuousCodeOptions): void
打开扫码界面并持续识别。每次扫到新码触发 onResult 回调,用户手动结束(点击完成或返回)后触发 success 返回所有已识别结果。
ScanContinuousCodeOptions:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
vibrate |
boolean |
否 | true |
每次扫码成功时是否震动(仅 iOS 生效) |
showFlashButton |
boolean |
否 | true |
是否显示闪光灯按钮(Android / iOS 生效;HarmonyOS 不生效) |
onResult |
(res: ScanResult) => void |
否 | — | 每次识别到新码时触发(去重后触发) |
success |
(res: ScanMultiResult) => void |
否 | — | 用户结束扫码时返回所有结果 |
fail |
(err: ScanError) => void |
否 | — | 扫码取消/失败回调 |
complete |
(res: any) => void |
否 | — | 完成回调 |
关于默认值:与
ScanCodeOptions相同——vibrate/showFlashButton缺省时按true处理,接口层以any声明、各端以?? true兜底,以区分「未传」与「显式false」。
ScanMultiResult:
| 字段 | 类型 | 说明 |
|---|---|---|
results |
ScanResult[] |
所有已识别的码结果列表 |
图片多码识别
scanImageMulti(options: ScanImageMultiOptions): void
从本地图片文件中一次性识别所有二维码/条形码。
ScanImageMultiOptions:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
imagePath |
string |
是 | 图片文件路径 |
success |
(res: ScanMultiResult) => void |
否 | 识别成功,返回所有码结果 |
fail |
(err: ScanError) => void |
否 | 识别失败回调 |
complete |
(res: any) => void |
否 | 完成回调 |
闪光灯控制
| 方法 | 返回值 | 说明 |
|---|---|---|
openFlash() |
void |
打开闪光灯 |
closeFlash() |
void |
关闭闪光灯 |
toggleFlash() |
boolean |
切换闪光灯状态,返回切换后的状态(true=开,false=关) |
⚠️ 闪光灯依赖硬件支持,仅在设备有实体闪光灯且扫码界面激活时可用。
平台差异:
openFlash/closeFlash/toggleFlash仅 Android、iOS 生效;HarmonyOS 系统扫码界面不暴露闪光灯控制 API,这三个方法在鸿蒙端为占位实现,不会真正控制闪光灯。
支持的码类型
format 值 |
码类型 | 说明 |
|---|---|---|
QR_CODE |
QR 码 | 二维码 |
EAN_8 |
EAN-8 | 商品条码 |
EAN_13 |
EAN-13 | 商品条码 |
CODE_128 |
Code 128 | 一维条码 |
CODE_39 |
Code 39 | 一维条码 |
CODE_93 |
Code 93 | 一维条码 |
CODABAR |
Codabar | 一维条码 |
ITF |
ITF-14 | 一维条码 |
PDF_417 |
PDF417 | 二维条码 |
DATA_MATRIX |
Data Matrix | 二维条码 |
AZTEC |
Aztec | 二维条码 |
UPC_A |
UPC-A | 商品条码 |
UPC_E |
UPC-E | 商品条码 |
错误码
| 错误码 | 常量名 | 说明 |
|---|---|---|
1001 |
CAMERA_DENIED |
相机权限被用户拒绝 |
1002 |
CAMERA_UNAVAILABLE |
相机硬件不可用 |
1003 |
SCAN_CANCELLED |
用户主动取消扫码 |
1004 |
SCAN_FAILED |
扫码识别失败(未识别到条码) |
1005 |
IMAGE_NOT_FOUND |
图片文件不存在或无法加载 |
1006 |
IMAGE_DECODE_FAILED |
图片中未识别到二维码/条形码 |
也可以在代码中使用错误码常量:
import { SCAN_CANCELLED } from '@/uni_modules/w-scankit';
startScan({
fail(err) {
if (err.code === SCAN_CANCELLED) {
// 用户取消,不做提示
return;
}
uni.showToast({ title: err.message, icon: 'none' });
}
});
代码示例
示例 1:单次扫码(完整权限流程)
<template>
<view>
<button @click="doScan">扫码</button>
<text>结果:{{ result }}</text>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { checkPermission, requestPermission, startScan } from '@/uni_modules/w-scankit';
const result = ref('');
const doScan = () => {
if (!checkPermission()) {
requestPermission({
success(granted) {
if (granted) launchScan();
else uni.showToast({ title: '需要相机权限', icon: 'none' });
}
});
return;
}
launchScan();
};
const launchScan = () => {
startScan({
vibrate: true,
success(res) {
result.value = `${res.format}: ${res.text}`;
uni.showToast({ title: '扫码成功', icon: 'success' });
},
fail(err) {
if (err.code !== 1003) {
uni.showToast({ title: err.message, icon: 'none' });
}
}
});
};
</script>
示例 2:连续扫码(多码批量收集)
<template>
<view>
<button @click="startContinuous">{{ scanning ? '扫码中...' : '连续扫码' }}</button>
<view v-for="(item, i) in codes" :key="i">
<text>[{{ item.format }}] {{ item.text }}</text>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { startContinuousScan } from '@/uni_modules/w-scankit';
const codes = ref([]);
const scanning = ref(false);
const startContinuous = () => {
codes.value = [];
scanning.value = true;
startContinuousScan({
vibrate: true,
onResult(res) {
// 每扫到一个码实时追加到列表
codes.value.unshift(res);
},
success(res) {
scanning.value = false;
uni.showToast({
title: `共识别 ${res.results.length} 个码`,
icon: 'success'
});
},
fail(err) {
scanning.value = false;
if (err.code !== 1003) {
uni.showToast({ title: err.message, icon: 'none' });
}
}
});
};
</script>
示例 3:从相册选图识码
import { scanImage, scanImageMulti } from '@/uni_modules/w-scankit';
// 选择单张图片,识别单个码
uni.chooseImage({
count: 1,
success(res) {
const imagePath = res.tempFilePaths[0];
scanImage({
imagePath,
success(result) {
uni.showModal({
title: '识别结果',
content: `类型: ${result.format}\n内容: ${result.text}`
});
},
fail(err) {
uni.showToast({ title: err.message, icon: 'none' });
}
});
}
});
// 选择单张图片,识别所有码
uni.chooseImage({
count: 1,
success(res) {
scanImageMulti({
imagePath: res.tempFilePaths[0],
success(multiRes) {
const items = multiRes.results
.map((r, i) => `${i + 1}. [${r.format}] ${r.text}`)
.join('\n');
uni.showModal({
title: `识别到 ${multiRes.results.length} 个码`,
content: items
});
},
fail(err) {
uni.showToast({ title: err.message, icon: 'none' });
}
});
}
});
示例 4:闪光灯控制
import { openFlash, closeFlash, toggleFlash } from '@/uni_modules/w-scankit';
// 打开闪光灯
openFlash();
// 切换闪光灯
const isOn = toggleFlash();
console.log('闪光灯状态:', isOn ? '开' : '关');
// 关闭闪光灯
closeFlash();
注意事项
-
Android 依赖 HMS Core Android 端基于华为 HMS ScanKit 实现。首次使用时会自动检查 HMS Core 版本。若设备不支持 HMS(如非华为设备且未安装 HMS Core),需引导用户安装 HMS Core。
-
iOS 隐私描述 iOS 端必须在
manifest.json中配置NSCameraUsageDescription,否则打包时会校验失败。部分场景下还需要配置NSPhotoLibraryUsageDescription(相册识码时)。 -
HarmonyOS NEXT 要求 鸿蒙端基于
@kit.ScanKit实现,要求 HarmonyOS API 12+。图片识码需要@kit.CoreFileKit进行路径转换。 -
图片路径格式 支持
file://开头的 URI 和沙箱绝对路径(如/data/storage/...)。Android 端会自动去除file://前缀,iOS 端直接使用路径。 -
连续扫码去重 HarmonyOS 连续扫码模式下,同一码内容在 2 秒内不会重复触发
onResult回调,避免频繁重复上报。 -
参数平台差异 部分参数与能力在不同平台的支持情况不同:
参数 / 能力 Android iOS HarmonyOS vibrate(扫码震动)❌ ✅ ❌ showFlashButton(单次扫码)❌ ✅ ❌ showFlashButton(连续扫码)✅ ✅ ❌ autoClose(自动关闭)❌ ✅ ❌ 闪光灯控制( openFlash/closeFlash/toggleFlash)✅ ✅ ❌ - Android:单次扫码使用 HMS ScanKit 默认界面,
vibrate、showFlashButton、autoClose均不生效(闪光灯按钮由系统根据环境光自动显示、扫码成功即返回,是否震动由系统默认行为决定)。连续扫码为插件注册的原生全屏扫码页(基于 Scan Kit RemoteView,真实 Activity、自带进入过渡、支持闪光灯按钮),showFlashButton生效。 - HarmonyOS:系统扫码界面不暴露震动、闪光灯按钮、闪光灯控制等 API,上述能力均不生效;连续扫码采用系统扫码页逐次识别模式(无相机预览界面,体验与 Android/iOS 不同)。
- Android:单次扫码使用 HMS ScanKit 默认界面,
-
小程序不支持 本插件仅支持 App 原生平台(Android / iOS / HarmonyOS)。小程序端请使用 uni-app 内置的
uni.scanCode()。 -
Android 连续扫码的原生 Activity 需打包合并 插件在 Android 的
AndroidManifest.xml中注册了连续扫码用的原生 Activity。云打包 / Android Studio 离线打包会自动合并插件 manifest;若用本地「自定义调试基座」运行出现ActivityNotFoundException,请改用云打包 / 离线打包验证。 -
调试请使用自定义基座 本插件是 UTS 插件(含原生代码),无法运行在标准基座上。请先在 HBuilderX 制作自定义调试基座再运行到真机,详见文档顶部说明。

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 103
赞赏 0
下载 12591875
赞赏 1949
赞赏
京公网安备:11010802035340号