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}")
}
}