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;}}
更多相关文章
- Android(安卓)Tag-Cloud (云标签) 效果
- 【Android】AndroidManifest 中original-package标签
- Android仿饿了么搜索功能
- 一起学android之自定义控件一起制作自定义标签(39)
- 介绍一种不同流式标签的实现方式
- BroadcastReceiver与Notification的综合应用之自定义Action的调
- 【翻译】NFC近场通信
- Android实用视图动画及工具系列之六:通用表情栏,仿QQ微信聊天弹出
- Android(安卓)UI设计之使用HTML标签,实现在TextView中对中文文字