NFC Reader Mode 标签发现、轮询间隔与重复事件控制【鸿蒙心迹】
NFC 标签贴在手机后面没动,为什么应用连续收到多次发现事件?

做 NFC 应用的时候,最开始的思路很简单:标签贴上来,收到一次回调,处理业务。
结果真做的时候发现不对:标签一直贴在手机后面没动,应用却连续收到好几次标签发现事件。一次贴卡,触发了好几次业务逻辑。
这时候才意识到:NFC 标签发现不是"贴一次回调一次",是系统一直在轮询。标签还在那里,系统就会反复发现它。
一、先想清楚:NFC 是怎么发现标签的
先把最基础的问题想明白。
NFC 不是被动等标签来。是手机一直在主动发射频信号,轮询周围有没有标签。
| 阶段 | 做什么 |
|---|---|
| 射频轮询 | 手机不断发射频信号 |
| 标签响应 | 标签收到信号,回响应 |
| 发现事件 | 系统检测到标签,触发回调 |
| 回调业务 | 应用收到 TagInfo,处理业务 |
问题就在这里:轮询是持续的。标签一直在那里,每次轮询都能发现它,每次都触发回调。
二、普通 Reader Mode 和带 interval 的有什么区别
普通 Reader Mode:一发现标签就回调。标签一直在,就一直回调。
带 interval 的 Reader Mode:可以设置回调间隔。比如设置 1 秒,那 1 秒内最多回调一次。
| 对比 | 普通 Reader Mode | 带 interval |
|---|---|---|
| 回调频率 | 每次轮询发现都回调 | 按间隔回调 |
| 适合场景 | 一次性读卡 | 连续读卡 |
| 业务负担 | 很重 | 可控 |
interval 就是用来控制回调频率的。不是让系统不轮询,是让系统别那么频繁地通知你。
这段代码解决什么问题: 注册带间隔的 Reader Mode。
文件: nfc/NfcReader.ets
用途: NFC 标签发现控制
接入位置: 页面启动时
import { readerMode } from '@kit.ConnectivityKit';
// 注册 Reader Mode,设置 500ms 间隔
readerMode.readerModeWithInterval({
techs: [nfc.NFC_A, nfc.NFC_B],
interval: 500, // 每 500ms 最多回调一次
callback: (err, tagInfo) => {
if (err) return;
console.log('tag found:', tagInfo.tagId);
}
});
这里 interval 就是关键。设成 0 就是普通模式,设大一点就控制频率。
三、为什么会连续收到同一个标签
现在做个实验:把一张 NFC 标签一直贴在手机后面不动。
日志会是什么样?
10:00:00.100 tag found: AABBCC
10:00:00.600 tag found: AABBCC
10:00:01.100 tag found: AABBCC
10:00:01.600 tag found: AABBCC
同一个标签,UID 都一样,连续回调了四次。为什么?
因为轮询一直在跑。标签还在,每次轮询都能发现,每次都触发回调。interval 设了 500ms,所以每 500ms 回调一次。

四、业务层为什么要自己做去重
系统的 interval 只是控制回调频率,不代表系统帮你判断"这个标签已经处理过了"。
系统不知道你业务上要做什么。它只知道:标签在,回调你。
所以业务层要自己做去重:同一个 UID,之前处理过了,这次就不用再处理了。
| 层 | 做什么 |
|---|---|
| 系统层 | 射频轮询,发现标签,按 interval 回调 |
| 业务层 | 判断是不是同一个标签,要不要处理 |
系统管发现,业务管处理。分工要清楚。
五、几个容易踩的坑
第一个坑:一次回调就认为标签已经离场。不对,标签可能还在那里。
第二个坑:同一 UID 连续触发重复业务。贴一次卡,扣款扣了四次。
第三个坑:interval 设置过小导致业务层频繁执行。interval 越小,回调越频繁。
第四个坑:所有 NFC 技术类型全部监听。你只需要 NFC-A,就别监听 NFC-B、NFC-F。
第五个坑:页面退出后 Reader Mode 未关闭。一直轮询,耗电。
第六个坑:回调中直接执行数据库或网络耗时操作。回调要快,重操作放后台。
第七个坑:用时间防抖代替真正的标签状态管理。不是等一段时间不回调就算离场,要主动判断。

这次做 NFC 最大的体会是:NFC 标签发现不是事件驱动,是轮询驱动。系统一直在跑,标签一直在,回调就一直在。
真正做的时候,最容易忽略的不是怎么读卡,而是怎么处理重复事件。贴一次卡,可能触发十次回调,你业务上要处理十次还是一次?这个要自己想清楚。
更多推荐





所有评论(0)