更新记录
1.0.0(2026-08-21)
- 初版发布:一套面向 uni-app / uni-app x 的跨端 NFC 能力插件(UTS API 插件)。
- 对外 API 契约统一语义化命名:类型
NfcError/TagSnapshot/NfcResult/NdefRecordInput/DispatchDiagnostics/ScannerRuntime/IosWorkbench/TagListener;函数如isNfcSupported/startTagScan/readMifareClassicSector/transceiveIsoDep/writeNdefRecords/startSession等。 - Android 原生层:
NfcBridge(桥接)、NfcKernel(NFC 引擎)、NfcTransitActivity(前台分发中转)。 - iOS 原生层:
NfcBridgeIOS(CoreNFC)。 - HarmonyOS 原生层:
NfcBridge(@ohos.nfc.tag / controller)。 - 微信小程序(Android):基于
wx.getNFCAdapter()实现标签扫描/监听与 NDEF 文本写入,读写类接口提供*Async异步变体;iOS 微信返回 9010007。 - 三端均提供同步函数与
*Async异步变体。
平台兼容性
uni-app(5.13)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(5.13)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ |
lime-nfc
面向 uni-app / uni-app x 的跨端 NFC 能力插件(以函数式 UTS API 为主,附一个演示组件便于快速预览)。提供标签发现、NDEF 读写、Mifare Classic/Ultralight 读写、IsoDep/NfcV 透传等能力,覆盖 Android、iOS、HarmonyOS、微信小程序(Android)。
安装
插件市场导入,在页面引入,自定义基座。
自定义基座说明:
- 本插件使用 UTS 原生能力,必须在自定义基座中运行,标准基座无法使用。
- CLI 项目特别注意:请检查根目录
package.json,确保所有@dcloudio/*相关包的版本号一致,且与当前 HBuilderX 版本对齐。版本不一致会导致自定义基座编译失败或运行异常。
代码演示
// TS 环境:导入所需的选项/数据类型,并用 `as` 标注选项对象以获得类型校验
import type {
ActionOptions,
WatchOptions,
TextWriteOptions,
TagSnapshot
} from '@/uni_modules/lime-nfc'
import {
isNfcSupported,
isNfcEnabled,
openSystemNfcSettings,
startTagScan,
setTagListener,
writeTextToTag
} from '@/uni_modules/lime-nfc'
// 建议放在页面 onLoad / 按钮回调等函数内执行,避免顶层直接 return
function runNfcDemo() {
if (!isNfcSupported()) {
console.log('设备不支持 NFC')
return
}
if (!isNfcEnabled()) {
openSystemNfcSettings({
fail: (err) => console.log(err.errMsg)
} as ActionOptions)
}
// 方式一:回调监听
startTagScan({
success: (tag: TagSnapshot) => {
console.log('发现标签', tag.serialHex, tag.textContent)
},
fail: (err) => {
console.log('监听失败', err.errCode, err.errMsg)
}
} as WatchOptions)
// 方式二:设置全局监听
setTagListener((tag: TagSnapshot) => {
console.log('标签到达', tag)
})
// 写入文本
writeTextToTag({
content: 'hello lime-nfc',
success: () => console.log('写入成功'),
fail: (err) => console.log('写入失败', err.errMsg)
} as TextWriteOptions)
}
TS 与非 TS 的差异:在 TypeScript / uni-app x 中,选项对象建议用对应的选项类型(
ActionOptions/WatchOptions/TextWriteOptions等)做as标注;在非 TS 环境(普通 JS / 纯 UTS)中,无需import type这些类型,也不必写as,直接传对象即可。演示组件:导入后也可直接使用内置演示组件查看效果(代码位于
uni_modules/lime-nfc/components/lime-nfc):<lime-nfc />
能力索引(意图 → 函数)
不确定用哪个函数时,先在这里按「你想做什么」定位。带「异步版本」的函数在微信小程序等异步平台必须用其
*Async形态。
| 你想做什么 | 推荐函数 | 异步版本 | 备注 |
|---|---|---|---|
| 判断设备是否支持 NFC | isNfcSupported |
— | 返回 false 时其余接口返回 9010001 |
| 判断 NFC 是否已开启 | isNfcEnabled |
— | 关闭时读写失败 9010002(iOS 上该路径不可达,见下文) |
| 引导用户打开 NFC 设置 | openSystemNfcSettings |
— | 失败 9010006 |
| 开始监听标签(回调式) | startTagScan |
— | 发现即回调 TagSnapshot |
| 设置全局常驻监听 | setTagListener |
— | 传 null 解除 |
| 停止标签监听 | stopTagScan |
— | 彻底停止并释放 |
| 恢复挂起的监听 | resumeTagScan |
— | 沿用上次回调 |
| 主动读取最近一次标签 | getLastTag |
— | clearAfterRead 防重复 |
| 清空标签缓冲 | clearTagBuffer |
— | 批处理后调用 |
| 获取上次触碰时间 | getLastTapTime |
— | 毫秒时间戳 |
| 写入 NDEF 文本 | writeTextToTag |
— | 最常见写入 |
| 写入多条 NDEF 记录 | writeNdefRecords |
writeNdefRecordsAsync |
文本/URI 混合 |
| 写 Mifare Classic 块 | writeMifareClassicBlock |
writeMifareClassicBlockAsync |
需密钥认证 |
| 写 Mifare Ultralight 页 | writeMifareUltralightPage |
writeMifareUltralightPageAsync |
每页 4 字节 |
| 读 Mifare Classic 扇区 | readMifareClassicSector |
readMifareClassicSectorAsync |
整扇区 |
| 读 Mifare Classic 块 | readMifareClassicBlock |
readMifareClassicBlockAsync |
单块 16 字节 |
| 读 Mifare Ultralight 页 | readMifareUltralightPages |
readMifareUltralightPagesAsync |
连续多页 |
| 发送 APDU 透传(IsoDep) | transceiveIsoDep |
transceiveIsoDepAsync |
自定义/金融卡底层 |
| 发送指令透传(NfcV) | transceiveNfcV |
transceiveNfcVAsync |
ISO 15693 |
| 配置扫描调度策略 | configureScanner |
— | 防抖/去重/租约 |
| 批量取出标签 | getTagBatch |
— | 配合 clearAfterRead |
| 探测待处理 Intent | probeTagIntent |
— | Android 冷启动补处理 |
| 暂停/恢复前台扫描 | pauseForegroundScan / resumeForegroundScan |
— | 临时挂起 |
| 排查调度问题 | getDispatchDiagnostics |
— | 为何没收到标签 |
| 查看运行时状态 | getScannerRuntime |
— | 含已生效策略 |
| 查看 iOS 工作台 | getIosWorkbench |
— | 仅 iOS 有意义 |
| 开启/结束会话 | startSession / stopSession |
— | iOS 需显式开启 |
错误码
| 错误码 | 含义 |
|---|---|
| 9010001 | 当前设备不支持 NFC 功能 |
| 9010002 | 当前设备的 NFC 开关未开启 |
| 9010003 | 启动标签监听失败 |
| 9010004 | 写入标签失败 |
| 9010005 | 读取/透传失败(标签不支持、密钥认证失败或连接失败) |
| 9010006 | 无法打开系统 NFC 设置页 |
| 9010007 | 当前平台暂未提供此能力 |
| 9010008 | 没有可用的活动标签 |
| 9010009 | 传入参数不合法 |
平台支持与权限
| 平台 | 状态 |
|---|---|
| Android | 完整实现(原生 NFC 引擎) |
| iOS | 完整实现(CoreNFC) |
| HarmonyOS | 完整实现(@ohos.nfc.tag / controller) |
| 微信小程序 | Android 微信可用(wx.getNFCAdapter 标签读写监听);iOS 微信返回 9010007 |
| Web | 兜底实现(返回 9010007 当前平台暂未提供此能力) |
iOS 上 Mifare Classic 相关接口按平台能力返回占位错误,与系统 CoreNFC 限制一致。微信小程序读写底层为异步回调模型,读写为
*Async异步接口,同步读写接口返回“请改用*Async”提示。
- Android:宿主工程
manifest.json需声明android.permission.NFC,插件已内置前台分发 Activity 与 tech 列表(res/xml/nfc_tech_routes.xml)。 - iOS:需在
Info.plist配置 NFC 读取权限描述与Near Field Communication Tag Reading能力(插件已内置示例),并部署到 iOS 13+。 - HarmonyOS:模块已声明
ohos.permission.NFC_TAG权限。 - 微信小程序:使用
wx.getNFCAdapter(),需在微信开发者工具中开启 NFC 接口权限;仅 Android 微信支持标签读写。
API 参考
下面以函数为列表逐一说明:每个函数写明用途、参数(含 options 的实际字段)与返回。
设备与状态
isNfcSupported(): boolean
判断当前设备是否支持 NFC。返回 false 时其余接口会返回 9010001,建议在调用任何读写/监听前先调用。
isNfcEnabled(): boolean
判断 NFC 是否已开启。返回 false 时扫描/写入会失败并返回 9010002,应先引导用户开启。
iOS 上
isNfcEnabled与isNfcSupported等价:CoreNFC 没有单独查询「系统 NFC 开关是否打开」的公开 API(仅NFReaderSession.readingAvailable合并了硬件 / 权限 / 限制),二者取同一来源。详见平台差异速记。
openSystemNfcSettings(options: ActionOptions): void
跳转系统 NFC 设置页,引导用户开启 NFC。失败时 fail 携带 9010006。
标签扫描与监听
startTagScan(options: WatchOptions): void
开始标签监听(回调式)。发现标签即触发 success(tag: TagSnapshot),同时 complete 也会触发。内部先校验 isNfcSupported(不支持 → 9010001)与 isNfcEnabled(未开启 → 9010002),启动失败 → 9010003。
在 iOS 上由于
isNfcEnabled与isNfcSupported等价,9010002路径实际不可达;装置缺失或受限会走9010001,其余连接 / 权限问题由beginWatcher失败转为9010003。
stopTagScan(options: ActionOptions): void
彻底停止标签监听并释放前台分发。
resumeTagScan(): void
恢复此前被挂起的监听,沿用上一次 startTagScan 注册的回调。
setTagListener(listener: TagListener): void
设置全局常驻监听。传入回调函数后,任意标签到达都会回调;传入 null 解除监听。
getLastTag(clearAfterRead: boolean): TagSnapshot | null
主动取出最近一次发现的标签快照;clearAfterRead 为 true 时取走即清空,避免重复处理。无可用标签返回 null。
clearTagBuffer(): void
清空标签缓冲队列,通常在批量处理(getTagBatch)后调用。
getLastTapTime(): number
返回上次触碰标签的毫秒时间戳。
标签写入
writeTextToTag(options: TextWriteOptions): void
最简单的文本写入:将 options.content 作为 NDEF 文本写入标签。失败 fail 携带 9010004。
writeNdefRecords(records: NdefRecordInput[]): NfcResult
写入多条 NDEF 记录(文本 / URI 混合等)。返回 NfcResult,成功 payload 含 { recordCount };记录为空 → 9010009,写入失败 → 9010004。
writeMifareClassicBlock(block: number, keySlot: string, keyHex: string, dataHex: string): NfcResult
写入 Mifare Classic 指定块(16 字节)。keySlot 为 'A' 或 'B'(密钥槽),keyHex 为 6 字节(12 位十六进制)密钥,dataHex 为 16 字节(32 位十六进制)数据。密钥非 12 位 → 9010009,认证失败 → 9010005。
writeMifareUltralightPage(page: number, dataHex: string): NfcResult
写入 Mifare Ultralight 指定页(每页 4 字节)。dataHex 为 4 字节(8 位十六进制)数据。
标签读取与透传
readMifareClassicSector(sector: number, keySlot: string, keyHex: string): NfcResult
读取 Mifare Classic 整个扇区。成功 payload 含 { sector, blocks: string[] }(每块 16 字节十六进制)。无标签 → 9010008,不支持/认证失败 → 9010005。
微信小程序端当前固定读取 4 块/扇区(标准 1K 卡即整扇区;4K 卡的大扇区含 16 块时可能读不全);iOS 该接口返回
9010007占位,仅 Android / HarmonyOS 原生实现按实际扇区大小完整读取。
readMifareClassicBlock(block: number, keySlot: string, keyHex: string): NfcResult
读取 Mifare Classic 单块(16 字节)。成功 payload 含 { block, hex }。
readMifareUltralightPages(startPage: number, pageCount: number): NfcResult
读取 Mifare Ultralight 连续多页(每次以 4 页为单位读取)。成功 payload 含 { startPage, packets: string[] }。
transceiveIsoDep(apduHex: string): NfcResult
向 IsoDep 标签透传 APDU 指令(金融卡 / 自定义协议底层)。apduHex 为十六进制指令。成功 payload 含 { hex }(响应)。
transceiveNfcV(commandHex: string): NfcResult
向 NfcV(ISO 15693)标签透传指令。成功 payload 含 { hex }。
异步变体(Async)
微信小程序等异步平台必须使用以下
*Async版本;同步版本在微信小程序会直接提示「请改用*Async」。它们返回Promise<NfcResult>,可直接await。
readMifareClassicSectorAsync(sector, keySlot, keyHex): Promise<NfcResult>readMifareClassicBlockAsync(block, keySlot, keyHex): Promise<NfcResult>readMifareUltralightPagesAsync(startPage, pageCount): Promise<NfcResult>transceiveIsoDepAsync(apduHex): Promise<NfcResult>transceiveNfcVAsync(commandHex): Promise<NfcResult>writeNdefRecordsAsync(records): Promise<NfcResult>writeMifareClassicBlockAsync(block, keySlot, keyHex, dataHex): Promise<NfcResult>writeMifareUltralightPageAsync(page, dataHex): Promise<NfcResult>
参数与返回结构与对应的同步版本一致。
调度治理
configureScanner(options: ScanPolicy | null): void
配置扫描调度策略(防抖、去重、前台通道等)。传入 null 为安全空操作:不改变任何策略、直接返回(各端实现均为 no-op)。ScanPolicy 字段:
| 字段 | 类型 | 含义 |
|---|---|---|
frontScanLane |
'reader' \| 'dispatch' |
前台扫描通道 |
omitNdefSurvey |
boolean |
跳过 NDEF 探测 |
echoShieldMs |
number |
回声屏蔽时长(毫秒) |
sessionLeaseMs |
number |
会话租约时长 |
inboxCap |
number |
收件箱容量上限 |
repeatWindowMs |
number |
重复去重窗口 |
hotTagHoldMs |
number |
热标签保持时长 |
pendingLimit |
number |
待处理上限 |
getTagBatch(clearAfterRead: boolean, maxCount: number): TagSnapshot[]
批量取出当前缓冲的标签(最多 maxCount 条),clearAfterRead 为 true 时取走即清空。配合 configureScanner 的去重与 clearTagBuffer 使用。
probeTagIntent(): boolean
探测并补偿处理待处理的 Android 系统 NFC Intent(常用于冷启动后补处理),返回是否有待处理 Intent。
resumeForegroundScan(): boolean
恢复前台扫描,返回是否成功恢复。
pauseForegroundScan(): void
临时挂起前台扫描(不释放监听),可用 resumeForegroundScan 恢复。
诊断与运行时
getDispatchDiagnostics(): DispatchDiagnostics | null
获取调度诊断信息,用于排查「为何没收到标签」:lastIngressAt / lastIngressSource / lastIngressSerial / lastIngressAction / cachedCount / foregroundArmed。
getScannerRuntime(): ScannerRuntime | null
获取扫描运行时状态,含已生效策略 appliedPolicy、最近一次触碰信息、bridgeLane 等。
getIosWorkbench(): IosWorkbench | null
获取 iOS 工作台信息(仅 iOS 有意义):系统版本、阅读器可达性、会话/观察者/监听器绑定状态、当前驻留标签、队列深度与已配置的去重/保持窗口等。
会话
iOS 上 NFC 需显式开启会话(弹出系统扫描 sheet),其他平台可忽略。
startSession(): void
开启 NFC 会话(iOS 弹窗)。
stopSession(): void
结束 NFC 会话。
数据类型(数据模型)
所有类型均可在 TS 环境下通过
import type引入:
import type {
NfcError, TagSnapshot, NfcResult, NdefRecordInput,
DispatchDiagnostics, ScannerRuntime, IosWorkbench,
ActionOptions, WatchOptions, TextWriteOptions, ScanPolicy, TagListener
} from '@/uni_modules/lime-nfc'
通用回调语义:操作类函数的
options均含success/fail/complete三个回调字段。fail携带NfcError({ errCode, errSubject, errMsg }),complete无论成败都会触发。
| 类型 | 含义 / 关键字段 |
|---|---|
NfcError |
失败回调携带的错误:{ errCode, errSubject, errMsg }。errCode 见错误码;errSubject 为出错子系统(如 dispatch / ndef / classic);errMsg 为可读描述。 |
NdefRecordInput |
构造 NDEF 记录的输入:{ kind: string, value: string }。kind 为记录类型(text / uri 等),value 为对应内容。 |
TagSnapshot |
标签快照:serialHex(UID 十六进制)、techNames: string[]、textContent: string \| null、linkContent: string \| null、ndefLines: string[]、actionName: string、detectedAt: number、extraBag: UTSJSONObject \| null。 |
NfcResult |
读写/透传类函数的返回值:{ ok, code, message, payload }。code 为 0 表示成功,非 0 为错误码;payload 为业务数据(见各函数说明)。 |
DispatchDiagnostics |
调度诊断:lastIngressAt / lastIngressSource / lastIngressSerial / lastIngressAction / cachedCount / foregroundArmed。 |
ScannerRuntime |
运行时状态:appliedPolicy(已生效策略)、最近一次触碰信息、bridgeLane 等。 |
IosWorkbench |
iOS 工作台:系统版本、阅读器可达性、会话/观察者/监听器状态、驻留标签、队列深度与去重/保持窗口等。 |
ActionOptions |
{ success?, fail?, complete? },用于无业务返回值的操作。 |
WatchOptions |
同 ActionOptions,但 success 携带 TagSnapshot。 |
TextWriteOptions |
{ content: string, success?, fail?, complete? },文本写入专用。 |
ScanPolicy |
configureScanner() 入参,null 表示不修改。字段见调度治理。 |
TagListener |
(snapshot: TagSnapshot) => void,setTagListener 的监听器类型。 |

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 73792
赞赏 596
下载 12522205
赞赏 1943
赞赏
京公网安备:11010802035340号