且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-07 20:37:43

您已经发现,NFC论坛2类标签(例如MIFARE Ultralight,NTAG等)要求将NDEF消息嵌入到NDEF TLV中(标签长度值)结构.这意味着您将标记03和NDEF消息的长度放在消息(值)本身的前面.因此,您得到

As you already found, NFC Forum Type 2 tags (such as MIFARE Ultralight, NTAG, etc.) require an NDEF message to be embedded into a NDEF TLV (tag-length-value) structure. This means that you prepend the tag 03 and the length of the NDEF message to the message (value) itself. Thus, you get

+-----+--------+-------------------------+
| TAG | LENGTH | VALUE                   |
| 03  | 08     | D1 01 04 54 02 65 6E 31 |
+-----+--------+-------------------------+

此外,您可以添加终结器TLV(标签= FE,长度= 00),以指示可以跳过标签上的剩余数据区域.

In addition you may add a Terminator TLV (tag = FE, length = 00) to indicate that the remaining data area on the tag can be skipped from processing.

您使用的NDEF库仅处理 NDEF消息,而不处理将数据存储在NFC标签上所需的容器格式.因此,您需要自己处理该部分.

The NDEF library that you use only processes NDEF messages and not the container format that is needed for storing the data on an NFC tag. Thus, you need to process that part yourself.

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;
}