我刚刚开始使用Android NFC编码,我已成功读取和编写NIFF数据到mifare经典标签。问题是当app从ndef记录中读取有效负载时,它总是在文本的开头包含字符'* en'。我认为这是语言特征,但是如何在没有该角色的情况下获得真正的短信?
这是从标签读取的应用程序的屏幕截图,实际文本是“Hello World”
这是要阅读的代码
@Override
public void onNewIntent(Intent intent) {
Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
// mText.setText("Discovered tag NDEF " + ++mCount + " with intent: " + intent);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
NdefMessage[] msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
NdefMessage msg = msgs[0];
try {
mText.setText(new String(msg.getRecords()[0].getPayload(), "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
答案 0 :(得分:14)
您所看到的是转换为UTF8的NDef文本记录的原始数据。
NDef文本记录的构建如下:
第一个字节:Control-Byte
位7:0:文本以UTF-8编码1:文本编码为 UTF16
位6:RFU(必须设置为零)
位5..0:IANA语言代码的长度。
接下来是语言代码,存储在US-ASCII(在您的情况下为en)中,如RFC 3066中所定义。语言代码的长度在控制字节中给出。
接下来是控制字节的第7位指定格式的文本。
空方字符来自您将原始数据转换为UTF-8。我几乎可以肯定你的情况下的控制字节有数值2.由于这个数值没有可打印的字符,它将被unicode-set中的不可打印的占位符字符替换。这通常显示为空方块。
答案 1 :(得分:0)
这就是我在 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}")
}
}
答案 2 :(得分:0)
这是我在类似的帖子中找到的答案。
在读取NFC标签时,这将隔离消息并在消息的开头排除语言代码。
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");
edtUser.setText(payloadText);