1
votes

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];
3
How do you read the payload in your app? How do you write the payload (i.e. what format did you chose) with NXP TagWriter? - Michael Roland
I've done a bit of research with the NFC tag formatting company and they load the data on to the tag via .csv file in NXP TagWriter. If they write the data to the tags manually one by one then there is no 'd' prepended. It would seem that the 'd' appears when loaded from a excel spead sheet??? - turtleboy
The format i use when using NXP tagwriter is plain text. I can post you my source code with regards to the code i use to read the payload. [EDIT1] - turtleboy

3 Answers

3
votes

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");
0
votes

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.

0
votes

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.