更新记录

1.3.0(2026-04-29)

一、iOS异常日志收紧

1.2.9(2026-04-29)

一、iOS相关

1.2.8(2026-04-28)

一、iOS 标签写入相关问题

查看更多

平台兼容性

uni-app(4.66)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Safari app-vue app-nvue Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本
1.3.0 1.3.0 - - - × 4.4 1.3.0 16 1.3.0 12 1.3.0
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 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. 页面里调用 configure(可选,调去重/队列等),再 onTagDiscovered 注册回调。
  3. 仅 iOS / HarmonyOS:用户要点按钮或你主动调用 startNFCSession()Android 前台自动监听,一般不用 startNFCSession

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

import { onTagDiscovered, startNFCSession, stopNFCSession, configure } from '@/uni_modules/hl-nfccase-uts'
import { onShow, onHide } from '@dcloudio/uni-app'

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

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

判断能力:isNfcSupported() / 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 {
  onTagDiscovered,
  startNFCSession,
  stopNFCSession,
  configure
} from '@/uni_modules/hl-nfccase-uts'

export default {
  data() {
    return {
      tagData: null
    }
  },
  onShow() {
    configure({ pendingMax: 10, dedupeMs: 600 })
  },
  onHide() {
    this.stopScan()
  },
  methods: {
    startScan() {
      // 注册回调
      onTagDiscovered((event) => {
        console.log('NFC 标签:', event)
        this.tagData = event
      })
      // #ifdef APP-IOS || APP-HARMONY
      startNFCSession()
      // #endif
    },
    stopScan() {
      // #ifdef APP-IOS || APP-HARMONY
      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) 全平台 注册碰卡回调
startNFCSession() / stopNFCSession() iOS/HarmonyOS 启停前台扫描
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。iOS 另有 keepSessionAlive 等,见下方注意事项。

读 / 写 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 { onTagDiscovered, isNfcSupported, isNfcEnabled } from '@/uni_modules/hl-nfccase-uts'

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

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

写入 NDEF(Android / iOS / HarmonyOS)

import { ndefWrite, onTagDiscovered } from '@/uni_modules/hl-nfccase-uts'

// iOS 写入前需要 configure({ keepSessionAlive: true, activeTagTtlMs: 10000 })
onTagDiscovered(() => {
  const res = ndefWrite([
    { type: 'text', data: 'Hello', lang: 'en' },
    { type: 'uri', data: 'https://example.com' }
  ])
  if (res.code !== 0) console.error(res.data.error)
})

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

import { ndefWrite, refreshActiveTagSync, configure } from '@/uni_modules/hl-nfccase-uts'

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

格式化空白卡(仅 Android)

import { ndefFormatAndWrite, onTagDiscovered } from '@/uni_modules/hl-nfccase-uts'
onTagDiscovered(() => {
  const res = ndefFormatAndWrite([{ type: 'text', data: 'Hello', lang: 'en' }])
  // 仅格式化:ndefFormatAndWrite([])
})

Mifare 写块 / Ultralight 写页

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

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

NfcA / NfcB raw(仅 Android)

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

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

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

import { clearPendingTag, clearActiveTag, resetNfcState } from '@/uni_modules/hl-nfccase-uts'

clearPendingTag()   // 只清队列
clearActiveTag()    // 只清内存 Tag + 去重
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 等时机用 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 去重读写后延长去重,一般无需自己管;若仍异常,可 resetNfcState() 再试。

iOS

  • Info.plist NFCReaderUsageDescription、Xcode NFC Capability、Entitlements 含 NDEF + TAG
  • 无后台唤醒;每次扫描通常需 startNFCSession()
  • 每次新会话会丢弃上一轮未送达的旧回调;可选 clearPendingTag() 再注册回调。
  • 会话内续读可 configure({ keepSessionAlive: true, activeTagTtlMs: 10000 }) + refreshActiveTagSync()

HarmonyOS

  • ohos.permission.NFC_TAG;需 startNFCSession()

常见问题(精简)

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

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

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


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

隐私、权限声明

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

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

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

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

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