Search code examples
androidnfcrfidiso-15693

Connection error when reading Android NfcV tags


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) {
        }
    }
}

Solution

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