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)
- WELL-KNOWN: urn:nfc:wkt:U (URI) Identifier: 0x05 ("tel:") "911"
- 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.