如何使用与 Android 兼容的 C# 以 NDEF 格式读取和写入 NFC 标签?

Viv*_*ara 3 c# format wpf nfc ndef

我正在使用Mifare Ultralight C标签并向它们写入 NDEF 格式的数据。我正在使用NDEF-NFC 库为我的 NDEF 消息创建原始字节。我的 NDEF 消息是

var spRecord = new NdefTextRecord {
        Text = "1",
        LanguageCode = "en"
};
var msg = new NdefMessage { spRecord };
Run Code Online (Sandbox Code Playgroud)

我得到的输出是D1 01 04 54 02 65 6E 31(十六进制)。如果我按原样将此字节数组写入标签:

  • 从标签读取并使用相同的 NDEF-NFC 库后,我可以转换回所需的 NDEF 消息。
  • Android 应用程序无法识别 NDEF 消息。我尝试了 Android 的NFC 工具

按照使用 ACR122U 作为 Reader/Writer 在 Windows 窗体应用程序 C# 中将 Ndef 写入 NFC 标签中的建议,我修改了我的字节数组以写入而不是库生成的原始字节数组。03 08 D1 01 04 54 02 65 6E 31 FE 00

  • 现在我可以使用 Android 应用程序读取 NDEF 消息。

  • 但是在尝试使用库将字节数组转换为 NDEF 消息对象时,出现以下错误:

    Ndef 解析错误:第一条记录中缺少预期的消息开始。

如何正确读回 NDEF 消息?

Mic*_*and 6

正如您已经发现的,NFC 论坛类型 2 标签(例如 MIFARE Ultralight、NTAG 等)需要将 NDEF 消息嵌入到 NDEF TLV(标签长度值)结构中。这意味着您将标记03和 NDEF 消息的长度添加到消息(值)本身之前。因此,你得到

+-----+--------+-------------------------+
| TAG | LENGTH | VALUE                   |
| 03  | 08     | D1 01 04 54 02 65 6E 31 |
+-----+--------+-------------------------+
Run Code Online (Sandbox Code Playgroud)

此外,您可以添加一个 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;
Run Code Online (Sandbox Code Playgroud)

从 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;
}
Run Code Online (Sandbox Code Playgroud)