簡體   English   中英

如何正確寫入MifareUltralight NFC標簽?

[英]How to properly write to a MifareUltralight NFC tag?

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

查詢getMaxTransceiveLength()方法將返回253個字節。 但是,該標簽的廣告為888字節。 是否應該多次調用transceive()並因此writePage()調用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)

MIFARE Ultralight和NTAG標簽的存儲分為4頁,每頁4個字節。 因此,WRITE命令( MifareUltralight.writePage() )一次寫入4個字節。 (請注意,READ命令( MifareUltralight.readPages() )一次讀取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字節的數據有效負載。 getMaxTransceiveLength()的值表示基礎庫,HAL和硬件在理論上可能達到的最大收發長度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM