How to read and write to NFC tags in NDEF format using C# compatible with Android?

旧街凉风 提交于 2019-12-11 06:09:12

问题


I am working with Mifare Ultralight C tags and write data in NDEF format to them. Am using NDEF-NFC library to create raw bytes for my NDEF message. My NDEF message is

var spRecord = new NdefTextRecord {
        Text = "1",
        LanguageCode = "en"
};
var msg = new NdefMessage { spRecord };

The output I get is D1 01 04 54 02 65 6E 31 (hexadecimal). If I write this byte array to the tag as-is:

  • After reading from the tag and using the same NDEF-NFC library I am able to convert back to the desired NDEF message.
  • Android applications do not recognize the NDEF message. I tried NFC Tools for Android.

Following the suggestions in Writing Ndef to NFC tag in Windows Form Application C# using ACR122U as Reader/Writer, I modified my byte array to write 03 08 D1 01 04 54 02 65 6E 31 FE 00 instead of the original byte array produced by the library.

  • Now I'm able to read the NDEF message using Android apps.
  • But on trying to convert the byte array to an NDEF message object using the library, I get the following error:

    Ndef parse error: Expected Message Begin missing in first record.

How can I read back the NDEF message correctly?


回答1:


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 |
+-----+--------+-------------------------+

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.

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.

Pack NDEF message into TLV structure

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;

Unpack NDEF message from TLV structure

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


来源:https://stackoverflow.com/questions/38359491/how-to-read-and-write-to-nfc-tags-in-ndef-format-using-c-sharp-compatible-with-a

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!