Android nfcA.connect()、nfcA.transceive()、nfcA.setTimeout() 和 nfcA.getMaxTransceiveLength()

Android nfcA.connect(), nfcA.transceive(), nfcA.setTimeout() and nfcA.getMaxTransceiveLength()

我有一些 NfcA 新手问题。 docs 和网络上的其他地方似乎对此没有什么指导,所以我希望没有人介意我在这里将几个基本问​​题串在一起...

我正在使用 nfcA.transceive() 数据写入我的 NTAG213 标签,如下所示:

    byte[] result = nfcA.transceive(new byte[] {
            (byte)0xA2,  // WRITE
            (byte)(pageNum & 0x0ff),
            myData[0], myData[1], myData[2], myData[3]
    });

1. result 数组是一个值为 10 的字节。这是什么意思,我还应该注意哪些其他值?

我也在使用相同的方法从我的 NTAG213 标签中读取数据:

    byte[] result = nfcA.transceive(new byte[] {
            (byte)0x30,  // READ
            (byte)(pageNum & 0x0ff)
    });

2. 我预计这是 return 4 个字节的用户数据(即对应于我的 pageNum 的 4 个字节),但它 returned 16 个字节。为什么会这样?

3. 在调用 nfcA.connect() 之前检查 nfcA.isConnected() 是一种好习惯吗?这样做? (我问,因为我从两者的知名来源中看到了代码示例。)

4.nfcA.connect()之前还是之后调用nfcA.setTimeout()比较好?

5. For my NTAG213 tags nfcA.getMaxTransceiveLength() returns 253. 这真的意味着我最多可以写入 251 字节的用户数据(加上其他 2 个字节)一次,如果是这样,建议还是最好用单独的 nfcA.transceive() 调用写入每个页面(4 个字节)?

1。 WRITE 命令的结果数组是一个值为 10 的字节。这是什么意思,我应该注意哪些其他值?

值 10(十六进制的 Ah 或二进制表示的 1010b)是显式 ACK,当 return 没有数据的命令成功时,return 确认。

可能的值为实际数据、ACK、被动 ACK 或 NACK。这些由 NFC 论坛数字协议规范和 NFC 论坛 2 类标签操作规范定义。

  1. 如果命令在成功时预期 return 实际数据,则数据 returned 而不是显式 ACK 值。
  2. ACK 被定义为一个 4 位短帧(参见 NFC 论坛数字协议规范和 ISO/IEC 14443-3 以获取更多详细信息),值为 1010b (Ah)。
  3. 被动 ACK 定义为标签在特定超时时间内根本不发送响应。
  4. NACK 定义为值为 0x0xb(其中 x 为 0 或 1)的 4 位短帧。

NTAG213/215/216 产品数据 sheet 在可能的 NACK 值上更具体一些:

  1. 0000b (0h) 表示命令参数无效。
  2. 0001b (1h) 表示奇偶校验或 CRC 错误。
  3. 0100b (4h) 表示无效的身份验证计数器溢出。
  4. 0101b (5h) 表示 EEPROM 写入错误。

除上述之外,某些 设备上的 NFC 堆栈实现无法正确地将 NACK 响应传播到应用程序。相反,他们要么抛出 TagLostException 或 return null。同样,您可能(?)得到一个 TagLostException 指示被动 ACK。

因此,您通常会检查以下收发方法的结果(除非您发送的命令预计会导致被动 ACK):

try {
   response = nfca.transceive(command);
   if (response == null) {
       // either communication to the tag was lost or a NACK was received
   } else if ((response.length == 1) && ((response[0] & 0x00A) != 0x00A)) {
       // NACK response according to Digital Protocol/T2TOP
   } else {
       // success: response contains ACK or actual data
   }
} catch (TagLostException e) {
   // either communication to the tag was lost or a NACK was received
}

2。我希望 READ 方法能够 return 4 个字节的用户数据(即对应于我的 pageNum 的 4 个字节),但它 returned 16 个字节。为什么会这样?

READ 命令被定义为 return 4 个以指定块号开始的数据块(在 NFC 论坛类型 2 标签操作规范中)。因此,如果您为块 4 发送 READ 命令,您将获得块 4、5、6 和 7 的数据。

3。在调用 nfcA.connect() 之前检查 nfcA.isConnected() 是一种好习惯吗?如果是这样,这样做是否会造成任何重大的性能损失?

如果您直接从 NFC 系统服务(通过 NFC 意图)收到 Tag 句柄,则不会连接标签。因此,除非您在调用 nfca.connect() 之前使用 Tag 句柄,否则我不明白您为什么要先调用 nfca.isConnected()。然而,在连接之前调用该方法几乎没有任何性能开销,因为在关闭标签技术对象上调用 isConnected() 将由 famework API 处理,而无需调用 NFC 系统服务。因此,它并不比 NfcA 对象的布尔成员变量上的简单 if 多多少开销。

4。在nfcA.connect()之前或之后调用nfcA.setTimeout()更好吗?

我不确定那个。但是,收发超时通常会在断开标签技术时重置。

5。对于我的 NTAG213 标签 nfcA.getMaxTransceiveLength() returns 253。这是否真的意味着我可以一次写入最多 251 个字节的用户数据(加上其他 2 个字节),如果是这样,是否可取或用单独的 nfcA.transceive() 调用写入每个页面(4 字节)是否更好?

不可以,一次只能写一个块。这个受限于NTAG213的WRITE命令,只支持一个block作为数据输入。

但是,253 的收发缓冲区大小允许您使用 FAST_READ 命令一次读取多个块(最多 62 个,因此对于 NTAG213 最多 45 个):

int firstBlockNum = 0;
int lastBlockNum = 42;
byte[] result = nfcA.transceive(new byte[] {
        (byte)0x3A,  // FAST_READ
        (byte)(firstBlockNum & 0x0ff),
        (byte)(lastBlockNum & 0x0ff),
});