读取 NFC 标签时出现奇怪的字符
Strange character when reading NFC tag
我正在尝试使用 Android 读取 NFC 标签。我是一名养蜂人,当我接近它们时,这是为了识别我的蜂箱。我在这里搜索过,但在读取标签时仍然遇到问题。我想看课文,但是看课文时,在要看的课文前出现了一个方块字和“十”字样的字。
这是我正在使用的代码。我知道有效负载字节必须正确,我尝试更改它们但无济于事。
private static NdefMessage getTestMessage() {
byte[] mimeBytes = "application/com.android.cts.verifier.nfc"
.getBytes(Charset.forName("US-ASCII"));
byte[] id = new byte[] {1, 3, 3, 7};
byte[] payload = "CTS Verifier NDEF Push Tag".getBytes(Charset.forName("US-ASCII"));
return new NdefMessage(new NdefRecord[] {
new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, id, payload)
});
}
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
mNfcAdapter.setNdefPushMessageCallback(this, this);
}
// sending message
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
return getTestMessage();
}
private NdefMessage[] getNdefMessages(Intent intent) {
Parcelable[] rawMessages = intent
.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMessages != null) {
NdefMessage[] messages = new NdefMessage[rawMessages.length];
for (int i = 0; i < messages.length; i++) {
messages[i] = (NdefMessage) rawMessages[i];
}
return messages;
} else {
return null;
}
}
static String displayByteArray(byte[] bytes) {
String res="";
StringBuilder builder = new StringBuilder().append("");
for (int i = 0; i < bytes.length; i++) {
res+=(char)bytes[i];
}
return res;
}
// displaying message
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
NdefMessage[] messages = getNdefMessages(intent);
edtUser.setText(displayByteArray(messages[0].toByteArray()));
Toast.makeText(this, "NFC tag entered", Toast.LENGTH_LONG).show();
}
由于您尝试将整个原始 NDEF 记录显示为文本字符串(使用一些奇怪的解码方法),因此在显示消息时出现奇怪的附加字符:
NdefMessage[] messages = getNdefMessages(intent);
edtUser.setText(displayByteArray(messages[0].toByteArray()));
这有几个问题。首先,您通常希望使用与编写文本相同的编码来解码文本。例如,如果您使用
String text = "...";
byte[] bytes = text.getBytes(Charset.forName("US-ASCII"));
要获取给定文本字符串的 US-ASCII 编码字节数组,您还需要使用相同的 US-ASCII 编码再次将字节转换为文本字符串:
byte[] bytes = ...;
String text = new String(bytes, "US-ASCII");
其次,您将整个 NDEF 消息解释为文本字符串。但是,您存储在标签上的文本通常只包含在 NDEF 记录的有效负载中。在您的情况下,前缀 "Ten" 表明您使用了带有语言指示 "en"(英语)的 NFC 论坛文本记录(类型名称 "T")。因此,您希望在 NDEF 消息中搜索文本记录:
for (NdefRecord r : messages[0].getRecords()) {
if (r.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
if (Arrays.equals(r.getType(), NdefRecord.RTD_TEXT)) {
找到文本记录后,您可以解码其文本负载。有效载荷由状态字节、语言字段和实际文本组成:
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);
}
}
}
我正在尝试使用 Android 读取 NFC 标签。我是一名养蜂人,当我接近它们时,这是为了识别我的蜂箱。我在这里搜索过,但在读取标签时仍然遇到问题。我想看课文,但是看课文时,在要看的课文前出现了一个方块字和“十”字样的字。
这是我正在使用的代码。我知道有效负载字节必须正确,我尝试更改它们但无济于事。
private static NdefMessage getTestMessage() {
byte[] mimeBytes = "application/com.android.cts.verifier.nfc"
.getBytes(Charset.forName("US-ASCII"));
byte[] id = new byte[] {1, 3, 3, 7};
byte[] payload = "CTS Verifier NDEF Push Tag".getBytes(Charset.forName("US-ASCII"));
return new NdefMessage(new NdefRecord[] {
new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, id, payload)
});
}
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
mNfcAdapter.setNdefPushMessageCallback(this, this);
}
// sending message
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
return getTestMessage();
}
private NdefMessage[] getNdefMessages(Intent intent) {
Parcelable[] rawMessages = intent
.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMessages != null) {
NdefMessage[] messages = new NdefMessage[rawMessages.length];
for (int i = 0; i < messages.length; i++) {
messages[i] = (NdefMessage) rawMessages[i];
}
return messages;
} else {
return null;
}
}
static String displayByteArray(byte[] bytes) {
String res="";
StringBuilder builder = new StringBuilder().append("");
for (int i = 0; i < bytes.length; i++) {
res+=(char)bytes[i];
}
return res;
}
// displaying message
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
NdefMessage[] messages = getNdefMessages(intent);
edtUser.setText(displayByteArray(messages[0].toByteArray()));
Toast.makeText(this, "NFC tag entered", Toast.LENGTH_LONG).show();
}
由于您尝试将整个原始 NDEF 记录显示为文本字符串(使用一些奇怪的解码方法),因此在显示消息时出现奇怪的附加字符:
NdefMessage[] messages = getNdefMessages(intent);
edtUser.setText(displayByteArray(messages[0].toByteArray()));
这有几个问题。首先,您通常希望使用与编写文本相同的编码来解码文本。例如,如果您使用
String text = "...";
byte[] bytes = text.getBytes(Charset.forName("US-ASCII"));
要获取给定文本字符串的 US-ASCII 编码字节数组,您还需要使用相同的 US-ASCII 编码再次将字节转换为文本字符串:
byte[] bytes = ...;
String text = new String(bytes, "US-ASCII");
其次,您将整个 NDEF 消息解释为文本字符串。但是,您存储在标签上的文本通常只包含在 NDEF 记录的有效负载中。在您的情况下,前缀 "Ten" 表明您使用了带有语言指示 "en"(英语)的 NFC 论坛文本记录(类型名称 "T")。因此,您希望在 NDEF 消息中搜索文本记录:
for (NdefRecord r : messages[0].getRecords()) {
if (r.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
if (Arrays.equals(r.getType(), NdefRecord.RTD_TEXT)) {
找到文本记录后,您可以解码其文本负载。有效载荷由状态字节、语言字段和实际文本组成:
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);
}
}
}