简体   繁体   English

在 Android 上持续检测 NFC 标签

[英]Continuously detect an NFC tag on Android

From my reading and experimentation I have found that Android devices use some method to prevent duplicate reading of a tag ( as discussed here ).从我的阅读和实验中,我发现 Android 设备使用某种方法来防止重复读取标签( 如此处所述)。 This is great for power conservation however limits the possible application of this technology.这对节能非常有用,但限制了该技术的可能应用。

For example the problem I face is, I have a passive tag where the content is continuously updated.例如,我面临的问题是,我有一个内容不断更新的被动标签。 Once the tag has been read the phone stops detecting tags until it is removed, during this time you cannot continue to read the updated content in the tag without removing it from the field and re-tapping.一旦标签被读取,手机将停止检测标签,直到它被移除,在此期间,如果不将其从字段中移除并重新点击,您将无法继续读取标签中的更新内容。 Further more the magnetic field is either powered down of extremely weak to save power after the tag has been initially read.此外,在最初读取标签后,磁场或者关闭极弱以节省电力。 As such you cannot continuously power passive devices.因此,您无法持续为无源设备供电。

Is there a way to force an Android device to continuously power and read an updating passive tag?有没有办法强制 Android 设备持续供电并读取更新的被动标签?

NB: I do not mind if it involves rooting the Android device in order to achieve direct control of the hardware.注意:我不介意它是否涉及对 Android 设备进行 root 以实现对硬件的直接控制。

What you state in your question is simply not true for Android NFC devices.您在问题中陈述的内容对于 Android NFC 设备完全不正确。 Once a tag has been detected (= valid tag that responsed to all mandatory commands and could potentially be dispatched to an app), the NFC reader will continuously power the tag (HF carrier is kept on) and exchange some commands with it.一旦检测到标签(= 响应所有强制性命令的有效标签,并可能被发送到应用程序),NFC 阅读器将持续为标签供电(HF 载波保持开启)并与其交换一些命令。 The commands that are exchanged during that keep-alive phase ("presence check") depend on the tag type, the Android version and the Android NFC stack implementation.在保持活动阶段(“存在检查”)期间交换的命令取决于标签类型、Android 版本和 Android NFC 堆栈实现。 This is typically either这通常是

  1. repeated deactivation and re-activation cycles,重复停用和重新激活循环,
  2. repeatedly reading a certain memory area, or重复读取某个内存区域,或
  3. some other ping-pong command sequence其他一些乒乓命令序列

that allows the NFC stack to find out if the tag is still responsive.这允许 NFC 堆栈确定标签是否仍然响应。 Only if the presence check fails, Android will switch off the HF carrier of the NFC reader and will re-start with either a full polling sequence (testing for all kinds of supported tag technologies) or with a sensing phase (short HF carrier pulses to detect detuning that indicates the potential presence of a tag).仅当存在检查失败时,Android 才会关闭 NFC 阅读器的 HF 载波,并以完整的轮询序列(测试各种支持的标签技术)或感测阶段(短 HF 载波脉冲到检测指示标签潜在存在的失谐)。

Thus, if your tag behaves properly and your users manage to keep a tag attached to the Android device for a longer period of time, there is nothing that would prevent you from reading new data from the same tag (while continuously attached) multiple times.因此,如果您的标签行为正常并且您的用户设法将标签附加到 Android 设备上更长时间,则没有什么可以阻止您多次从同一标签(连续附加时)读取新数据。 You just need to make sure that you keep the tag handle ( Tag object or even a specific tag technology object instantiated from that tag handle) for as long as you want to access the tag and the tag reading activity of your app needs to stay continuously in the foreground.只要您想访问标签,并且您的应用程序的标签读取活动需要持续保持,您只需要确保保留标签句柄( Tag对象,甚至是从该标签句柄实例化的特定标签技术对象)在前台。

You could, for instance, do something like this to read a continuously updated NDEF message from a tag (note that you might better want to use an AsyncTask (or similar) instead of simply spawning that thread AND you might want to implement some mechanism to interrupt the thread):例如,您可以执行类似的操作以从标签中读取持续更新的 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();

Superb answer from Michael.迈克尔的精彩回答。 But I'm seeing a problem.但我看到了一个问题。 When the microcontroller on the tag performs an i2c read of the non-volatile memory in the NFC device, it would seem that it risks interfering with the "pinging" that is being done by the phone.当标签上的微控制器对 NFC 设备中的非易失性存储器执行 i2c 读取时,它似乎有干扰电话正在执行的“ping”的风险。

I'm using a Motorola G6 Play phone with something very similar to the M24LR-DISCOVERY tag which has a M24LR04E-R.我使用的是摩托罗拉 G6 Play 手机,它与带有 M24LR04E-R 的 M24LR-DISCOVERY 标签非常相似。 [I have reproduced the results for the ST25DV.] The tag is powered from a bench supply NOT from energy harvesting for this experiment. [我已经复制了 ST25DV 的结果。] 该标签由工作台电源供电,而不是来自该实验的能量收集。

When the tag is in the field of the phone, I can see activity in logcat of the Android debugger every 130ms or so.当标签在手机的字段中时,我可以每 130 毫秒左右在 Android 调试器的 logcat 中看到活动。

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

This appears to be Android checking for the presence of the tag.这似乎是 Android 检查标签的存在。 During this time I see the RF_BUSY output of the M24LR go low for about 15ms every 130ms or so.在此期间,我看到 M24LR 的 RF_BUSY 输出每 130 毫秒左右变低约 15 毫秒。 I associate this with the Android activity above.我将此与上面的 Android 活动相关联。

If the microcontroller then does a block read over i2c of the M24LR memory, then shortly afterwards the phone plays a notification tone.如果微控制器随后通过 M24LR 存储器的 i2c 读取块,那么不久之后手机就会播放通知音。 What has happened is that the phone has lost connection with the tag and reconnected.发生的事情是手机与标签失去连接并重新连接。 The logcat output for this time shows this happening without warning.这次的 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

The disconnect connect obviously plays havoc with any app running on the phone that is trying to exchange information with the tag.断开连接显然会对手机上运行的任何试图与标签交换信息的应用程序造成严重破坏。

I tried using the BUSY signal to prevent the microcontroller on the tag starting any i2c read operations when the RF access was in progress but the problem still occurs.我尝试使用 BUSY 信号来防止标签上的微控制器在 RF 访问正在进行时启动任何 i2c 读取操作,但问题仍然存在。 I'm guessing that the problem is due to an RF ping happening when a memory access is in progress but I'm only guessing.我猜这个问题是由于在进行内存访问时发生了 RF ping,但我只是猜测。

It seems that the chances of a disconnect increase with the number of bytes read (supporting the idea of a "clash".) Single byte reads can often get away without causing a disconnect.似乎断开连接的机会随着读取的字节数增加(支持“冲突”的想法)。单字节读取通常可以逃脱而不会导致断开连接。

Can this really be the correct behaviour?这真的是正确的行为吗? Is there nothing that can be done to prevent this?有什么办法可以防止这种情况发生吗? How would the OP (or myself) use these devices to implement a system whereby a microcontroller on the tag could read/write the memory of the NFC device to exchange information with an app running on the phone? OP(或我自己)将如何使用这些设备来实现一个系统,使标签上的微控制器可以读/写 NFC 设备的内存,以便与手机上运行的应用程序交换信息? As I said, I have observed this with both M24LR and ST25DV.正如我所说,我在 M24LR 和 ST25DV 上都观察到了这一点。

[Apologies if this is more of a question than an answer, but I wanted to shed some more light on the subject.] [抱歉,如果这更像是一个问题而不是答案,但我想对这个主题有更多的了解。]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM