更新记录

1.3.8(2026-06-01)

打包冲突问题处理

1.3.7(2026-06-01)

iOS 自定义文案

1.3.6(2026-05-27)

iOS 自定义识别结果文案

查看更多

平台兼容性

uni-app(4.66)

Vue2 Vue3 Chrome Safari app-vue app-vue插件版本 app-nvue app-nvue插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本
- - - - 1.3.8 1.3.8 4.4 1.3.8 16 1.3.8 12 1.3.8
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(4.66)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

UTS环境兼容性

uni-app uni-app x

hl-nfccase-uts

跨端 NFC 读/写 插件(Android / iOS / HarmonyOS)。

阅读指引(按角色)

你想… 直接看
5 分钟跑通读卡 快速开始平台差异
查有哪些方法 API 参考
写 NDEF / 写块 / transceive 按场景示例
事件里有哪些字段 返回数据结构
Android 自定义基座、后台碰卡、报错 reason 注意事项Android 小节

快速开始

  1. 安装插件后,Android 需自定义基座或重新打包(插件含 NFC Manifest / 后台分发 Activity)。
  2. 页面里调用 HlNfc.configure(可选,调去重/队列等),再 HlNfc.onTagDiscovered 注册回调。
  3. 仅 iOS / HarmonyOS:用户要点按钮或你主动调用 HlNfc.startNFCSession();iOS 可传自定义提示文案,如 HlNfc.startNFCSession('请将卡片靠近设备顶部')Android 前台自动监听,一般不用 startNFCSession

推荐导入方式(命名空间导入,调用更清晰):

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

最小示例(推荐:<script setup>

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'
import { onShow, onHide } from '@dcloudio/uni-app'

onShow(() => {
  HlNfc.configure({ pendingMax: 10, dedupeMs: 600 })
  HlNfc.onTagDiscovered((event) => {
    console.log('UID:', event.uidHex, event)
  })
  // #ifdef APP-IOS || APP-HARMONY
  HlNfc.startNFCSession()
  // #endif
})

onHide(() => {
  // #ifdef APP-IOS || APP-HARMONY
  HlNfc.stopNFCSession()
  // #endif
})

判断能力:HlNfc.isNfcSupported() / HlNfc.isNfcEnabled()

uni-app(Options API,完整可复制)

<script setup> 逻辑相同:页面显示时 configure;点击「开始扫描」注册 onTagDiscovered 并在 iOS/Harmony 启动会话;页面隐藏时停止会话。

<template>
  <view class="container">
    <button @click="startScan">开始扫描 NFC</button>
    <button @click="stopScan">停止扫描</button>
    <view v-if="tagData">
      <text>UID: {{ tagData.uidHex }}</text>
    </view>
  </view>
</template>

<script>
import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

export default {
  data() {
    return {
      tagData: null
    }
  },
  onShow() {
    HlNfc.configure({ pendingMax: 10, dedupeMs: 600 })
  },
  onHide() {
    this.stopScan()
  },
  methods: {
    startScan() {
      // 注册回调
      HlNfc.onTagDiscovered((event) => {
        console.log('NFC 标签:', event)
        this.tagData = event
      })
      // #ifdef APP-IOS || APP-HARMONY
      HlNfc.startNFCSession('请将 NFC 标签靠近设备')
      // #endif
    },
    stopScan() {
      // #ifdef APP-IOS || APP-HARMONY
      HlNfc.stopNFCSession()
      // #endif
    }
  }
}
</script>

平台差异一览

一句话

  • Android:前台自动收卡;高级读写依赖内存里的 Tag,注意 activeTagTtlMs;可 refreshActiveTagSync() 写后重读。
  • iOS:必须 startNFCSession(),有系统弹窗;NDEF 写入需开启 keepSessionAlive 并在同一会话内完成,不支持 Mifare 直读块、NfcA/B raw transceive。
  • HarmonyOS:需 startNFCSession();读写能力与 Android 接近,见下表。

能力对比表

特性 Android iOS HarmonyOS
启动方式 自动监听 startNFCSession() startNFCSession()
系统弹窗
FeliCa
Mifare Classic 读块
NDEF 写入 ✅(需 keepSessionAlive)
Mifare 写块/写页
NdefFormatable 格式化
NfcA/NfcB Raw Transceive
最低系统 Android 5.0+ iOS 13.0+ HarmonyOS 3.0+

默认回调里会尽量解析 UID、技术列表、NDEF 文本/URI不会默认读 Mifare 扇区内容(需密钥,易因卡而异)。

支持的技术类型(摘要)

平台 常见支持
Android NDEF、Mifare Classic/Ultralight、IsoDep、NfcA/B/F/V
iOS ISO14443(MiFare、ISO7816)、ISO15693(NFC-V);无 FeliCa
HarmonyOS 与 Android 类似,见各 techs 字段

API 参考

基础能力

方法 平台 说明
onTagDiscovered(callback) 全平台 注册碰卡回调
onSessionInvalidated(cb) 仅 iOS 监听 NFC 会话失效(用户取消/超时等)
startNFCSession(alertMessage?) / stopNFCSession() iOS/HarmonyOS 启停前台扫描;alertMessage 仅 iOS 生效
getPendingTagSync(clearRead) 全平台 读一条缓存(后台/冷启动)
getPendingTagsSync(clearRead, max) 全平台 读多条缓存
refreshActiveTagSync() 三端 写后不离卡,重读当前标签快照
clearPendingTag() 全平台 只清 磁盘缓存队列
clearActiveTag() 全平台 内存活动标签 + 去重状态
resetNfcState() 全平台 上两者都做
isNfcSupported() / isNfcEnabled() 全平台 能力与开关
configure(options) 全平台 见下表
clearReadCache() 全平台 Android 侧多为占位,保留接口一致
checkAndSaveCurrentIntentNfc() Android 兜底:从当前 Activity Intent 取 NFC
checkNfcDispatchCalled() Android 调试:分发 Activity 是否被调过

configure 常用字段(Android)useReaderModeactiveTagTtlMs(默认可操作时间窗,默认 5000)、dedupeMs(同 UID 去重窗口)、pendingMaxskipNdefCheck

configure iOS 额外字段(系统 NFC 弹框文案,均可选)

字段 默认值 说明
keepSessionAlive false 读卡后保持会话,便于同一会话内 ndefWrite
readSuccessAlertMessage 读取成功! 读卡完成且即将关闭会话时的弹框文案
readSuccessKeepAliveAlertMessage 读取成功,请保持标签靠近设备以继续操作 keepSessionAlive: true 时读卡完成文案

扫描开始文案仍通过 HlNfc.startNFCSession(alertMessage?) 传入,默认 请将 NFC 标签靠近设备

读 / 写 API

方法 平台
mifareClassicReadSector / ReadBlock / WriteBlock Android/HarmonyOS
mifareUltralightReadPages / WritePage Android/HarmonyOS
isoDepTransceive / nfcVTransceive Android/HarmonyOS
nfcATransceive / nfcBTransceive 仅 Android
ndefWrite / ndefFormatAndWrite ndefWrite 支持 Android/iOS/HarmonyOS(iOS 需 keepSessionAlive);ndefFormatAndWrite 仅 Android

按场景示例

读卡 + 判断 NFC

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

if (!HlNfc.isNfcSupported() || !HlNfc.isNfcEnabled()) { /* 提示用户 */ }

HlNfc.onTagDiscovered((e) => { console.log(e.uidHex, e.ndefText, e.ndefUri) })
// Android 无需 startNFCSession;iOS/Harmony 需先 HlNfc.startNFCSession(),见快速开始

写入 NDEF(Android / iOS / HarmonyOS)

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

// iOS 写入前需要 configure({ keepSessionAlive: true, activeTagTtlMs: 10000 })
// iOS 可选:自定义系统弹框文案
HlNfc.configure({
  keepSessionAlive: true,
  activeTagTtlMs: 10000,
  readSuccessAlertMessage: '识别成功',
  readSuccessKeepAliveAlertMessage: '识别成功,请保持贴卡以继续写入'
})
HlNfc.startNFCSession('请将手机顶部靠近门锁')
HlNfc.onTagDiscovered(() => {
  const res = HlNfc.ndefWrite([
    { type: 'text', data: 'Hello', lang: 'en' },
    { type: 'uri', data: 'https://example.com' }
  ])
  if (res.code !== 0) console.error(res.data.error)
})

说明:

  • 只有 type: 'raw'data 会按十六进制 payload 解析
  • text / uri / mime / externaldata 都按普通字符串写入

写 Android 包名(AAR / External Type)

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

const res = HlNfc.ndefWrite([
  {
    type: 'external',
    domain: 'android.com',
    extType: 'pkg',
    data: 'com.example.app'
  }
])

这里的 data 直接传 Android 包名字符串,不要转十六进制。

写后立刻重读(推荐 Android 调大 activeTagTtlMs

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

HlNfc.configure({ activeTagTtlMs: 10000 })
const w = HlNfc.ndefWrite([{ type: 'text', data: 'Hi', lang: 'en' }])
if (w.code === 0) {
  const r = HlNfc.refreshActiveTagSync()
  if (r.code === 0) console.log(r.data.ndefText)
}

格式化空白卡(仅 Android)

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

HlNfc.onTagDiscovered(() => {
  const res = HlNfc.ndefFormatAndWrite([{ type: 'text', data: 'Hello', lang: 'en' }])
  // 仅格式化:HlNfc.ndefFormatAndWrite([])
})

Mifare 写块 / Ultralight 写页

HlNfc.onTagDiscovered 同一贴卡时间窗内调用(默认约 5s,可 HlNfc.configure({ activeTagTtlMs }))。

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

HlNfc.mifareClassicWriteBlock(4, 'A', 'FFFFFFFFFFFF', '00112233445566778899AABBCCDDEEFF')
HlNfc.mifareUltralightWritePage(4, '00112233')

NfcA / NfcB raw(仅 Android)

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

HlNfc.nfcATransceive('3004')   // Type2 读示例,具体命令依芯片文档
HlNfc.nfcBTransceive('05...')

勿随意写 Ultralight 低页;有 NDEF 时优先 HlNfc.ndefWrite

清理状态(缓存 vs 内存标签)

import * as HlNfc from '@/uni_modules/hl-nfccase-uts'

HlNfc.clearPendingTag()   // 只清队列
HlNfc.clearActiveTag()    // 只清内存 Tag + 去重
HlNfc.resetNfcState()     // 两者都清
方法 缓存队列 活动标签 去重
clearPendingTag
clearActiveTag
resetNfcState

返回数据结构

字段因平台略有不同,常见:timestampactionuidHextechsndef / ndefText / ndefUriextras

Android(示例)

{
  "timestamp": 1769741815417,
  "action": "TECH_DISCOVERED",
  "uidHex": "04A1B2C3D4E5F6",
  "techs": ["android.nfc.tech.NfcA", "android.nfc.tech.Ndef"],
  "ndefText": "文本内容",
  "ndefUri": "https://example.com",
  "extras": { /* nfcA / mifareClassic 等 */ }
}

iOS(示例)

{
  "timestamp": 1769741815417,
  "action": "iOS_CoreNFC_MiFare",
  "uidHex": "53318EF7210001",
  "techs": ["MiFare", "MiFareUnknown"],
  "ndefUri": "https://example.com"
}

HarmonyOS(示例)

{
  "timestamp": 1769741815417,
  "action": "Harmony_NFC_TAG",
  "uidHex": "04A1B2C3D4E5F6",
  "techs": ["NfcA", "MifareClassic", "Ndef"],
  "ndefText": "文本内容",
  "extras": { }
}

注意事项

所有平台

  • 高级读写失败统一 { code: -1, data: { error, reason? } },请以 res.data.error 为准。
  • getPendingTagSync / onTagDiscovered:偏「事件」;refreshActiveTagSync:偏「当前卡写后重读」。

Android(必读)

  • 自定义基座或重打包(含 NFC Intent、后台 NfcDispatchActivity)。
  • 后台/冷启动碰卡会先缓存,前端在 onShow 等时机用 HlNfc.getPendingTagSync(true) 消费并自行跳转。
  • 同一张卡在不同机型上 techs 可能不同;仅有 NfcA 而无 MifareUltralight 时,用 nfcATransceivendefWrite,不要强行 mifareUltralightReadPages
  • *`mifareUltralight** 要求 techList 里真有android.nfc.tech.MifareUltralight`。

Android(进阶 / 排错)

  • 活动标签:高级 API 依赖进程内最近一次扫描的 Tag;仅读过磁盘缓存不算「有 Tag」。超时见 TAG_TTL_EXPIRED,可调大 activeTagTtlMs 或重新贴卡。
  • reason 字段NO_TAG_IN_MEMORY(内存无 Tag)、TAG_TTL_EXPIRED(附带 elapsedMs / ttlMs);其它如卡移开见 error 原文。
  • 插件已处理 Intent 消费防重复ReaderMode 去重读写后延长去重,一般无需自己管;若仍异常,可 HlNfc.resetNfcState() 再试。

iOS

  • Info.plist NFCReaderUsageDescription、Xcode NFC Capability、Entitlements 含 NDEF + TAG
  • 无后台唤醒;每次扫描通常需 HlNfc.startNFCSession()
  • 每次新会话会丢弃上一轮未送达的旧回调;可选 HlNfc.clearPendingTag() 再注册回调。
  • 会话内续读可 HlNfc.configure({ keepSessionAlive: true, activeTagTtlMs: 10000 }) + HlNfc.refreshActiveTagSync()
  • iOS 系统弹框文案:HlNfc.startNFCSession(alertMessage?) 自定义扫描提示;HlNfc.configure({ readSuccessAlertMessage, readSuccessKeepAliveAlertMessage }) 自定义读卡完成提示(均可选,不传保留默认)。
  • 支持监听系统 NFC 弹框被用户主动取消或超时等异常中断,通过 HlNfc.onSessionInvalidated((e) => { ... }) 获取,原因包含 userCanceled / sessionTimeout / systemBusy 等。

HarmonyOS

  • ohos.permission.NFC_TAG;需 HlNfc.startNFCSession()

常见问题(精简)

Q:为什么有 UID 但 ndefWrite 报没有活动标签?
A:可能只有缓存、没有本次前台扫描到的 Tag。请重新贴卡或先 onTagDiscovered 再写,并检查 activeTagTtlMs

Q:Android 为什么写一次又触发一次回调?
A:射频断开再连会再发现同卡;插件已做去重与写后延长去重,仍异常可试 HlNfc.configure({ dedupeMs })HlNfc.resetNfcState()

Q:iOS 能写 NDEF 吗?
A:可以写 NDEF,但必须先 HlNfc.configure({ keepSessionAlive: true }),再 HlNfc.startNFCSession(),并在 HlNfc.onTagDiscovered 回调里马上调用 HlNfc.ndefWrite()。离开会话或插件读完后自动关闭会话,都会导致写入失败。


文档版本随插件迭代;完整方法签名以 utssdk/interface.uts 为准。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android: NFC权限;iOS: NFCReaderUsageDescription;HarmonyOS: ohos.permission.NFC_TAG

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

仅读取 NFC 标签数据,不收集用户信息

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: