我正在编写一个Android应用程序来编写NFC标签,我一直看到这样的例子:
private NdefRecord createTextRecord(String content){
try {
byte[] language;
language = Locale.getDefault().getLanguage().getBytes("UTF-8");
final byte[] text = content.getBytes("UTF-8");
final int languageSize = language.length;
final int textLength = text.length;
final ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + languageSize + textLength);
payload.write((byte) (languageSize & 0x1F)); // <----- LOOK HERE
payload.write(language, 0, languageSize);
payload.write(text, 0, textLength);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());
}
catch (UnsupportedEncodingException e){
Log.e("createNdefMessage",e.getMessage());
}
return null;
}
请注意payload.write((byte) (languageSize & 0x1F));
部分。那个0x1F
位掩码怎么了?起初我认为规范只允许5位来描述编码的长度,但这没有意义,因为我们总是编写一个完整的字节。
有关NDEF规范的示例,请参阅here和here。有关使用此神秘0x1F
掩码的更多示例,请参阅here和here。
我错过了什么吗?
编辑:由于我已经回答了我自己的问题,而且我不完全确定我是否正确,如果其他人可以提供更好的解释或更多的见解,我会选择你的答案。答案 0 :(得分:2)
NDEF文本记录是通用NDEF记录结构的一个版本,其特征在于类型名称格式(TNF字段)代码1(由NFC论坛分配的众所周知的记录类型名称)和类型名称(TYPE)字段)“T”(0x54)。
对于NFC论坛众所周知的类型名称“T”,NDEF记录PAYLOAD的结构由“NFC论坛文本记录类型定义”规范给出。
文本记录有效负载由状态字节,后跟可变长度语言代码和实际的UTF-8或UTF-16编码文本内容组成。状态字节的最高有效位对于UTF-8为0,对于UTF-16编码为1。下一位是保留的。 6个最低有效位表示语言代码占用的字节数。位掩码0x1F对应于字节的5个最低有效位,与规范文本不匹配。此外,后续行写入languageSize
个字节而不应用相同的掩码,因此可能会创建一个错误的NDEF文本记录,其中语言代码的尾部成为文本内容的一部分。
作为示例有效负载,字节序列02656e48656c6c6f20576f726c64
以状态字节0x02开头,用于2字节语言代码“en”(0x65,0x6e),后跟UTF-8编码文本“Hello World”。
答案 1 :(得分:0)
感谢代码here中的评论......
byte MASK = (byte) 0x1F;
if ((tagFirstOctet & MASK) == MASK) { // EMV book 3, Page 178 or Annex B1 (EMV4.3)
...我能够在page 156 of EMV 4.3 Book 3上找到我问题的部分答案。
似乎低5位描述编码,用于tag number
,前3位用于描述class
和object
,因此:
b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Meaning
---------------------------------------------------------------
0 | 0 | | | | | | | Universal class
0 | 1 | | | | | | | Application class
1 | 0 | | | | | | | Context-specific class
1 | 1 | | | | | | | Private class
| | 0 | | | | | | Primitive data object
| | 1 | | | | | | Constructed data object
| | | 1 | 1 | 1 | 1 | 1 | See subsequent bytes
| | | Any other value <31 | Tag number
According to ISO/IEC 8825, Table 36 defines the coding rules of the
subsequent bytes of a BER-TLV tag when tag numbers ≥ 31 are used
(that is, bits b5 - b1 of the first byte equal '11111').
b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Meaning
---------------------------------------------------------------
1 | | | | | | | | Another byte follows
0 | | | | | | | | Last tag byte
| Any value > 0 | (Part of) tag number
因此,似乎使用(languageSize & 0x1F)
的建议不正确,至少出于以下原因:
universal class
和primitive data
由于我已经回答了我自己的问题,而且我不完全确定我是否正确,如果其他人可以提供更好的解释或更多的见解,我会选择你的答案。