简体   繁体   中英

How to properly write to a MifareUltralight NFC tag?

What's the proper way of using the MifareUltralight.writePage() method?

Querying the getMaxTransceiveLength() method returns 253 bytes. Yet the tag is advertised at 888 bytes. Is the transceive() and thus writePage() supposed to be invoked multiple times? The payload being written has a size of 457 bytes.

        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()
}

Exception

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)

The memory of MIFARE Ultralight and NTAG tags is organized in pages of 4 byte each. Consequently, the WRITE command ( MifareUltralight.writePage() ) writes 4 bytes at a time. (Note that the READ command ( MifareUltralight.readPages() ) reads 4 pages (= 16 bytes) at a time.

Therefore, when you want to write to your NTAG216 tag, you need to split the data into chunks of 4 bytes. You seem to already do that with the for-loop in your code (though you'll run into some issues since you do not clear the unused bytes of the last page if your data is not page-aligned).

Not all the pages of a MIFARE Ultralight/NTAG tag are freely usable for data storage. Only the user memory area in pages 4 to 225 (for NTAG216) is. The first 2 pages (pages 0 and 1) are read-only and reserved for the tag serial number. The next 2 pages (pages 2 and 3) contain write-once memory (ie memory areas where a bit that is once written to 1 can't be changed to 0 again). Specifically, there are the lock-bits in page 2 (also in page 226, but you shouldn't have touched them if your data is only 457 bytes). If you set the lock-bits, you prevent write access to parts of the user memory pages, which would result in a "Transceive failed" exception. Consequently, if the value of PAGE_OFFSET is less than 4, you probably rendered the tag unusable by writing data to reserved memory areas.

In general, if you only intend to store (freely-readable) data and won't make use of additional features of the tag (such as password protection), I would strongly suggest that you do not use low-level IO methods for accessing NFC tags. Instead, stick to the NDEF abstraction layer and store your data in NDEF records. Android will then take care of putting the data into appropriate memory locations on any NFC tag.

Finally, the transceive length is the amount of bytes that can be transfered in one command or response. So, for instance, for a WRITE command, this would be 6 bytes in total (4 bytes of data payload, one address byte and one command code byte). For a READ response this would be the 16 bytes of data payload. The value of getMaxTransceiveLength() indicates the maximum transceive length theoretically possible by the underlying libraries, HAL and hardware.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM