android nfc常用标签读取
隨著nfc智能手機越來越普及,nfc在生活中的應用也越來越多,加上最近自己也正好有點時間,因此打算研究一下nfc標簽的讀取,在網上找了一些資料,很多文章都寫的很好,不過都是針對某種特定數據格式的nfc標簽的讀寫,也由各種nfc的app可以讀取各種類型的nfc標簽,但是又沒有源碼,由此,本文主要是針對常用的nfc標簽做基本讀取操作,第一次發文章,如果有問題請大家指正。
nfc的基本介紹就不做說明了,網上有很多資料,下面主要描述nfc數據過濾、NDEF數據讀取和非NDEF數據讀取:
1、nfc數據過濾
? ? ? nfc主要有三種過濾器,分別是NDEF_DISCOVERED,TECH_DISCOVERED,TAG_DISCOVERED,主要說明如下:
? ? ? NDEF_DISCOVERED:當檢測到標簽中含有NDEF格式的數據,并且在應用中聲明了可以接收ndef數據的intent時,觸發該action的intent;
? ? ??TECH_DISCOVERED:當沒有應用響應NDEF_DISCOVERED時,會發出tech的intent;
? ? ??TAG_DISCOVERED:當前兩個intent都沒有觸發時,默認觸發tag類型的intent;
? ? ? (1) NDEF_DISCOVERED過濾定義:
<intent-filter><action android:name="android.nfc.action.TECH_DISCOVERED" /></intent-filter><meta-dataandroid:name="android.nfc.action.TECH_DISCOVERED"android:resource="@xml/nfc_tech_filter" />
nfc_tech_filter文件:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><tech-list><tech>android.nfc.tech.IsoDep</tech><tech>android.nfc.tech.NfcA</tech><tech>android.nfc.tech.NfcB</tech><tech>android.nfc.tech.NfcF</tech><tech>android.nfc.tech.NfcV</tech><tech>android.nfc.tech.Ndef</tech><tech>android.nfc.tech.NdefFormatable</tech><tech>android.nfc.tech.MifareClassic</tech><tech>android.nfc.tech.MifareUltralight</tech></tech-list> </resources>
(3) TAG_ DISCOVERED過濾:
?<intent-filter>
? ? ? ? ? ? ? ? <action android:name="android.nfc.action.TAG_DISCOVERED" />
? ? ? ? ? ? </intent-filter>
2、各類nfc數據讀取
(1)NDEF數據讀取
? ? ? ? ??TNF_ABSOLUTE_URI讀取:
??
private void parseAbsoluteUriRecode(NdefRecord record) {byte[] payload = record.getPayload();Uri uri = Uri.parse(new String(payload, Charset.forName("utf-8")));setNoteBody(new String(payload, Charset.forName("utf-8")));}<span style="font-size: 13.3333px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> TNF_WELL_KNOWN的URI讀取:</span>
<pre name="code" class="java">private void parseWellKnownUriRecode(NdefRecord record) {Preconditions.checkArgument(Arrays.equals(record.getType(),NdefRecord.RTD_URI));byte[] payload = record.getPayload();String prefix = URI_PREFIX_MAP.get(payload[0]);byte[] fulluri = Bytes.concat(prefix.getBytes(Charset.forName("utf-8")),Arrays.copyOfRange(payload, 1, payload.length));Uri uri = Uri.parse(new String(fulluri, Charset.forName("utf-8")));setNoteBody(new String(fulluri, Charset.forName("utf-8")));}
? ? ? ?TNF_WELL_KNOWN的TEXT讀取:
private void parseWellKnownTextRecode(NdefRecord record) {Preconditions.checkArgument(Arrays.equals(record.getType(),NdefRecord.RTD_TEXT));String payloadStr = "";byte[] payload = record.getPayload();Byte statusByte = record.getPayload()[0];String textEncoding = "";textEncoding = ((statusByte & 0200) == 0) ? "utf-8" : "utf-16";int languageCodeLength = 0;languageCodeLength = statusByte & 0077;try {payloadStr = new String(payload, languageCodeLength + 1,payload.length - languageCodeLength - 1, textEncoding);} catch (UnsupportedEncodingException e) {}setNoteBody(payloadStr);}
? ? TNF_ABSOLUTE_URI的record類型和TNF_EXTERNAL_TYPE類型讀取:
private void parseOtherRecode(NdefRecord record) {byte[] payload = record.getPayload();Uri uri = Uri.parse(new String(payload, Charset.forName("utf-8")));setNoteBody(new String(payload, Charset.forName("utf-8")));}(2)非NDEF數據讀取
MifareUltralight讀取:
public String readTagUltralight(Tag tag) {MifareUltralight mifare = MifareUltralight.get(tag);try {mifare.connect();int size=mifare.PAGE_SIZE;byte[] payload = mifare.readPages(0);String result="page1:"+ByteArrayToHexString(payload)+"\n"+"總容量:"+String.valueOf(size)+"\n";//這里只讀取了其中幾個page、byte[] payload1 = mifare.readPages(4);byte[] payload2 = mifare.readPages(8);byte[] payload3 = mifare.readPages(12);result+="page4:"+ByteArrayToHexString(payload1)+"\npage8:"+ByteArrayToHexString(payload2)+"\npage12:"+ByteArrayToHexString(payload3)+"\n";//byte[] payload4 = mifare.readPages(16);//byte[] payload5 = mifare.readPages(20);return result;//+ new String(payload4, Charset.forName("US-ASCII"));//+ new String(payload5, Charset.forName("US-ASCII"));} catch (IOException e) {Log.e(TAG, "IOException while writing MifareUltralight message...",e);return "讀取失敗!";} catch (Exception ee) {Log.e(TAG, "IOException while writing MifareUltralight message...",ee);return "讀取失敗!";} finally {if (mifare != null) {try {mifare.close();} catch (IOException e) {Log.e(TAG, "Error closing tag...", e);}}}}
MifareClassic讀取:
public String readTagClassic(Tag tag) {boolean auth = false;MifareClassic mfc = MifareClassic.get(tag);// 讀取TAGtry {String metaInfo = "";int type = mfc.getType();// 獲取TAG的類型int sectorCount = mfc.getSectorCount();// 獲取TAG中包含的扇區數String typeS = "";switch (type) {case MifareClassic.TYPE_CLASSIC:typeS = "TYPE_CLASSIC";break;case MifareClassic.TYPE_PLUS:typeS = "TYPE_PLUS";break;case MifareClassic.TYPE_PRO:typeS = "TYPE_PRO";break;case MifareClassic.TYPE_UNKNOWN:typeS = "TYPE_UNKNOWN";break;}metaInfo += "卡片類型:" + typeS + "\n共" + sectorCount + "個扇區\n共"+ mfc.getBlockCount() + "個塊\n存儲空間: " + mfc.getSize()+ "B\n";for (int j = 0; j < sectorCount; j++) {// Authenticate a sector with key A.auth = mfc.authenticateSectorWithKeyA(j,MifareClassic.KEY_DEFAULT);int bCount;int bIndex;if (auth) {metaInfo += "Sector " + j + ":驗證成功\n";// 讀取扇區中的塊bCount = mfc.getBlockCountInSector(j);bIndex = mfc.sectorToBlock(j);for (int i = 0; i < bCount; i++) {byte[] data = mfc.readBlock(bIndex);metaInfo += "Block " + bIndex + " : "+ ByteArrayToHexString(data) + "\n";bIndex++;}} else {metaInfo += "Sector " + j + ":驗證失敗\n";}}return metaInfo;} catch (Exception e) {Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();e.printStackTrace();} finally {if (mfc != null) {try {mfc.close();} catch (IOException e) {Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();}}}return null;}
IsoDep讀取:
IsoDep isodep = IsoDep.get(tagFromIntent);isodep.connect();//select the card manager appletbyte[] mf = { (byte) '1', (byte) 'P',(byte) 'A', (byte) 'Y', (byte) '.', (byte) 'S', (byte) 'Y',(byte) 'S', (byte) '.', (byte) 'D', (byte) 'D', (byte) 'F',(byte) '0', (byte) '1', };String result="";byte[] mfRsp = isodep.transceive(getSelectCommand(mf));Log.d(TAG, "mfRsp:" + HexToString(mfRsp));//select Main Applicationbyte[] wht = { (byte) 0x41, (byte) 0x50,//此處以武漢通為例,其它的卡片參考對應的命令,網上可以查到(byte) 0x31, (byte) 0x2E, (byte) 0x57, (byte) 0x48, (byte) 0x43,(byte) 0x54, (byte) 0x43, };byte[] sztRsp = isodep.transceive(getSelectCommand(wht));byte[] balance = { (byte) 0x80, (byte) 0x5C, 0x00, 0x02, 0x04};byte[] balanceRsp = isodep.transceive(balance);Log.d(TAG, "balanceRsp:" + HexToString(balanceRsp));if(balanceRsp!=null && balanceRsp.length>4){int cash = byteToInt(balanceRsp, 4); float ba = cash / 100.0f;result+=" 余額:"+String.valueOf(ba);}setNoteBody(result); isodep.close();
NfcB讀取:
nfcbTag = NfcB.get(tag);try {nfcbTag.connect();if (nfcbTag.isConnected()) {System.out.println("已連接");Toast.makeText(MainActivity.this, "身份證已連接",Toast.LENGTH_SHORT).show();new CommandAsyncTask().execute();}// nfcbTag.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}
NfcA讀取:
NfcA nfca = NfcA.get(tagFromIntent);try{nfca.connect();if (nfca.isConnected()) {//NTAG216的芯片byte[] SELECT = {(byte) 0x30,(byte) 5 & 0x0ff,//0x05};byte[] response = nfca.transceive(SELECT);nfca.close();if(response!=null){setNoteBody(new String(response, Charset.forName("utf-8")));}}}catch(Exception e){}
NfcF讀取:
NfcF nfc = NfcF.get(tag);try {nfc.connect();byte[] felicaIDm = new byte[]{0};byte[] req = readWithoutEncryption(felicaIDm, 10);byte[] res = nfc.transceive(req);nfc.close();setNoteBody(ByteArrayToHexString(res));} catch (Exception e) {Log.e(TAG, e.getMessage() , e);}
NfcV讀取:
NfcV tech = NfcV.get(tag);if (tech != null) {try {tech.connect();if (tech.isConnected()) {byte[] tagUid = tag.getId(); // store tag UID for use in addressed commandsint blockAddress = 0;int blocknum = 4;byte[] cmd = new byte[] {(byte)0x22, // FLAGS(byte)0x23, // 20-READ_SINGLE_BLOCK,23-所有塊0, 0, 0, 0, 0, 0, 0,0,(byte)(blockAddress & 0x0ff),(byte)(blocknum-1 & 0x0ff)};System.arraycopy(tagUid, 0, cmd, 2, tagUid.length); // paste tag UID into commandbyte[] response = tech.transceive(cmd);tech.close();if(response!=null){setNoteBody(new String(response, Charset.forName("utf-8")));}}} catch (IOException e) {}}
Ndef與NdefFormatable讀取:
NdefMessage[] messages = getNdefMessages(getIntent());byte[] payload = messages[0].getRecords()[0].getPayload();setNoteBody(new String(payload)); NdefMessage[] getNdefMessages(Intent intent) {//讀取nfc數據// Parse the intentNdefMessage[] msgs = null;String action = intent.getAction();if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);if (rawMsgs != null) {msgs = new NdefMessage[rawMsgs.length];for (int i = 0; i < rawMsgs.length; i++) {msgs[i] = (NdefMessage) rawMsgs[i];}} else {// Unknown tag typebyte[] empty = new byte[] {};NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);NdefMessage msg = new NdefMessage(new NdefRecord[] {record});msgs = new NdefMessage[] {msg};}} else {Log.d(TAG, "Unknown intent.");finish();}return msgs;}
最后提供一下源代碼下載地址:http://download.csdn.net/detail/shjn2004/9610180
? ? ? ?
? ? ? ?
總結
以上是生活随笔為你收集整理的android nfc常用标签读取的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#反序列化 “在分析完成之前就遇到流结
- 下一篇: Mysql 存储过程和函数区别