Reputation: 7574
I have an app that reads the payload of an NDEF record on MIFARE Ultralight tags.
The payload packed into an NDEF Text record and the text value is in the following format:
1,10,200,Arthur smith
So there always 3 commas that separate the 3 numbers and the name.
I use NXP TagWriter to format the tag and my app can read the payload correctly. The problem is that the company I work for has used a separate company to format the tags for us. Now, when my app scans these tags there is a problem. The payload then reads:
d1,10,200,Arthur smith
This causes my app not to process the tag.
The NXP app can successfully read the tag and if I reformat the tag with the same data using NXP TagWriter then my app will correctly read the tag.
It seems that there is a 'd' in front of the payload when it comes from the formatting company that only my app can see.
Has anyone any ideas of what the 'd' is and how I can fix this?
Here is the code I use to read the payload:
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(i.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(i.getAction())) {
if(NfcScannerApplication.isCanScanNfcTag() == true){
messages = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (messages != null) {
//setContentView(R.layout.successfulnfc);
NfcScannerApplication.startNfcTimer();
//Toast.makeText(this, "NFC timer set", Toast.LENGTH_LONG).show();
Log.e(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one
vibrate(); // signal found messages :-)
// parse to records
for (int i = 0; i < messages.length; i++) {
List<Record> records = null;
try {
records = new Message((NdefMessage)messages[i]);
} catch (FormatException e) {
e.printStackTrace();
}
Log.e(TAG, "Found " + records.size() + " records in message " + i);
for(int k = 0; k < records.size(); k++) {
Log.e(TAG, " Record #" + k + " is of class " + records.get(k).getClass().getSimpleName());
Record record = records.get(k);
NdefRecord ndefRecord = record.getNdefRecord();
byte[] arr = ndefRecord.getPayload();
String payload = new String(arr);
if(payload.length() > 0){
payload = payload.substring(3, payload.length());
Log.e(TAG, "payload = " + payload);
int counter = 0;
for( int z = 0; z < payload.length(); z++ ) {
if( payload.charAt(z) == ',' ) {
counter++;
}
}
if(counter == 3){
//Toast.makeText(this, "comma count = 3 ", Toast.LENGTH_SHORT).show();
String[] splitPayload = payload.split(",");
String tagType = splitPayload[0];
String tagCompany = splitPayload[1];
String tagClientID = splitPayload[2];
String tagClientName = splitPayload[3];
Upvotes: 1
Views: 1220
Reputation: 40831
Your code does not properly decode the payload of the NDEF Text record. You are assuming that the payload is UTF-8 encoded (default encoding on Android) and that the actual text value starts at offset 3 of that decoded string:
NdefRecord ndefRecord = record.getNdefRecord();
byte[] arr = ndefRecord.getPayload();
String payload = new String(arr);
payload = payload.substring(3, payload.length());
However, these assumptions are wrong. A Text record consists of a Status byte, followed by a variable(!) length language code (US-ASCII encoded), and the text value itself (either encoded in UTF-8 or UTF-16). Consequently, the additional "d" that you are seeing may be actually be part of the language code or may be a result of decoding incorrect character codes (e.g. the value of the Status byte) into a UTF-8 string.
Therefore, in order to get the text value, you first have to Status byte to find the length of the language code and the encoding of the text value:
byte[] payloadBytes = ndefRecord.getPayload();
boolean isUTF8 = (payloadBytes[0] & 0x080) == 0; //status byte: bit 7 indicates encoding (0 = UTF-8, 1 = UTF-16)
int languageLength = payloadBytes[0] & 0x03F; //status byte: bits 5..0 indicate length of language code
int textLength = payloadBytes.length - 1 - languageLength;
String languageCode = new String(payloadBytes, 1, languageLength, "US-ASCII");
String payloadText = new String(payloadBytes, 1 + languageLength, textLength, isUTF8 ? "UTF-8" : "UTF-16");
Upvotes: 3
Reputation: 7574
It turns out there is a bug in the NXP TagWiter app that is prepending the 'd'. I am forced to wait for the update from NXP that fixes this issue.
Thanks for your help.
Upvotes: 0
Reputation: 77
My guess is that it could be something that the formatting company is doing to the tags they create as to make sure your company can't switch from them as easily.
However, I don't see why you couldn't just check the payload for the initial "d" and then just strip it if its found.
Upvotes: 0