如何正确写入MifareUltralight NFC标签?

时间:2018-08-08 21:56:53

标签: java android kotlin nfc mifare

使用MifareUltralight.writePage()方法的正确方法是什么?

查询getMaxTransceiveLength()方法将返回253个字节。 tag的广告位为888字节。 transceive()并因此writePage()是否应该被多次调用?正在写入的有效负载大小为457字节。

        val jsonString = Gson().toJson(casualty)  
        val casualtyBytes = toBlob(casualty)
        var currentPage = PAGE_OFFSET
        val pageBytes = ByteArray(MifareUltralight.PAGE_SIZE)
        var byteIndex = 0
        for(i in 0 until casualtyBytes.size){
            pageBytes[byteIndex] = casualtyBytes[i]
            byteIndex++
            if(byteIndex == 4 || i == (casualtyBytes.size-1)) {
                tag.writePage(currentPage, pageBytes)
                currentPage++
                byteIndex = 0
            }
        }

fun toBlob(item : Any) : ByteArray{
    val bos = ByteArrayOutputStream()
    val gzip = GZIPOutputStream(bos) //compress
    val oos = ObjectOutputStream(gzip)
    oos.writeObject(item)
    oos.close()
    return bos.toByteArray()
}

例外

java.io.IOException: Transceive failed
    at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:52)
    at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151)
    at android.nfc.tech.MifareUltralight.writePage(MifareUltralight.java:193)
    at some.package.nfc.NfcCasualtyPublisher.writeToTag(NfcCasualtyPublisher.kt:42)
    at some.package.nfc.NfcCasualtyPublisher.access$writeToTag(NfcCasualtyPublisher.kt:11)
    at some.package.nfc.NfcCasualtyPublisher$publishCasualty$1.run(NfcCasualtyPublisher.kt:21)
    at java.lang.Thread.run(Thread.java:818)

1 个答案:

答案 0 :(得分:2)

MIFARE Ultralight和NTAG标签的存储分为4页,每页4个字节。因此,WRITE命令(SomeModel)一次写入4个字节。 (请注意,READ命令(MifareUltralight.writePage())一次读取4页(= 16字节)。

因此,当您要写入NTAG216标签时,需要将数据分成4个字节的块。您似乎已经在代码中使用了for循环来做到这一点(尽管您会遇到一些问题,因为如果数据未按页面对齐,则不会清除最后一页的未使用字节)。

并非MIFARE Ultralight / NTAG标签的所有页面均可自由用于数据存储。仅第4到225页(用于NTAG216)中的用户存储区。前2页(第0和1页)是只读的,并保留给标签序列号。接下来的2页(第2页和第3页)包含一次写入存储器(即曾经被写入1的位不能再次变为0的存储区)。具体来说,第2页中有锁定位(第226页中也有锁定位,但是如果您的数据仅为457字节,则不应该触摸它们)。如果设置了锁定位,则将阻止对部分用户存储器页面的写访问,这将导致“发送失败”异常。因此,如果PAGE_OFFSET的值小于4,则可能通过将数据写入保留的存储区来使标记不可用。

通常,如果您仅打算存储(自由读取)数据,并且不使用标签的其他功能(例如密码保护),则强烈建议您不要使用低级IO访问NFC标签的方法。相反,请坚持使用NDEF抽象层并将数据存储在NDEF记录中。然后,Android将负责将数据放入任何NFC标签上的适当内存位置。

最后,收发长度是一个命令或响应中可以传输的字节数。因此,例如,对于WRITE命令,这总共是6个字节(4个字节的数据有效载荷,一个地址字节和一个命令代码字节)。对于READ响应,这将是16字节的数据有效负载。 MifareUltralight.readPages()的值表示基础库,HAL和硬件在理论上可能的最大收发长度。