Continuously detect an NFC tag on Android
Asked Answered
I

2

5

From my reading and experimentation I have found that Android devices use some method to prevent duplicate reading of a tag (as discussed here). 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?

NB: I do not mind if it involves rooting the Android device in order to achieve direct control of the hardware.

Insurgency answered 5/5, 2016 at 8:2 Comment(2)
I have never observed this behavior. Can you provide a link where this is discussed?Avelar
electronics.stackexchange.com/questions/154402/… I will update this link in the original postInsurgency
D
10

What you state in your question is simply not true for Android NFC devices. 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. 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. 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. 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).

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. 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.

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):

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();
Dyane answered 5/5, 2016 at 16:39 Comment(2)
You are correct that what i stated was in fact wrong, I guess its a case of a wrong conclusion based on my observation. After reading your response I implemented a code very similar to the one you provided which constantly polled a block of memory (without the delay) for a whole minute. To my surprise android phone did in fact continue to power the device. I appreciate your help and detailed explanation!Insurgency
would like to share my case, I had missed the ndef,close() instruction, hence my conclusion, after each read we have to close and then connect again to perform next read.Heerlen
T
2

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.

I'm using a Motorola G6 Play phone with something very similar to the M24LR-DISCOVERY tag which has a M24LR04E-R. [I have reproduced the results for the ST25DV.] The tag is powered from a bench supply NOT from energy harvesting for this experiment.

When the tag is in the field of the phone, I can see activity in logcat of the Android debugger every 130ms or so.

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. During this time I see the RF_BUSY output of the M24LR go low for about 15ms every 130ms or so. I associate this with the Android activity above.

If the microcontroller then does a block read over i2c of the M24LR memory, then shortly afterwards the phone plays a notification tone. 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.

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. 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.

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? As I said, I have observed this with both M24LR and ST25DV.

[Apologies if this is more of a question than an answer, but I wanted to shed some more light on the subject.]

Titlark answered 14/10, 2020 at 10:2 Comment(2)
Though not mentioned in my original question I too was using the M24LR in the a similar context to you. I did manage to get it to work by modifying my android code but this was so long ago that I now don't recall exactly how I did this :(Insurgency
@user3095420 - I've not been able to find anything on the android side to change the way it checks for the presence of a tag. I would be interested to discover how. I've worked around the problem by changing the way that the microcontroller accesses the nfc memory, but its not a method I like and it has ramifications. I'm amazed that the problem exists. I have scanned the data sheets and cannot see a recommended method to avoid conflicts and make accesses safe.Titlark

© 2022 - 2024 — McMap. All rights reserved.