uni-app读取NFC标签UID需满足三前提:前台调度激活(onShow中调用plus.nfc.startndefdispatch)、权限与硬件声明完整(manifest.json补全NFC权限及android.hardware.nfc特性)、标签支持raw tech通信(绕过NDEF,用tag.getId()获取原始UID)。

uni-app 读取 NFC 标签 UID 不是“写个 plus.nfc.read 就完事”,核心卡点在 **前台调度机制是否激活**、**权限与硬件声明是否完整**、**标签是否真能被识别为可读技术类型**。安卓真机上 plus.nfc 无反应,90% 是配置没对,不是代码逻辑错。
plus.nfc.startndefdispatch() 必须手动调用且仅在前台生效
安卓系统从 API 16 起强制要求:NFC 事件(如标签靠近)只能由前台 Activity 接收。uni-app 的 plus.nfc 模块不自动注册前台调度,必须显式调用启动方法,否则永远收不到回调。
- 必须在页面
onShow或onLoad中调用plus.nfc.startndefdispatch(),不能只在onLaunch里调一次 - 调用前需确认
plus.nfc已就绪:if (plus.nfc && plus.nfc.isSupported()) { ... } - 切到后台、锁屏、弹出系统权限框、甚至微信浮窗覆盖,都会导致调度中断——此时再靠近标签毫无反应
- 建议配合
plus.android.keepScreenOn(true)防止锁屏中断,但需在onHide中关闭,避免耗电
manifest.json 权限和特性声明缺一不可
仅加 <uses-permission android:name="android.permission.NFC"/> 不够,系统会因缺少硬件声明直接跳过 NFC 初始化。
- 在
manifest.json的"app-plus" → "distribute" → "android"节点下,补全以下两项: "permissions": ["<uses-permission android:name=\"android.permission.NFC\"/>"]"usesFeatures": ["android.hardware.nfc"]- 注意:不要写成
android.hardware.nfc.host_card_emulation,那是模拟卡用的,读 UID 不需要 - 打包后可用 ADB 命令验证:
adb shell dumpsys nfc查看 “mState: STATE_ON” 和 “mIsEnabled: true”
读 UID 必须绕过 NDEF,走 raw tech 通信
plus.nfc.read 默认尝试解析 NDEF 格式,但多数门禁卡、RFID 标签(如 MIFARE Classic 1K、NTAG213)根本不存 NDEF 数据,直接返回空或失败。要稳定读 UID,得用底层技术栈直连。
- 先通过
plus.android.importClass('android.nfc.tech.NfcA')等获取原始 tag 对象 - 从 Intent 中提取
android.nfc.extra.TAG,再调用tag.getId()获取原始字节数组 - NTAG213/215/216 返回 7 字节 UID;MIFARE Classic 1K 是 4 字节;部分国产白卡可能返回空——别硬解,先用 NFC Tools App 扫一遍确认真实长度
- 转换为十六进制字符串时注意高位补零:
Array.from(tagId).map(b => (b & 0xff).toString(16).padStart(2, '0')).join('')
写入失败常见原因:WRITE_TAG 权限无效 + 标签写保护
Android 9+(API 28)起,android.permission.WRITE_TAG 被设为 signature 级别权限,uni-app 的 manifest.json 无法声明生效。所以你写进配置文件的那行权限,打包后等于没写。
- 实际写入依赖原生层实现,必须用自定义原生插件或修改 DCloud 官方 NFC 插件源码(如替换为
NdefFormatable.format()或Ndef.writeNdefMessage()) - 写入前务必用 NFC Tools 尝试写入测试文本,若报
TagReadOnlyException,说明标签已锁定(出厂写保护或之前被格式化锁定) - NTAG213 默认可写,但部分批次存在 OTP 区域锁定;MIFARE Classic 类标签需密钥认证,uni-app 默认不支持
- 写入超时建议设为 3000ms 以上,低功耗标签响应慢,
writeTimeout: 5000更稳妥
最易忽略的一点:NFC 读取不是“触发一次就结束”,而是依赖持续的前台调度监听。很多开发者以为调一次 startndefdispatch() 就能一直收消息,实际上每次页面切换、弹窗、系统通知都可能中断它——必须把启动、监听、错误重试封装成生命周期感知的模块,而不是散落在某个按钮 click 里。

















