ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用低级NFC通信方法将NDEF数据写入NTAG216标记

2019-10-05 16:04:53  阅读:295  来源: 互联网

标签:ndef android java nfc mifare


我已经通过低级通信方法(遵循NTAG212 Mifare Ultralight with Authentication和NTAG216的数据表)实现了与NTAG216交互的代码.

到目前为止我取得的成就:

>如果未设置,则设置NTAG216上的密码写保护或新/空标记.
>如果已设置密码,请使用PWD_AUTH进行身份验证并比较PACK.
>读取数据.
>写入/覆盖数据.

到目前为止我还没能做到:

>检测我写入其他应用程序中的标记的NDEF消息.换句话说,我可以使用writePage()方法写入标记,也可以使用readPage()读取标记.但是,在写入页面时,我将NdefMessage转换为可以读取和写入的字节数组.但是,在其他应用程序中未检测到此NDEF消息.

为了能够检测到我从其他应用程序编写的NDEF消息,我需要做什么?

解决方法:

NTAG216是NFC论坛类型2标签.因此,在将数据写入此类NFC标签时,您必须遵循NFC论坛Type 2 Tag Operation specification.

因此,您需要遵循一些规则,以便可以将标记作为NDEF标记(类型2标记)发现:

首先,需要配置能力容器(位于块3中).

>字节0必须设置为“魔术”值0xE1.
>字节1必须设置为0x10以指示映射版本1.0.
>字节2必须设置为0x6D以指示NTAG216的内存大小.
>字节3可以设置为0x00以指示对NDEF数据的读/写访问,或者设置为0x0F以指示只读访问(请注意这些是应用程序层的权限).

因此,您可以将功能容器编写为:

byte[] response = nfc.transceive(new byte[] {
    (byte)0xA2, // WRITE
    (byte)3,    // block address
    (byte)0xE1, (byte)0x10, (byte)0x6D, (byte)0x00
});

NTAG216已经附带了正确配置的功能容器,因此无需手动执行此操作.另请注意,块3是一次性可编程的,这意味着位只能设置为1,但不能再次清零.因此,如果您已使用不同的值覆盖功能容器,则该标记很可能不再用作NDEF标记.

必须将数据写入从块4开始的数据块.必须将NDEF消息包装成NDEF消息TLV(tag-length-value)结构.此TLV的标记是0x03.长度可以是单字节格式(对于长度在0到254字节之间的NDEF消息),也可以是三字节格式(对于长度为255或更多字节的NDEF消息).此TLV块的数据是实际的NDEF消息(您可以从ndefMessage.toByteArray()获取).

例如,对于NDEF消息D1 01 0C 55 01 65 78 61 6D 70 6C 65 2E 63 6F 6D 2F(这是一个URL为“http://www.example.com/”的URI记录),您将获得以下TLV结构:

03 11 D1010C55016578616D706C652E636F6D2F

如果你有更长的NDEF消息(例如一个有259字节的消息),你将使用三字节长度格式:

03 FF0103 D101FF5501...

此外,您应该使用Terminator TLV(标记0xFE,没有长度和数据字段)标记标记上数据的结尾:

FE

然后,您可以将此数据写入标记:

byte[] ndefMessage = new byte[] {
    (byte)0xD1, (byte)0x01, (byte)0x0C, (byte)0x55, (byte)0x01, (byte)0x65, (byte)0x78, (byte)0x61, (byte)0x6D, (byte)0x70, (byte)0x6C, (byte)0x65, (byte)0x2E, (byte)0x63, (byte)0x6F, (byte)0x6D, (byte)0x2F
};

// wrap into TLV structure
byte[] tlvEncodedData = null;
if (ndefMessage.length < 255) {
    tlvEncodedData = new byte[ndefMessage.length + 3];
    tlvEncodedData[0] = (byte)0x03;  // NDEF TLV tag
    tlvEncodedData[1] = (byte)(ndefMessage.length & 0x0FF);  // NDEF TLV length (1 byte)
    System.arraycopy(ndefMessage, 0, tlvEncodedData, 2, ndefMessage.length);
    tlvEncodedData[2 + ndefMessage.length] = (byte)0xFE;  // Terminator TLV tag
} else {
    tlvEncodedData = new byte[ndefMessage.length + 5];
    tlvEncodedData[0] = (byte)0x03;  // NDEF TLV tag
    tlvEncodedData[1] = (byte)0xFF;  // NDEF TLV length (3 byte, marker)
    tlvEncodedData[2] = (byte)((ndefMessage.length >>> 8) & 0x0FF);  // NDEF TLV length (3 byte, hi)
    tlvEncodedData[3] = (byte)(ndefMessage.length & 0x0FF);          // NDEF TLV length (3 byte, lo)
    System.arraycopy(ndefMessage, 0, tlvEncodedData, 4, ndefMessage.length);
    tlvEncodedData[4 + ndefMessage.length] = (byte)0xFE;  // Terminator TLV tag
}

// fill up with zeros to block boundary:
tlvEncodedData = Arrays.copyOf(tlvEncodedData, (tlvEncodedData.length / 4 + 1) * 4);
for (int i = 0; i < tlvEncodedData.length; i += 4) {
    byte[] command = new byte[] {
        (byte)0xA2, // WRITE
        (byte)((4 + i / 4) & 0x0FF), // block address
        0, 0, 0, 0
    };
    System.arraycopy(tlvEncodedData, i, command, 2, 4);
    byte[] response = nfc.transceive(command);
}

最后,请注意,如果您在NDEF数据区域设置了读取密码,则无法将标记用作NDEF标记,因为NFC论坛类型2标记操作规范要求标记可以自由读取.

标签:ndef,android,java,nfc,mifare
来源: https://codeday.me/bug/20191005/1856565.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有