在 Android 上持续检测 NFC 标签

Continuously detect an NFC tag on Android

根据我的阅读和实验,我发现 Android 设备使用某种方法来防止重复读取标签 (as discussed here)。这对于节能非常有用,但限制了该技术的可能应用。

例如我面临的问题是,我有一个内容不断更新的被动标签。一旦标签被读取,phone 就会停止检测标签,直到它被移除,在此期间,如果不将标签从字段中移除并重新点击,您将无法继续读取标签中的更新内容。 此外,在最初读取标签后,磁场要么断电要么极弱以节省电力。因此,您无法持续为无源设备供电。

有没有办法强制 Android 设备持续供电并读取更新的无源标签?

注意:我不介意是否涉及对 Android 设备进行 root 以实现对硬件的直接控制。

您在问题中陈述的内容对于 Android NFC 设备来说根本不正确。一旦检测到标签(=响应所有强制命令并可能被发送到应用程序的有效标签),NFC reader 将持续为标签供电(HF 载波保持开启)并与交换一些命令它。在保持活动阶段 ("presence check") 交换的命令取决于标签类型、Android 版本和 Android NFC 堆栈实现。这通常是

  1. 重复停用和重新激活周期,
  2. 重复读取某个内存区域,或者
  3. 一些其他乒乓命令序列

这允许 NFC 堆栈查明标签是否仍然响应。仅当存在检查失败时,Android 才会关闭 NFC reader 的 HF 载波,并重新启动完整的轮询序列(测试所有类型的支持标签技术)或感测阶段(短 HF 载波脉冲检测表明可能存在标签的失谐)。

因此,如果您的标签行为正常并且您的用户设法将标签附加到 Android 设备上更长时间,则没有什么可以阻止您从同一设备读取新数据标记(同时连续附加)多次。您只需要确保在您想要访问标签和读取标签 activity 您的应用程序需要持续保持在前台。

例如,您可以执行类似的操作以从标签中读取持续更新的 NDEF 消息(请注意,您最好使用 AsyncTask(或类似的)而不是简单地生成该线程并且您可能想要实现某种机制来中断线程):

new Thread(new Runnable() {
    public void run() {
        Ndef ndef = Ndef.get(tag);

        try {
            while (true) {
                try {
                    Thread.sleep(30000);

                    ndef.connect();
                    NdefMessage msg = ndef.getNdefMessage();

                    // TODO: do something

                } catch (IOException e) {
                    // if the tag is gone we might want to end the thread:
                    break;
                } finally {
                    try {
                        ndef.close();
                    } catch (Exception e) {}
                }
            }
        } catch (InterruptedException e) {
        }
    }
}).start();

迈克尔的精彩回答。 但我看到了一个问题。当标签上的微控制器对 NFC 设备中的 non-volatile 内存执行 i2c 读取时,它似乎有干扰 phone.[=12 正在执行的“ping”的风险=]

我正在使用摩托罗拉 G6 Play phone,它与带有 M24LR04E-R 的 M24LR-DISCOVERY 标签非常相似。 [我已经复制了 ST25DV 的结果。]标签由台式电源供电,而不是来自本实验的能量收集。

当标记位于 phone 的字段中时,我可以每隔 130 毫秒左右在 Android 调试器的 logcat 中看到 activity。

2020-10-13 19:38:50.555 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 15
2020-10-13 19:38:50.555 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1389)] nfaConnectionCallback: NFA_PRESENCE_CHECK_EVT
2020-10-13 19:38:50.680 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1953)] nativeNfcTag_doPresenceCheck
2020-10-13 19:38:50.680 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1997)] nativeNfcTag_doPresenceCheck: handle=0
2020-10-13 19:38:50.694 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 15
2020-10-13 19:38:50.694 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1389)] nfaConnectionCallback: NFA_PRESENCE_CHECK_EVT
2020-10-13 19:38:50.820 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1953)] nativeNfcTag_doPresenceCheck
2020-10-13 19:38:50.820 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1997)] nativeNfcTag_doPresenceCheck: handle=0

这似乎是 Android 检查标签是否存在。在此期间,我看到 M24LR 的 RF_BUSY 输出每 130 毫秒左右变低约 15 毫秒。我将此与上面的 Android activity 相关联。

如果微控制器随后通过 M24LR 存储器的 i2c 进行块读取,则不久之后 phone 会播放通知音。发生的事情是 phone 与标签失去连接并重新连接。这次的 logcat 输出显示这种情况在没有警告的情况下发生。

2020-10-13 19:38:51.335 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 15
2020-10-13 19:38:51.335 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1389)] nfaConnectionCallback: NFA_PRESENCE_CHECK_EVT
2020-10-13 19:38:51.335 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(2173)] nativeNfcTag_doPresenceCheck: tag absent
2020-10-13 19:38:51.335 4209-28960/? D/NativeNfcTag: Tag lost, restarting polling loop
2020-10-13 19:38:51.335 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1392)] nativeNfcTag_doDisconnect: enter
2020-10-13 19:38:51.335 4209-28960/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(1414)] nativeNfcTag_doDisconnect: exit
2020-10-13 19:38:51.336 4209-28960/? D/NfcService: Discovery configuration equal, not updating.
2020-10-13 19:38:51.336 4209-28960/? D/NativeNfcTag: Stopping background presence check
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(793)] nfaConnectionCallback: Connection Event = 6
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(1121)] nfaConnectionCallback: NFA_DEACTIVATED_EVT: Type=0, gIsTagDeactivating=0
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcManager.cpp(5280)] notifyPollingEventwhileNfcOff: sDiscCmdwhleNfcOff=0
2020-10-13 19:38:51.344 4209-4411/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(921)] getReconnectState = 0x0
2020-10-13 19:38:51.345 4209-4411/? I/libnfc_nci: [INFO:NfcTag.cpp(189)] NfcTag::setDeactivationState: state=0
2020-10-13 19:38:51.345 4209-4411/? I/libnfc_nci: [INFO:NfcTag.cpp(1358)] NfcTag::resetTechnologies
2020-10-13 19:38:51.345 4209-4411/? I/libnfc_nci: [INFO:NativeNfcTag.cpp(263)] nativeNfcTag_abortWaits

断开连接显然会对 phone 上试图与标签交换信息的任何应用程序 运行 造成严重破坏。

我尝试使用 BUSY 信号来阻止标签上的微控制器在 RF 访问正在进行时启动任何 i2c 读取操作,但问题仍然存在。我猜问题是由于内存访问正在进行时发生 RF ping 而引起的,但我只是猜测。

似乎断开连接的可能性随着读取的字节数的增加而增加(支持“冲突”的想法)。单字节读取通常可以在不导致断开连接的情况下逃脱。

这真的是正确的行为吗?有什么办法可以防止这种情况发生吗? OP(或我自己)将如何使用这些设备来实现一个系统,标签上的微控制器可以 read/write NFC 设备的内存与 phone 上的应用程序 运行 交换信息]? 正如我所说,我在 M24LR 和 ST25DV 上都观察到了这一点。

[如果这是一个问题而不是一个答案,我深表歉意,但我想进一步阐明这个主题。]