先了解一下MifareClassic協議
在android sdk 的文檔中,描述道 “all MifareClassic
I/O operations will be supported, and MIFARE_CLASSIC
NDEF tags will also be supported. In either case, NfcA
will also be enumerated on the tag, because all MIFARE Classic tags are also NfcA
.” 所以說NFCA協議是兼容MifareClassic 協議的, 我們可以通過NfcA在android的相關類來處理給予MifareClassic 的RFID卡。
一般來說,給予MifareClassic的射頻卡,一般內存大小有3種:
1K: 16個分區(sector),每個分區4個塊(block),每個塊(block) 16個byte數據
2K: 32個分區,每個分區4個塊(block),每個塊(block) 16個byte數據
4K:64個分區,每個分區4個塊(block),每個塊(block) 16個byte數據
對於所有基於MifareClassic的卡來說,每個區最后一個塊叫Trailer,16個byte, 主要來存放讀寫該區的key,可以有A,B兩個KEY,每個key長6byte,默認的key一般是FF 或 0,最后一個塊的內存結構如下:
Block 0 Data 16bytes
Block 1 Data 16 bytes
Block 2 Data 16 bytes
Block 3 Trailer 16 bytes
Trailer:
Key A: 6 bytes
Access Conditions: 4 bytes
Key B: 6 bytes
所以在寫卡的內存的時候,一般不能寫每個sector的最后一個block,除非你有要修改KEY和訪問權限的需求。如果KEY A 被你不小心修改掉了,而你不知道修改成什么,那與之對應的那個sector你就沒有辦法訪問了。因為在MifareClassic中,如果你要讀取數據,那么必須要有這個數據地址所在的sector的權限,這個權限就是這個sector的trailer的keyA或KEY B。
讀數據的例子:
//tag 就是在上一篇中onNewIntent中獲取的tag
MifareClassic mc = MifareClassic.get(tag); short startAddress = 0; short endAddress = 5; byte[] data = new byte[(endAddress - startAddress + 1 ) * ByteCountPerBlock]; try { mc.connect();for (short i = startAddress; i <= endAddress; i++ ,time++) { boolean auth = false; short sectorAddress = getSectorAddress(i); auth = mc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_DEFAULT); if (auth){ //the last block of the sector is used for KeyA and KeyB cannot be overwritted short readAddress = (short)(sectorAddress == 0 ? i : i + sectorAddress); byte[] response = mc.readBlock(readAddress); CombineByteArray(data, response, time * ByteCountPerBlock); } else{ throw new NfcException(NfcErrorCode.TemporaryError, "Authorization Error."); } } mc.close(); } catch (NfcException ne) { throw ne; } catch (IOException e) { throw new NfcException(NfcErrorCode.TemporaryError, "Get response, what it is not successfully.", e); } finally { try { mc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
寫數據的例子:
//tag 就是在上一篇中onNewIntent中獲取的tag MifareClassic mc = MifareClassic.get(tag); try { mc.connect(); boolean auth = false; short sectorAddress = 0 auth = mc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_DEFAULT); if (auth) { //the last block of the sector is used for KeyA and KeyB cannot be overwritted mc.writeBlock(readAddress, dataTemp); mc.close(); } }finally { try { mc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
完整的代碼示例在這里下載
上一篇 NFC (一) 概述