Connection error when reading Android NfcV tags
Asked Answered
O

1

2

I have an Android app that reads NFC tags. Everything works fine on the LG Nexus 4 but on Samsung Galaxy S5 I only get I/O exceptions (tested on multiple phones).

So, tags are of type NfcV and I get the I/O exception when calling connect() on the NfcV (further down it is error code -5 ERROR_CONNECT).

NFC TagInfo by NXP can read the the memory content of the tag on the SG5S - are there other ways of reading NfcV tags than with connect() and transceive()?

What differences between NFC chips will cause my app's connection to fail on one phone but not the other (while other apps read it fine)? Are there timeouts I need to adjust maybe?

Code snippet:

NfcV nfcvTag = NfcV.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
if(nfcvTag!=null){
    try {
        nfcvTag.connect();
        //{flags:0x00, read multiple blocks command: 0x23, start at block 0: 0x00, read 9 blocks (0 to 8): 0x08}
        response = nfcvTag.transceive(new byte[] {(byte)0x00,(byte)0x23,(byte)0x00,byte)0x08});
    } catch (IOException e) {
        Log.d("NFCService", nfcvTag.toString());
    } finally {
        try {
            nfcvTag.close();
        } catch (IOException e) {
        }
    }
}
Ohg answered 23/5, 2014 at 11:27 Comment(10)
Two things: (1) Is NFC TagInfo (mine, not the NXP one) capable of reading the tag? (2) How do you receive the NFC intent in your app (through foreground dispatch or through intent filters in your manifest)?Alcheringa
Yes, NFC TagInfo also reads the memory content just fine on the SG5S. I get the intents through foreground dispatch.Ohg
Do you immediately do the NfcV.get() and the nfcv.connect()after you receive the intent? Or is there any processing/creation of new threads etc. in between? Also just to confirm: It's the connect() method that throws the exception and not the transceive() method, right?Alcheringa
I pass the intent on to an IntentService which then does the 'get()' and 'connect()', so yes there is creation of a new thread in between. And yes 'connect()' throws the exception - not 'transceive()'.Ohg
Hmm, that's odd. Up to the connect that's pretty much what NFC TagInfo is doing (except that NFC TagInfo manually creates a worker thread to process the tag instead of using an IntentServce).Alcheringa
Finally got back to this. The comments made me suspect the IntentService and the SGS5 seems to connect just fine to the tag when manually creating the thread and doing the 'connect()' and 'transceive()' in that thread. However, the response from 'transceive()' is now always the same byte array ('[2]') which does not match the memory content and does not look like an error code either. Again, the Nexus4 reads the tags without problems. Does anyone have thoughts on this?Ohg
What exactly do you get back from the tag? Could you post that in hexadecimal notation?Alcheringa
I get a byte array with size 1 and value 0x02. I get the same response consistently (from different tags) also when I try to read a single block rather than the multi-block reading in the code above.Ohg
Well the only difference then between your code and NFC TagInfo seems to be that NFC TagInfo is using addressed commands (i.e. addressed flag set and UID included).Alcheringa
Thanks @michaelroland . Your comments have precisely pinpointed my problems so with manual thread handling and addressed reading the SGS5 reads the tags just fine. I really appreciate that you shared your expertise on this (feel free to post an answer to except). --- Switching to addressed reading makes sense (different NFC chip - different interface) but why the connect() fails when done in an IntentService puzzles me.Ohg
A
1

So, to summarize what we found out during the discussion in the above comments:

It seems that you cannot use an IntentService to handle access to an NFC tag (through a received NFC discovery intent) in a separate thread. In that case the tag technology object's connect() method will fail.

This does not mean that you cannot handle access to a tag in a separate (worker) thread. In fact you should not access a tag on the main (UI) thread as this will block the app (and its UI) for the duration of the tag access and may cause your app to be killed by the system for being unresponsive. Manually spawning a worker thread that handles access to a tag works just fine.

My personal and unverified ideas/wild guesses why the IntentService could not handle the tag:

  1. It could have been the case that passing the NFC discovery intent to the IntentService introduced a significant delay between the tag discovery and the actual access to the tag. During this delay communication with the tag could have dropped (e.g. due to the user misaligning the reader and tag antennas making communication impossible, etc)
  2. (I do not have enough knowledge about the internals of the Android NFC system service to know if this would even be possible:) It might be that the Tag object is somehow bound to the Activity. As the IntentService is a different component (though being executed in the same app context), it might not be permitted to access the Tag object.

It seems that the NFC controller used in the Galaxy S5 only supports addressed ISO/IEC 15693 READ commands. Using unaddressed commands (i.e. commands that do not have the addressed flag set and do not contain the tag's UID) lead to { 0x02 } being returned from the transceive() method.

It is difficult to say if this is generally the case with the NFC controller (PN547? from NXP) in the S5 or if that's something that is specific to how the tag treats addressed versus unaddressed commands and responses.

Alcheringa answered 11/6, 2014 at 16:0 Comment(1)
IntentService is the only problem?Lues

© 2022 - 2024 — McMap. All rights reserved.