Android NFC相关资料之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 bytes
Trailer:
Key A: 6 bytes
Access Conditions: 4 bytes
Key B: 6 bytes

M1卡分为16个扇区,每个扇区由4块(块0、块1、块2、块3)组成,(我们也将16个扇区的64个块按绝对地址编号为0~63,)存贮结构如右表所示


0

0

数据块

0

1

数据块

1

2

数据块

2

3

密码A  存取控制    密码B

数据块

3

1

0

数据块

4

1

数据块

5

2

数据块

6

3

密码A  存取控制    密码B

数据块

7


 

15

0

数据块

60

1

数据块

61

2

数据块

62

3

密码A  存取控制    密码B

数据块

63


0扇区的0(即绝对地址0块),它用于存放厂商代码,已经固化,不可更改。

每个扇区的块0、块1、块2为数据块,可用于存贮数据。

每个扇区的块3为控制块,包括了密码A、存取控制、密码B。具体结构如下:

A1A2 A3 A4 A5               FF 07 8069               B0 B1 B2 B3 B4 B5

密码A6字节)          存取控制(4字节)          密码B6字节)  

每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制;

存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的。
工作原理:

读写器向M1卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与讯写器发射的频率相同,在电磁波的激励下,LC谐振电路产生共振,从而使电容内有了电荷,在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内储存,当所积累的电荷达到2V时,此电容可做为电源为其它电路提供工作电压,将卡内数据发射出去或接取读写器的数据。

Android 读写M1卡

先了解一下MifareClassic协议

在android sdk 的文档中,描述道 “all MifareClassic I/O operations will be supported, and MIFARE_CLASSIC NDEF tags will also be supported. In either case, NfcAwill also be enumerated on the tag, because all MIFARE Classic tags are also NfcA.” 所以说NFCA协议是兼容MifareClassic 协议的, 我们可以通过NfcA在android的相关类来处理给予MifareClassic 的RFID卡。

读M1卡代码:

 if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
   // 3) Get an instance of the TAG from the NfcAdapter
   Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
   // 4) Get an instance of the Mifare classic card from this TAG
   // intent
   MifareClassic mfc = MifareClassic.get(tagFromIntent);
   if (mfc != null) {
    Toast.makeText(this, "检查到卡片,读卡中...", Toast.LENGTH_SHORT).show();
    try {
     mfc.connect();
     boolean auth = false;
     auth = mfc.authenticateSectorWithKeyA(1,MifareClassic.KEY_DEFAULT);// 验证密码
     if (auth) {
      view_text.setText(new String(mfc.readBlock(4)));// 读取M1卡的第4块即1扇区第0块
     }else
      Toast.makeText(this, "认证失败", Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
     if (BuildConfig.DEBUG) {
      e.printStackTrace();
     }

    }
   }
  }

写M1卡代码:

try {
   Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
   // 4) Get an instance of the Mifare classic card from this TAG
   // intent
   mfc = MifareClassic.get(tagFromIntent);
   mfc.connect();
   boolean auth = false;
   short sectorAddress = 1;
   auth = mfc.authenticateSectorWithKeyA(sectorAddress,
     MifareClassic.KEY_DEFAULT);
   if (auth) {
    // the last block of the sector is used for KeyA and KeyB
    // cannot be overwritted    
    //mfc.writeBlock(4, new byte[]{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08});// 必须为16字节不够自己补0
    if( edit_text.getText().toString().getBytes().length==16){
     mfc.writeBlock(4, edit_text.getText().toString().getBytes());
     mfc.close();
     Toast.makeText(MainActivity.this, "写入成功",Toast.LENGTH_SHORT).show();
    }else
     Toast.makeText(MainActivity.this, "must write 16 bytes",Toast.LENGTH_SHORT).show();
   }else
    Toast.makeText(this, "认证失败", Toast.LENGTH_SHORT).show();
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   try {
    mfc.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }

Demo下载地址:NFCDemo

参考资料:1/2/3/4/5


存取控制参考: http://wenku.baidu.com/view/f8c000daad51f01dc281f1af.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值