1
votes

I have developed a multi-purpose NFC app, which is capable of reading from and writing to different types of tags and in different types of formats, including External Type, RTD Text, and RTD URI. There is, however, a problem with parsing and reading the "TNF_WELL_KNOWN" Smart Poster contents. More specifically, and to begin with the problem I have, I used well-known "NFC TagWriter" app on Android to create a simple contact content. This contact contains a name, e.g., "Police", and a phone number, e.g., "911". When trying to read the same content using yet another popular app called "NFC TagInfo", I am able to successfully read the Smart Poster, showing exactly what it is supposed to show:

WELL-KNOWN: urn:nfc:wkt:Sp (Smart Poster)

  1. WELL-KNOWN: urn:nfc:wkt:U (URI) Identifier: 0x05 ("tel:") "911"
  2. WELL-KNOWN: urn:nfc:wkt:U (Text) Encoding: UTF-8 Language: en "Police"

On the other hand, I am not able to achieve the same. Here is the code I came up with as an attempt to decode the aforementioned content:

First I extract the NDEF Message(s) and their corresponding NDEF Record(s):

 // Use NdefMessage[] getNdefMessages(Intent) method to extract NDEF Message(s)

 NdefMessage[] ndefMessages = getNdefMessages(intent);
 for(int i = 0; i < ndefMessages.length; i++) {

    ndefRecords = ndefMessages[i].getRecords();

    for (int j = 0; j < ndefRecords.length; j++) { 

        // NDEF Record parsing snippet comes here!
        if (ndefRecords[j].getTnf() == NdefRecord.TNF_WELL_KNOWN) {

           // If TNF indicates a "Well-known" type,
           // determine the type using "Type" field  

           if (Arrays.equals(ndefRecords[j].getType(),  NdefRecord.RTD_SMART_POSTER)) {

               // First try to decode the content
               payload = new String(ndefRecords[j].getPayload(), 1, ndefRecords[j].getPayload().length - 1, Charset.forName("UTF-8"));
               Log.i(TAG, "Content: " + payload);

               // Second try to decode the content
               Log.i(TAG, "Content: " + ndefRecords[j].toUri());
           }
         }
       }
    }

When looking at the Logcat output, the first Log.i prints:

U911Q   TenPolice

While the second prints:

tel:911

It appears to me that the NFC TagWriter app creates a nested NDEF Record, in which one URI type and one Text type are concatenated. I am trying to figure out how to get this content decoded successfully. The first attempt removes the payload header and decodes the remaining part of NDEF Record payload. Clearly, the first part contains the "tel:911" content and the second part contains "Police", where "en" indicates the language. The second attempt uses the NDEFRecord class' toUri() helper method, which according to API documentation is able to extract RTD URIs. I am wondering in order to extract all nested records, we could decode one, convert that to byte[] array and remove from the payload, which will be re-iterated for yet another decoding. Though, this approach looks really inefficient. So, I would like to know what other experts suggest on how to approach this problem.

[UPDATE] Following is a short snippet to compose an Smart Poster NDEF Record for those interested:

NdefRecord uriNdefRecord = NdefRecord.createUri(Uri.parse((String) o[0])); //RTD_URI
NdefRecord textNdefRecord = createTextRecord((String) o[1], Locale.US, true); //RTD_TEXT
NdefRecord[] recs = new NdefRecord[]{uriNdefRecord, textNdefRecord};
NdefMessage smartPosterpContentMessage = new NdefMessage(recs);
byte[] bytes = smartPosterpContentMessage.toByteArray();
NdefRecord newRec = new NdefRecord((short) 0x01, NdefRecord.RTD_SMART_POSTER, null, bytes);
ndefMessageWriter(new NdefMessage(newRec));   

In the above snippet, the "ndefMessageWriter" uses a thread to communicate with the tag and write the content to it.

1
why you are reposting the question? check: "Text Record Type Definition" section 3.2.1Selvin
I added more description, hoping to give more information, and decided to re-post it (removing the old one, which I guess you voted down!). Instead of voting down, give some comments to help people improve their posts and help others, including myself, learn something!Kevin Ghaboosi
instead asking the question here use google ... i've already find the answer(and no, i will not share it with you, becuase you did not do some research by your own)Selvin
I know what you are talking about as I indeed did my research. The one you are talking about can be found all over the Internet but not the one I am asking here. For example you might refer to this: link or many others. I am able to decode RTD_TEXT and RTD_URI with no problem. The question here is the RTD type is Smart Poster which contain two sub-records (I think). I might be missing something, so let me know what I am missing.Kevin Ghaboosi
Your comment "check: "Text Record Type Definition" section 3.2.1"" is not related to this thread as I have described in my description. Michael gave the right link and suggestions.Kevin Ghaboosi

1 Answers

3
votes

As you correctly found out the Smart poster record contains a Text record and a URI record as its payload. So all you have to do to get these records is to decode the Smart poster records payload (btw. if you had Googled for "Smart poster record" you would have quickly come up with the Smart Poster Record Type Definition Specification, grab it here).

You already found out that the SP record contains an NDEF message, so you would decode the record's payload as an NDEF message:

NdefMessage spContentMsg = new NdefMessage(spRecord.getPayload());

Now you have an NDEF message which, per specification, contains at least one URI record and some other optional records (e.g. one descriptive Text record for each language):

NdefRecord[] spContentRecs = spContentMsg.getRecords();
for (NdefRecord rec : spContentRecs) {
    if (rec.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
       if (Arrays.equals(rec.getType(),  NdefRecord.RTD_URI)) {
           // do something
       } else if (Arrays.equals(rec.getType(),  NdefRecord.RTD_TEXT)) {
           // do something
       }
     }
   }
}

Btw, most of the NFC Forum's specifications are well written and easy to follow (particularly the various NDEF and RTD related specifications).