非淡泊无以明志,非宁静无以致远。这篇文章主要讲述Android NFC近场通信03----读写MifareClassic卡相关的知识,希望能为你提供帮助。
Android NFC近场通信02----读写MifareClassic卡
一.MifareClassic卡 相关
一般来说,给予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 bytesTrailer:
Key A: 6 bytes
Access Conditions: 4 bytes
Key B: 6 bytesM1卡分为16个扇区,每一个扇区由4块(块0、块1、块2、块3)组成。(我们也将16个扇区的64个块按绝对地址编号为0~63。)存贮结构如右表所看到的
扇 区 0 |
块0 |
数据块 |
0 |
|
块1 |
数据块 |
1 |
||
块2 |
数据块 |
2 |
||
块3 |
passwordA
存取控制
passwordB |
数据块 |
3 |
|
扇 区 1 |
块0 |
数据块 |
4 |
|
块1 |
数据块 |
5 |
||
块2 |
数据块 |
6 |
||
块3 |
passwordA
存取控制
passwordB |
数据块 |
7 |
|
: : : |
||||
扇 区 15 |
块0 |
数据块 |
60 |
|
块1 |
数据块 |
61 |
||
块2 |
数据块 |
62 |
||
块3 |
passwordA
存取控制
passwordB |
数据块 |
63 |
第0扇区的块0(即绝对地址0块),它用于存放厂商代码。已经固化。不可更改。
每一个扇区的块0、块1、块2为数据块。可用于存贮数据。
每一个扇区的块3为控制块,包含了passwordA、存取控制、passwordB。
详细结构例如以下:
A1A2 A3 A4 A5
FF 07 8069
B0 B1 B2 B3 B4 B5 passwordA(6字节) 存取控制(4字节) passwordB(6字节) |
存取控制为4个字节,共32位。扇区中的每一个块(包含数据块和控制块)的存取条件是由password和存取控制共同决定的。
工作原理:
读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路。其频率与讯写器发射的频率同样,在电磁波的激励下,LC谐振电路产生共振。从而使电容内有了电荷,在这个电容的还有一端。接有一个单向导通的电子泵,将电容内的电荷送到还有一个电容内储存,当所积累的电荷达到2V时。此电容可做为电源为其他电路提供工作电压,将卡内数据发射出去或接取读写器的数据。
二.读取数据
//tag 就是在上一篇中onNewIntent中获取的tag MifareClassic mc = MifareClassic.get(tag); short startAddress = 0; short endAddress = 5; byte[] data = https://www.songbingjia.com/android/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 overwrittedmc.writeBlock(readAddress, dataTemp); mc.close(); } }finally { try { mc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
附:NFC 论坛 http://www.nfcchina.org/forum.php
【Android NFC近场通信03----读写MifareClassic卡】
推荐阅读
- Android Stdio 如何自定义生成APK的名称
- Android Intent Scheme URLs攻击
- Android 关于BottomDialogSheet 与Layout擦出爱的火花()
- Android 基础-给有java基础的初学者(四大组件)
- ArcGIS Android SDK 中文标注乱码
- 妙用HTML5的八大特性来开发移动webAPP
- 浅谈android怎样同一时候适配pad和手机
- Android string.xml 显示特殊符号
- 支付宝---手机APP支付