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

标签 android tags response nfc mifare

我有许多新手 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. 我希望这会返回 4 个字节的用户数据(即对应于我的 pageNum 的 4 个字节),但它返回了 16 个字节。为什么会这样?

3. 在调用 nfcA.isConnected() 之前检查 nfcA.connect() 是否是一种好习惯,如果是这样,这样做是否可能会产生任何显着的性能损失? (我问,因为我已经看到了来自有信誉的来源的代码示例。)

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

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

最佳答案

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

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

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

  • 如果希望命令在成功时返回实际数据,则返回数据而不是显式 ACK 值。
  • ACK 定义为 4 位短帧(有关详细信息,请参阅 NFC 论坛数字协议(protocol)规范和 ISO/IEC 14443-3),其值为 1010b (Ah)。
  • 被动 ACK 定义为标签在特定超时内根本不发送响应。
  • NACK 定义为 4 位短帧,值为 0x0xb(其中 x 为 0 或 1)。

  • NTAG213/215/216 产品数据表对可能的 NACK 值更具体一点:
  • 0000b (0h) 表示命令参数无效。
  • 0001b (1h) 表示奇偶校验或 CRC 错误。
  • 0100b (4h) 表示无效的身份验证计数器溢出。
  • 0101b (5h) 表示 EEPROM 写入错误。

  • 除了上述之外,某些设备上的 NFC 堆栈实现不会正确地将 NACK 响应传播到应用程序。相反,他们要么抛出 TagLostException 要么返回 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 方法返回 4 个字节的用户数据(即与我的 pageNum 对应的 4 个字节),但它返回了 16 个字节。为什么会这样?

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

    3. 在调用 nfcA.isConnected() 之前检查 nfcA.connect() 是否是一种好习惯,如果是这样,这样做是否可能会产生任何显着的性能损失?

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

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

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

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

    不,你一次只能写一个 block 。这受到 NTAG213 的 WRITE 命令的限制,它只支持一个 block 作为数据输入。

    但是,253 的收发缓冲区大小允许您使用 FAST_READ 命令一次读取多个 block (最多 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),
    });
    

    关于Android nfcA.connect()、nfcA.transceive()、nfcA.setTimeout() 和 nfcA.getMaxTransceiveLength(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40288795/

    相关文章:

    android - 如何在不下载图片的情况下从图片网址创建文件

    android - 发生 fragment 加载闪烁时带有导航组件的底部导航

    javascript - 如何使用 jquery 将一个标签替换为另一个标签并保留属性?

    python - BS4 find_all 在空间中带有标签

    java - response.sendRedirect() 和 request.getRequestDispatcher().forward(request,response) 有什么区别

    javascript - 在响应函数中调用await

    jquery - 如何得到回应?

    android-layout - 图像渲染不佳(触摸屏幕后)

    java - 在 Android 上存储和检索值

    java - Android NFC 写入 NFCA 标签