NFC标签的读写

概述

现在市面上所售的Android手机几乎都支持NFC功能,作为开发者有必要对其进行一番了解,NFC技术是一种短距高频的无线电技术,主要用于IOT领域。NFC在Android上,是从API9才开始支持的,但是到了API14 Google才对NFC大力开发,所以等到了API15的时候,NFC的传输速度就得到了很大的加强,所以最小api最好设置为14。它有三种模式数据交互形式:

  • 读卡器模式(Reader/Witer Mode)
  • 仿真卡模式(Card Emulation Mode)公交刷卡所用的方式
  • 点对点模式(P2P Mode)共享数据所用的方式
    今天主要实现读卡器模式。

    具体实现:

  1. 权限的配置

    1
    2
    3
    4
    <uses-permission android:name="android.permission.NFC" />
    <!-- 要求当前设备必须要有NFC芯片 -->
    <uses-feature android:name="android.hardware.nfc"
    android:required="true" />
  2. 当我们在注册activity的时候还需要加上过滤NFC的intent,目的是一旦NFC标签靠近手机,手机发起响应不能让它调起系统自带的NFC应用,而是我们的应用

    1
    2
    3
    <intent-filter>
    <action android:name="android.nfc.action.TAG_DISCOVERED"/>
    </intent-filter>
  3. 定义NFC标签的规则标准,目的是哪些符合标准的NFC标签可以让自己的应用响应。该标准由xml文件编写,例如创建一个nfc_model.xml的文件。该文件放在rew资源中的xml文件夹中

  • nfc_model.xml里面的内容有:

    1
    2
    3
    4
    5
    <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
    <tech>android.nfc.tech.MifareClassic</tech>
    </tech-list>
    </resources>
  • 在注册activity时将nfc_model.xml文件添加进去:

    1
    2
    <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfc_model" />
  1. 在Activity中重写onNewIntent,这里的android:launchMode为”singleTop”,要注意。对NFC标签无论是读还是写都会调用这个重写的方法,数据格式是ndef
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Override
    protected void onNewIntent(Intent intent) {//通过intent来作为数据的载体
    if(iswrite){//是写入
    Tag detectedTag =intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createTextRecord(mTagText)});//写入ndef格式的字符串
    boolean result = writeTag(ndefMessage, detectedTag);
    if (result) {//写入成功

    }
    }else{//是读
    readNfcTag(intent);
    }
    }

/*
*/
`java
private void readNfcTag(Intent intent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {//标签靠近手机时,手机响应NFC标签
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);//获取序列数组
NdefMessage msgs[] = null;
if (rawMsgs != null) {//将数组放进NdefMessage中
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
NdefRecord record = msgs[0].getRecords()[0];
String textRecord = parseTextRecord(record);
//textRecord 就是读到的nfc标签里的字符串了
}
}

/**
 * 将文本信息转成ndef格式的NdefRecord 
 *
 * @param text
 * @return
 */
protected  NdefRecord createTextRecord(String text) {
    byte[] langBytes = Locale.CHINA.getLanguage().getBytes(Charset.forName("US-ASCII"));
    Charset utfEncoding = Charset.forName("UTF-8");
    //将文本转换为UTF-8格式
    byte[] textBytes = text.getBytes(utfEncoding);
    //设置状态字节编码最高位数为0
    int utfBit = 0;
    //定义状态字节
    char status = (char) (utfBit + langBytes.length);
    byte[] data = new byte[1 + langBytes.length + textBytes.length];
    //设置第一个状态字节,先将状态码转换成字节
    data[0] = (byte) status;
    //设置语言编码,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1到langBytes.length的位置
    System.arraycopy(langBytes, 0, data, 1, langBytes.length);
    //设置文本字节,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1 + langBytes.length
    //到textBytes.length的位置
    System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
    //通过字节传入NdefRecord对象
    //NdefRecord.RTD_TEXT:传入类型 读写
    NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
            NdefRecord.RTD_TEXT, new byte[0], data);
    return ndefRecord;
}
  1. 这里以Ndef开头的两个类,都是核心类:NdefMessage:主要是描述NDEF格式的信息。NdefRecord:这个是秒速NDEF信息的一个信息段。有了读和写,我们就能进行基本的数据交互。十分的简单。NFC标签属于IOT的范畴,有很多种的用途。更多的逻辑处理是在于读写的操作上。标签里如果需要存在大量的数据的话,需要把写入的文本数据写成json格式的字符串,再通过手机获取信息发送的服务器。