I am writing an Android app which is supposed to authenticate with a write protected NTAG213 NFC tag from NXP. Using the proper password everything works fine and I get the PACK in return.
Trying to authenticate with a wrong password, my code does not behave as expected. According to the tag's description I should receive a NAK in this case but instead I get a TagLostException
. Or do I get it wrong and everything behaves as expected? How can I then distinguish between a wrong password and an actual TagLostException
?
I would be grateful, if anyone was able to tell me what I am doing wrong.
try {
nfcA.connect();
byte[] response = nfcA.transceive(new byte[]{
NTAG213_PWD_AUTH, mTagPassword[0], mTagPassword[1],
mTagPassword[2], mTagPassword[3]
});
// checking if response was a NAK
if (((byte) 0x00 == response[0]) ||
((byte) 0x01 == response[0]) ||
((byte) 0x04 == response[0]) ||
((byte) 0x05 == response[0])) {
nfcA.close();
result.setErrorCode(WRONG_PASSWORD);
return result;
}
}catch (TagLostException e){
result.setErrorCode(TAG_LOST_EXCEPTION);
e.printStackTrace();
return result;
}catch (IOException e){
result.setErrorCode(IO_EXCEPTION);
e.printStackTrace();
return result;
}
You are right that the tag will answer with a NACK response if the authentication command fails. This is just the same as for the case when a tag does not support a command.
Unfortunately, the various Android NFC stack implementations handle a NACK response in different ways. They either return the NACK value in the response byte array, return an empty response (?), or they generate an IOException
(typically a TagLostException
). Consequently, you cannot reliably distingush between cases where authentication failed, the command was not supported, or the communication with the tag as actually interrupted.
In order to detect if the tag is still there (and thus, it was just the command that failed for whatever reason), you could issue a READ command (or some other command that you would expect to succeed for your specific tag type) afterwards. If that fails as well, you can be certain that communication with the tag was lost.
Note that you need to disconnect (NfcA.close()
) and reconnect (NfcA.connect()
) the tag after a failed command and before you continue to send other commands. This should be done regardless of whether you received an IOException
or an actual NACK response value from the transceive()
method. This is usually necessary in order to reset the state of the tag after any command failure.