android NFC学习笔记(二)

一:解析NDEF
据文档说这是google参考nfc论坛而提出和支持的格式。也就是说nfc的格式和标准肯定有很多,google只不过比较支持其中的这一种NDEF。

ndef格式,就是数据被包裹在一个NdefMessage里,而同时一个NdefMessage里面又可以包含多个NdefRecord.当然你也应该还记得,nfc的tag里面是可以不包含Ndef数据的,他也可以包含android.nfc.tech所定义的多种标签。Google推荐开发人员使用ndef格式的数据来处理android相关的nfc格式数据。

当一个android设备检测到nfc标签包含ndef格式的数据的时候,他就会尝试的去解析数据中的MIME type或者是URI。为了做这个事情,他需要解析NdefMessage中的第一个NdefRecord。第一个NdefRecord中的结构一般如下:

3-bit TNF (Type Name Format)

如何解释variable length type的数据。并依据不同的解析,来确定发送什么样的intent。如果这里定义的是TNF_WELL_KNOWN则还要参考variable length type来进一步确定。如果是网络地址URL则直接去调用浏览器程序了。

Variable length type

进一步定义record的类型。具体的请参看android文档。不过话在这里多说一句,TNF和TYPE这两个参数非常的重要,直接决定了你NDEF格式的命中程度。定义的越规范,越清楚,同时在androidmanifest文件中写的越正确,就越好,否则系统就会被你发TECH_ACTION

比如:构造的时候写

new NdefRecord(
NdefRecord.TNF_WELL_KNOWN ,
NdefRecord.RTD_TEXT,
new byte[0],
data.getBytes(Charset.forName("UTF-8")));

androidmanifest文件中写




这一对就可以正确的过滤一个text/plain格式的ndef

Variable length ID
不经常使用.....是用来唯一标示一个record的。

Variable length payload
actual这个才是真正的数据区域。读写操作一般应该主要是对这个区域的操作。一个NdefMessage可以有多个NdefRecord所以不要假设所有的数据都仅仅存储在第一个NdefRecord中。

已经知道了Ndef的格式了,那么解析带有Ndef数据的Intent也就简单很多了。底下这个解析的方法,通常放在onResume或者onNewIntent中。

private boolean readFromTag(Intent in){
    Parcelable[] rawArray = in.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    //如果你不止一个的话,那么你要遍历了。
    NdefMessage mNdefMsg = (NdefMessage)rawArray[0];
    //如果你不止一个record,那么你也要遍历出来所有的record
    NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];
    try {
        if(mNdefRecord != null){
            readResult = new String(mNdefRecord.getPayload(),"UTF-8");
            readJson = new JSONObject(readResult);
            return true;
        }
    } catch (JSONException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    };
    return false;
}

二:解析其他tech标签

现在你已经会解析ndef标签了,但是你也应该知道,大多数nfc标签其实并不是ndef格式的。比如你的公交卡,各个城市的公交卡会支持什么格式,并不一定。所以你还要会解析各种tech格式的nfc数据。
如果你还记得我们再tech-list中定义了多少种格式,你就应该知道我们如果要全部解析的话,应该要解析多少种不同的nfc格式了。底下这段代码可以显示出你所扫描的nfc卡到底支持哪几种格式。

    Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    String[] temp = tag.getTechList();
    for(String s :temp){
      Log.i("xxx","s = "+s);
    }

这是一段最常用的(我个人理解啊)的nfc解析代码,主要是解析MifareClassic格式。貌似大多数nfc标签都会支持这种格式。先普及下关于他的简单常识:不知道各个格式的数据是怎么构成的,你压根就没法解析。

一般来说,给予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的卡来说,每个区最后一个块(block)叫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的KEY A或KEY B。

这就是解析MifareClassic的代码了

private void readTechPayloadMC(Tag tag){
    MifareClassic mc = MifareClassic.get(tag);//通过intent拿到EXTRA_TAG并转化成MirareClassic格式。
    int bCount = 0 ;
    int bIndex = 0 ;
    try {
        mc.connect();
        int sectorCount = mc.getSectorCount();//获得sector总数
        Log.i("liyufei3","sectorCount = "+sectorCount);
        for(int i =0;i

你可能感兴趣的:(android NFC学习笔记(二))