Strange character on Android NDEF record payload

What you're seeing is the raw data of an NDef text-record converted to UTF8.

The NDef text-record is build like this:

First byte: Control-Byte

Bit 7: 0: The text is encoded in UTF-8 1: The text is encoded in UTF16

Bit 6: RFU (MUST be set to zero)

Bit 5..0: The length of the IANA language code.

This is followed by the language code, stored in US-ASCII (en in your case) as defined in RFC 3066. The length of the language-code is given in the control-byte.

And this is followed by the text in the format as specified by bit 7 of the control-byte.

The empty square character comes from your conversion of raw data into UTF-8. I'm almost sure that the control-byte in your case has the numeric value 2. Since there is no printable character for this numeric value it gets replaced with the non-printable placeholder character from the unicode-set. This is usually displayed as an empty square.


Here's what I did in Kotlin on API 29:

// ... in the onIntent(...) method
val parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)

parcelables?.let {
    try {
        val inNdefMessage = parcelables[0] as NdefMessage
        val inNdefRecords = inNdefMessage.records

        // convert the payload to string and drop 3 characters to get
        // rid of the " en" prefix
        val payload = inNdefRecords[0].payload

        // figure out if we need to take out the " en" at the beginning
        val textEncoding = if(payload[0] and 128.toByte() == 0.toByte()) "UTF-8" else "UTF-16"
        val langCodeLength = payload[0] and 63.toByte()

        // create a string starting by skipping the first 3 characters
        // based on the language code length
        var inMessage = String(
            payload,
            langCodeLength + 1,
            payload.count() - langCodeLength - 1,
            charset(textEncoding))

        // try to convert the message to json
        try {
            val json = JsonParser().parse(inMessage)

            // ... use json or whatever here
        } catch (error: Exception) {
            println("NFC tag data seems to invalid:\n\n$inMessage\n\n${error.localizedMessage}")
        }

        // ... do whatever
    } catch (error: Exception) {
        println("Error attempting to pull tag info: ${error.localizedMessage}")
    }
}

Tags:

Android

Nfc

Ndef