Android应用实例之----MifareUltralight格式的nfc标签读写
随着支持nfc通信功能的智能手机更加普及,在移动支付及公交卡、诊疗卡读写等方面将会发挥更大的作用。
首先介绍Android NFC的工作流程:
步骤1:通过android.nfc.NfcAdapter.getDefaultAdapter()取得手机的object NfcAdapter;
步骤2:通过NfcAdapter.isEnabled()查询该手机是否支持NFC;
步骤3:如果手机支持NFC,手机内置的NFC扫描器扫描到电子标签后,就会向应用程序发送ACTION_TAG_DISCOVERED的Intent,intent的extras架构中会包含NDEF;
步骤4:如果收到ACTION_TAG_DISCOVERED,就提取NdefMessage,并在此基础上进而提取NdefRecord。
在使用NFC API的时候需要在AndroidManifest.xml中声明获取使用权限
- <uses-permission android:name="android.permission.NFC" />
- <activity
- android:name=".activitys.MainAct"
- android:screenOrientation="landscape"
- android:windowSoftInputMode="adjustUnspecified|stateHidden" >
- <meta-data
- android:name="android.nfc.action.TECH_DISCOVERED"
- android:resource="@xml/nfc_tech_filter" />
- </activity>
应用支持nfc功能的手机读取公交卡等信息时需要应用标签调度系统。当Android设备搜索到标签时,不能让用户选择要处理的意图,而是让Activity去处理nfc标签。
NFC标签调度定义了三个不同优先级的意图ACTION_NDEF_DISCOVERED、ACTION_TECH_DISCOVERED、ACTION_TAG_DISCOVERED ,
ACTION_NDEF_DISCOVERED优先级最高,标签调度系统在任何情况下都先试图在其他意图前使用该意图去启动一个activity。如果没有activity注册处理
ACTION_NDEF_DISCOVERED意图,标签调度系统会试图使用ACTION_TECH_DISCOVERED去启动一个应用。当Android设备扫描到包含NDEF格式数据的NFC标签后,
解析消息识别其URI,读取NdefMessage的第一个NefRecord以便解析整个NDEF消息(一个NDEF消息可能有多个NDEF Records)。
在前台发布系统中列出nfc标签支出的不同数据格式列表,要求该列表包含要读取卡的数据格式。
- private void utfds() {
- // Using the foreground dispatch system
- // 前台发布系统
- pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
- getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
- IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
- try {
- ndef.addDataType("*/*");
- }
- catch (MalformedMimeTypeException e) {
- throw new RuntimeException("fail", e);
- }
- intentFiltersArray = new IntentFilter[] { ndef, };
- techListsArray = new String[][] {
- new String[] { NfcF.class.getName() },
- new String[] { NfcA.class.getName() },
- new String[] { NfcB.class.getName() },
- new String[] { NfcV.class.getName() },
- new String[] { Ndef.class.getName() },
- new String[] { MifareClassic.class.getName() },
- new String[] { MifareUltralight.class.getName()}};
- }
用到的nfc芯片为兼容MifareUltralight协议的射频卡,一般内存大小为1k,16个分区,每个分区四个块,每个块16个字节数据。Nfc标签系统写信息到nfc芯片时,将nfc内存
分为64个块,前3个块用于存放厂商代码,已经固化,不可更改。从第四个块开始,每个块写入四个字节。另外推荐一个应用工具TagWriter,它能擦除写入nfc标签卡中的数据,
还原标签卡的初始模式。读写支持MifareUltralight数据格式的nfc标签代码如下:
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.nio.charset.Charset;
- import android.content.Context;
- import android.content.Intent;
- import android.nfc.NdefMessage;
- import android.nfc.NdefRecord;
- import android.nfc.NfcAdapter;
- import android.nfc.Tag;
- import android.nfc.tech.MifareUltralight;
- import android.nfc.tech.Ndef;
- import android.nfc.tech.NdefFormatable;
- import android.os.Parcelable;
- //import android.os.Parcelable;
- import android.widget.Toast;
- public class NfcHelper {
- private Intent intent;
- private Context con;
- public NfcHelper(Intent intent, Context con) {
- this.intent = intent;
- this.con = con;
- }
- public String RedTag() {
- String readResult = new String();
- if (intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) != null) {
- Tag rawArray = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- MifareUltralight mifare = MifareUltralight.get(rawArray);
- for (String tech : rawArray.getTechList()) {
- java.lang.System.out.println("=="+tech);
- }
- try {
- mifare.connect();
- byte[] payload = mifare.readPages(4);
- byte[] payload1 = mifare.readPages(8);
- byte[] payload2 = mifare.readPages(12);
- byte[] payload3 = mifare.readPages(16);
- byte[] payload4 = mifare.readPages(20);
- readResult = readResult+ new String(payload,Charset.forName("US_ASCII"))
- +new String(payload3,Charset.forName("US_ASCII"))+new String(payload4,Charset.forName("US_ASCII"))
- +new String(payload1,Charset.forName("US_ASCII"))+ new String(payload2,Charset.forName("US_ASCII"));
- return readResult;
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (mifare != null) {
- try {
- mifare.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- return null;
- }
- public void writeTag() {
- Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- MifareUltralight ultralight = MifareUltralight.get(tag);
- try {
- ultralight.connect();
- String str = "ij00";
- byte[] by=str.getBytes();
- int i = str.length();
- ultralight.writePage(4,"aaaa".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(5,"bbbb".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(6,"cccc".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(7,"abcd".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(8,"abcd".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(9,"abcd".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(10,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(11,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(12,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(13,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(14,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(15,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(16,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(17,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(18,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(19,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(20,"".getBytes(Charset.forName("US_ASCII")));
- ultralight.writePage(21,"".getBytes(Charset.forName("US_ASCII")));
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- ultralight.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- private NdefMessage createNdefMessage(String str) {
- NdefMessage msg = new NdefMessage(new NdefRecord[] { createMimeRecord(
- "text/plain", str.getBytes()) });
- return msg;
- }
- public NdefRecord createMimeRecord(String mimeType, byte[] payload) {
- byte[] mimeBytes = mimeType.getBytes(Charset.forName("UTF-8"));
- NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
- mimeBytes, new byte[0], payload);
- return mimeRecord;
- }
- //字符序列转换为16进制字符串
- private String bytesToHexString(byte[] src) {
- StringBuilder stringBuilder = new StringBuilder("0x");
- if (src == null || src.length <= 0) {
- return null;
- }
- char[] buffer = new char[2];
- for (int i = 0; i < src.length; i++) {
- buffer[0] = Character.forDigit((src[i] >>> 4) & 0x0F, 16);
- buffer[1] = Character.forDigit(src[i] & 0x0F, 16);
- System.out.println(buffer);
- stringBuilder.append(buffer);
- }
- return stringBuilder.toString();
- }
- protected String changeEncoding(String str) {
- try {
- str = new String(str.getBytes("iso8859-1"), "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return str;
- }
- }

浙公网安备 33010602011771号