如何使用兼容Android的C#读写NDEF格式的NFC标签?
How to read and write to NFC tags in NDEF format using C# compatible with Android?
我正在使用 Mifare Ultralight C tags and write data in NDEF format to them. Am using NDEF-NFC library 为我的 NDEF 消息创建原始字节。我的 NDEF 消息是
var spRecord = new NdefTextRecord {
Text = "1",
LanguageCode = "en"
};
var msg = new NdefMessage { spRecord };
我得到的输出是D1 01 04 54 02 65 6E 31
(十六进制)。如果我按原样将此字节数组写入标签:
- 从标签读取并使用相同的 NDEF-NFC 库后,我能够转换回所需的 NDEF 消息。
- Android 应用程序无法识别 NDEF 消息。我试过 NFC Tools Android.
按照 中的建议,我将字节数组修改为<b>03 08</b> D1 01 04 54 02 65 6E 31 <b>FE 00</b>
而不是库生成的原始字节数组。
现在我可以使用 Android 应用程序阅读 NDEF 消息。
但是在尝试使用库将字节数组转换为 NDEF 消息对象时,出现以下错误:
Ndef parse error: Expected Message Begin missing in first record.
如何正确读回 NDEF 消息?
如您所知,NFC Forum Type 2 标签(例如 MIFARE Ultralight、NTAG 等)需要将 NDEF 消息嵌入到 NDEF TLV(标签-长度-值)结构中。这意味着您将标记 03
和 NDEF 消息的长度添加到消息(值)本身。因此,你得到
+-----+--------+-------------------------+
| TAG | LENGTH | VALUE |
| 03 | 08 | D1 01 04 54 02 65 6E 31 |
+-----+--------+-------------------------+
另外你可以添加一个Terminator TLV (tag = FE
, length = 00
)来表示标签上剩余的数据区域可以跳过处理。
您使用的 NDEF 库仅处理 NDEF 消息,而不处理在 NFC 标签上存储数据所需的容器格式。因此,您需要自己处理该部分。
将NDEF报文打包成TLV结构
var msg = new NdefMessage { ... };
var msgBytes = msg.toByteArray();
var ndefTlvLen = new byte[(msgBytes.Length < 255) ? 1 : 3];
if (msgBytes.Length < 255) {
ndefTlvLen[0] = (byte)(msgBytes.Length);
} else {
ndefTlvLen[0] = (byte)0x0FF;
ndefTlvLen[1] = (byte)((msgBytes.Length >> 8) & 0x0FF);
ndefTlvLen[2] = (byte)(msgBytes.Length & 0x0FF);
}
var tagData = new byte[1 + ndefTlvLen.Length + msgBytes.Length + 2];
int offset = 0;
tagData[offset++] = (byte)0x003;
Array.Copy(ndefTlvLen, 0, tagData, offset, ndefTlvLen.Length);
offset += ndefTlvLen.Length;
Array.Copy(msgBytes, 0, tagData, offset, msgBytes.Length);
offset += msgBytes.Length;
tagData[offset++] = (byte)0x0FE;
tagData[offset++] = (byte)0x000;
从 TLV 结构中解压 NDEF 消息
var tagData = ...; // byte[]
var msg;
int offset = 0;
while (offset < tagData.Length) {
byte tag = tagData[offset++];
int len = (tagData[offset++] & 0x0FF);
if (len == 255) {
len = ((tagData[offset++] & 0x0FF) << 8);
len |= (tagData[offset++] & 0x0FF);
}
if (tag == (byte)0x03) {
var msgBytes = new byte[len];
Array.Copy(tagData, offset, msgBytes, 0, len);
msg = NdefMessage.FromByteArray(msgBytes);
} else if (tag == (byte)0xFE) {
break;
}
offset += len;
}
我正在使用 Mifare Ultralight C tags and write data in NDEF format to them. Am using NDEF-NFC library 为我的 NDEF 消息创建原始字节。我的 NDEF 消息是
var spRecord = new NdefTextRecord {
Text = "1",
LanguageCode = "en"
};
var msg = new NdefMessage { spRecord };
我得到的输出是D1 01 04 54 02 65 6E 31
(十六进制)。如果我按原样将此字节数组写入标签:
- 从标签读取并使用相同的 NDEF-NFC 库后,我能够转换回所需的 NDEF 消息。
- Android 应用程序无法识别 NDEF 消息。我试过 NFC Tools Android.
按照<b>03 08</b> D1 01 04 54 02 65 6E 31 <b>FE 00</b>
而不是库生成的原始字节数组。
现在我可以使用 Android 应用程序阅读 NDEF 消息。
但是在尝试使用库将字节数组转换为 NDEF 消息对象时,出现以下错误:
Ndef parse error: Expected Message Begin missing in first record.
如何正确读回 NDEF 消息?
如您所知,NFC Forum Type 2 标签(例如 MIFARE Ultralight、NTAG 等)需要将 NDEF 消息嵌入到 NDEF TLV(标签-长度-值)结构中。这意味着您将标记 03
和 NDEF 消息的长度添加到消息(值)本身。因此,你得到
+-----+--------+-------------------------+
| TAG | LENGTH | VALUE |
| 03 | 08 | D1 01 04 54 02 65 6E 31 |
+-----+--------+-------------------------+
另外你可以添加一个Terminator TLV (tag = FE
, length = 00
)来表示标签上剩余的数据区域可以跳过处理。
您使用的 NDEF 库仅处理 NDEF 消息,而不处理在 NFC 标签上存储数据所需的容器格式。因此,您需要自己处理该部分。
将NDEF报文打包成TLV结构
var msg = new NdefMessage { ... };
var msgBytes = msg.toByteArray();
var ndefTlvLen = new byte[(msgBytes.Length < 255) ? 1 : 3];
if (msgBytes.Length < 255) {
ndefTlvLen[0] = (byte)(msgBytes.Length);
} else {
ndefTlvLen[0] = (byte)0x0FF;
ndefTlvLen[1] = (byte)((msgBytes.Length >> 8) & 0x0FF);
ndefTlvLen[2] = (byte)(msgBytes.Length & 0x0FF);
}
var tagData = new byte[1 + ndefTlvLen.Length + msgBytes.Length + 2];
int offset = 0;
tagData[offset++] = (byte)0x003;
Array.Copy(ndefTlvLen, 0, tagData, offset, ndefTlvLen.Length);
offset += ndefTlvLen.Length;
Array.Copy(msgBytes, 0, tagData, offset, msgBytes.Length);
offset += msgBytes.Length;
tagData[offset++] = (byte)0x0FE;
tagData[offset++] = (byte)0x000;
从 TLV 结构中解压 NDEF 消息
var tagData = ...; // byte[]
var msg;
int offset = 0;
while (offset < tagData.Length) {
byte tag = tagData[offset++];
int len = (tagData[offset++] & 0x0FF);
if (len == 255) {
len = ((tagData[offset++] & 0x0FF) << 8);
len |= (tagData[offset++] & 0x0FF);
}
if (tag == (byte)0x03) {
var msgBytes = new byte[len];
Array.Copy(tagData, offset, msgBytes, 0, len);
msg = NdefMessage.FromByteArray(msgBytes);
} else if (tag == (byte)0xFE) {
break;
}
offset += len;
}