NFC簡介
NFC,即Near Field Communication,近距離無線通訊技術,是一種短距離的(通常<=4cm或更短)高頻(13.56M Hz)無線通信技術,它提供了一種簡單、觸控式的解決方案,可以讓消費者簡單直觀地交換信息、訪問內容與服務。
NFC技術由非接觸式射頻識別(RFID)演變而來,由飛利浦半導體(現恩智浦半導體公司)、諾基亞和索尼共同研制開發,其基礎是RFID及互連技術。近場通信(Near Field Communication,NFC)是一種短距高頻的無線電技術,在單一芯片上結合感應式讀卡器、感應式卡片和點對點的功能,能在13.56MHz頻率運行于4厘米距離內,與兼容設備進行識別和數據交換。其傳輸速度有106 Kbit/秒、212 Kbit/秒或者424 Kbit/秒三種。目前近場通信已通過成為ISO/IEC IS 18092國際標準、ECMA-340標準與ETSI TS 102 190標準。現今這項技術在日韓被廣泛應用。手機用戶憑著配置了支付功能的手機就可以行遍全國:他們的手機可以用作機場登機驗證、大廈的門禁鑰匙、交通一卡通、信用卡、支付卡等等。
???????????????????????????????????????????????????????????????????????
NFC標簽的復雜度不一。簡單的標簽僅能夠提供讀寫語義,有時編程域是一次性的,寫完卡片就變成只讀。更復雜一點的tag能夠提供數學運算,擁有加密硬件保護區塊的訪問。最最復雜的tag包含操作環境,允許tag上執行的代碼進行交互。我們還能夠以各種格式來向tag中寫入存儲數據,但很多Android的API框架都是基于NFC論壇制定的NDEF標準。
AndroidManifest.xml
為了能夠使用Android手機的NFC功能,需要在Manifest文件中添加相應的權限:
使用<uses-permission>元素允許設備訪問NFC硬件:
<uses-permission android:name="android.permission.NFC" />
使用<uses-sdk>元素設置最小SDK版本,下面是基于android 4.0環境,因此聲明如下:
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
下面這項不一定需要,如果你希望你的軟件可以在android market中顯示有NFC硬件,可以使用<uses-feature>元素聲明:
<uses-feature android:name="android.hardware.nfc" android:required="true" />
NFC數據過濾
NFC有三種過濾器分別是ACTION_NDEF_DISCOVERED,ACTION_TECH_DISCOVERED,ACTION_TAG_DISCOVERED。
1.?ACTION_NDEF_DISCOVERED
當掃描到的tag中包含有NDEF載荷且為已知類型,該intent將用來啟動Activity。該intent的優先級最高,tag分發系統總是先于其他intent用該intent來啟動Activity。
2.?ACTION_TECH_DISCOVERED
如果manifest中沒有注冊處理ACTION_NDEF_DISCOVERED類型的intent,該intent將被用以啟動Activity。如果tag中沒有包含可以映射到MIME或者URI類型的數據,或者雖然沒有包含NDEF數據,但是已知的tag技術,則該intent也會被直接啟用。
3.?ACTION_TAG_DISCOVERED
如果以上兩個intent都沒人疼,那么該intent就會啟動。
過濾器的作用是過濾掉雜質,剩下的就是我們需要的了。這三種過濾方式可同時配置,可以比方成從上到下三層,只要是符合某一層過濾器要求的,過濾完就停止往下一層。
???????????????????????
NFC TAG的發布系統:
當android設備掃描到一個NFC標簽時,會自動尋找最適合的Activity來處理這個TAG,如果有多個Activity滿足條件的話,會讓用戶來選擇到底使用哪一個Activity來處理,可以理解為就是簡單的事件響應與事件處理。
那么如何讓一個Activity監聽 ”當掃描到NFC標簽時” 的這一個事件呢?使用intent-filter。
可以理解為當檢測到一個NFC標簽時系統自動創建一個相關Intent對象,含有響應intent-filter的Activity將處理這個Intent。
1.ACTION_NDEF_DISCOVERED過濾器定義如下:
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="text/plain" />
</intent-filter>
下面是能夠篩選URI為http://developer.android.com/index.html的ACTION_NDEF_DISCOVERED過濾器。
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:mimeType="text/plain" />
</intent-filter>
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="http" android:host="developer.android.com"android:pathPrefix="/index.html" />
</intent-filter>
2.ACTION_TECH_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" />
在res下新建xml文件夾然后新建一個nfc_tech_filter.xml文件,添加進你需要支持的標簽類型。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><!-- 可以處理所有Android支持的NFC類型 --><tech-list><tech>android.nfc.tech.IsoDep</tech></tech-list><tech-list><tech>android.nfc.tech.NfcA</tech></tech-list><tech-list><tech>android.nfc.tech.NfcB</tech></tech-list><tech-list><tech>android.nfc.tech.NfcF</tech></tech-list><tech-list><tech>android.nfc.tech.NfcV</tech></tech-list><tech-list><tech>android.nfc.tech.Ndef</tech></tech-list><tech-list><tech>android.nfc.tech.NdefFormatable</tech></tech-list><tech-list><tech>android.nfc.tech.MifareUltralight</tech></tech-list><tech-list><tech>android.nfc.tech.MifareClassic</tech></tech-list>
</resources>
不同數據標簽類型什么意思:
MIFARE Classic數據格式就是NfcA,MIFARE DESFire數據格式是IsoDep就是各種交通卡像武漢通,羊城通,深圳通,北京市政交通卡,長安通,我們使用的二代身份證用的就是NfcB,Felica用的就是NfcF,德州儀器的VicinityCard卡用的是NfcV,而Android分享文件就是實用的Ndef格式傳輸數據。
3.ACTION_TAG_DISCOVERED過濾器定義如下:
<intent-filter><action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
各類NFC數據讀取
1.NDEF格式數據讀取
@Override?
protected void onCreate(Bundle savedInstanceState) {?super.onCreate(savedInstanceState);?setContentView(R.layout.activity_write);?nfcTView=(TextView)findViewById(R.id.info_tv);?nfcAdapter = NfcAdapter.getDefaultAdapter(this);?if (nfcAdapter == null) {?nfcTView.setText("設備不支持NFC!");?inish();?return;?}?if (nfcAdapter!=null&&!nfcAdapter.isEnabled()) {?nfcTView.setText("請在系統設置中先啟用NFC功能!");?finish();?return;?}?
}?
@Override?
protected void onResume() {?super.onResume();?if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {?readFromTag(getIntent());?}?
}?//讀取內容:
private boolean readFromTag(Intent intent){?Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);?NdefMessage mNdefMsg = (NdefMessage)rawArray[0];?NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];?try {?if(mNdefRecord != null){?readResult = new String(mNdefRecord.getPayload(),"UTF-8");?return true;?}?}?catch (UnsupportedEncodingException e) {?e.printStackTrace();?};?return false;?
}?//寫入內容
@Override?
protected void onResume() {?super.onResume();?if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {?Tag tag=getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);?Ndef ndef=Ndef.get(tag);?try {?ndef.connect();?NdefRecord ndefRecord=createTextRecord(data,Locale.US,true);?NdefRecord[] records={ndefRecord};?NdefMessage ndefMessage=new NdefMessage(records);?ndef.writeNdefMessage(ndefMessage);?} catch (IOException e1) {?e1.printStackTrace();?} catch (FormatException e) {?<span style="white-space:pre"> ? </span><span style="white-space:pre"> ? </span>e.printStackTrace();?}
}?
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";//這里只讀取了其中幾個pagebyte[] 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);}}}
}
3.非NDEF數據MifareClassic讀取:
public class NFCActivity extends Activity {NfcAdapter nfcAdapter;TextView promt;private PendingIntent pi;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.nfc_info);promt = (TextView) findViewById(R.id.promt);// 獲取默認的NFC控制器nfcAdapter = NfcAdapter.getDefaultAdapter(this);pi = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);if (nfcAdapter == null) {Toast.makeText(this, "對不起,您的設備不支持nfc功能!", Toast.LENGTH_SHORT).show();//promt.setText("設備不支持NFC!");finish();return;}if (!nfcAdapter.isEnabled()) {Toast.makeText(this, "請在系統設置中開啟NFC功能!", Toast.LENGTH_SHORT).show();//promt.setText("請在系統設置中先啟用NFC功能!");finish();return;}}public void btn_back(View view){this.finish();}@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);// 當前app正在前端界面運行,這個時候有intent發送過來,那么系統就會調用onNewIntent回調方法,將intent傳送過來// 我們只需要在這里檢驗這個intent是否是NFC相關的intent,如果是,就調用處理方法if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {processIntent(intent);}}@Overrideprotected void onResume() {super.onResume();nfcAdapter.enableForegroundDispatch(this, pi, null, null);}/*@Overrideprotected void onResume() {super.onResume();//得到是否檢測到ACTION_TECH_DISCOVERED觸發if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {//處理該intentprocessIntent(getIntent());}}*///字符序列轉換為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();}private String ByteArrayToHexString(byte[] inarray) {int i, j, in;String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A","B", "C", "D", "E", "F" };String out = "";for (j = 0; j < inarray.length; ++j) {in = (int) inarray[j] & 0xff;i = (in >> 4) & 0x0f;out += hex[i];i = in & 0x0f;out += hex[i];}return out;}/*** Parses the NDEF Message from the intent and prints to the TextView*/private void processIntent(Intent intent) {//取出封裝在intent中的TAGTag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);String CardId =ByteArrayToHexString(tagFromIntent.getId());String metaInfo = "";metaInfo+="卡片ID:"+CardId;for (String tech : tagFromIntent.getTechList()) {System.out.println(tech);}boolean auth = false;//讀取TAGMifareClassic mfc = MifareClassic.get(tagFromIntent);try {//Enable I/O operations to the tag from this TagTechnology object.mfc.connect();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 += "\n卡片類型:" + 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 + " : "+ bytesToHexString(data) + "\n";bIndex++;}} else {metaInfo += "Sector " + j + ":驗證失敗\n";}}promt.setText(metaInfo);//Toast.makeText(this, metaInfo, Toast.LENGTH_SHORT).show();} catch (Exception e) {e.printStackTrace();}}
}
4.非NDEF數據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(); ? ? ? ? ? ? ??
完整代碼以廈門公交卡為例
package com.example.nfcdemo;import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;import android.support.v7.app.ActionBarActivity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.nfc.tech.NfcF;
import android.nfc.tech.NfcV;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.example.nfcdemo2.R;public class MainActivity extends ActionBarActivity {private NfcAdapter nfcAdapter; // NFC適配器// NFC前臺調度系統private PendingIntent pendingIntent = null;private TextView show_msg; // 顯示數據protected final static byte TRANS_CSU = 6; // 如果等于0x06或者0x09,表示刷卡;否則是充值protected final static byte TRANS_CSU_CPX = 9; // 如果等于0x06或者0x09,表示刷卡;否則是充值public String[][] tenchlists;public IntentFilter[] filters;@SuppressWarnings("unchecked")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);show_msg = (TextView) findViewById(R.id.show_msg);tenchlists = new String[][] { { IsoDep.class.getName() }, { NfcV.class.getName() }, { NfcF.class.getName() }, };try {filters = new IntentFilter[] { new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED, "*/*") };} catch (MalformedMimeTypeException e1) {e1.printStackTrace();}// 初始化PendingIntent,當有NFC設備連接上的時候,就交給當前Activity處理pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);// 獲取默認的NFC控制器,并進行判斷nfcAdapter = NfcAdapter.getDefaultAdapter(this);if (nfcAdapter == null) {Log.d("h_bl", "設備不支持NFC!");finish();return;}if (!nfcAdapter.isEnabled()) {Toast.makeText(getApplicationContext(), "請在系統設置中先啟用NFC功能!", Toast.LENGTH_SHORT).show();Log.d("h_bl", "請在系統設置中先啟用NFC功能!");return;}Intent intent = this.getIntent(); // 捕獲NFC IntentpraseIntent(intent);}private void praseIntent(Intent intent) {String nfcAction = intent.getAction(); // 解析該Intent的Actionif (NfcAdapter.ACTION_TECH_DISCOVERED.equals(nfcAction)) {Log.d("h_bl", "ACTION_TECH_DISCOVERED");Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // 獲取Tag標簽,既可以處理相關信息for (String tech : tag.getTechList()) {Log.d("h_bl", "tech=" + tech);}IsoDep isoDep = IsoDep.get(tag);String str = "";try {isoDep.connect(); // 連接if (isoDep.isConnected()) {Log.d("h_bl", "isoDep.isConnected"); // 判斷是否連接上// 1.select PSF (1PAY.SYS.DDF01)// 選擇支付系統文件,它的名字是1PAY.SYS.DDF01。byte[] DFN_PSE = { (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', };isoDep.transceive(getSelectCommand(DFN_PSE));// 2.選擇公交卡應用的名稱byte[] DFN_SRV = { (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x86, (byte) 0x98, (byte) 0x07, (byte) 0x01, };isoDep.transceive(getSelectCommand(DFN_SRV));// 3.讀取余額byte[] ReadMoney = { (byte) 0x80, // CLA Class(byte) 0x5C, // INS Instruction(byte) 0x00, // P1 Parameter 1(byte) 0x02, // P2 Parameter 2(byte) 0x04, // Le};byte[] Money = isoDep.transceive(ReadMoney);if (Money != null && Money.length > 4) {int cash = byteToInt(Money, 4);float ba = cash / 100.0f;show_msg.setText("余額:" + ba);}// 4.讀取所有交易記錄byte[] ReadRecord = { (byte) 0x00, // CLA Class(byte) 0xB2, // INS Instruction(byte) 0x01, // P1 Parameter 1(byte) 0xC5, // P2 Parameter 2(byte) 0x00, // Le};byte[] Records = isoDep.transceive(ReadRecord);// 處理RecordLog.d("h_bl", "總消費記錄" + Records);ArrayList<byte[]> ret = parseRecords(Records);List<String> retList = parseRecordsToStrings(ret);show_msg.append("\n" + "消費記錄如下:");for (String string : retList) {Log.d("h_bl", "消費記錄" + string);show_msg.append("\n" + string);}}} catch (IOException e) {e.printStackTrace();} finally {if (isoDep != null) {try {isoDep.close();} catch (IOException e) {e.printStackTrace();}}}}}@Overrideprotected void onPause() {if (nfcAdapter != null)nfcAdapter.disableForegroundDispatch(this);super.onPause();}@Overrideprotected void onResume() {super.onResume();nfcAdapter.enableForegroundDispatch(this, pendingIntent, filters, tenchlists);}@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);// 當前app正在前端界面運行,這個時候有intent發送過來,那么系統就會調用onNewIntent回調方法,將intent傳送過來// 我們只需要在這里檢驗這個intent是否是NFC相關的intent,如果是,就調用處理方法if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {Log.d("h_bl", "onNewIntent");praseIntent(intent);}}public static byte byteToHex(byte arg) {byte hex = 0;if (arg >= 48 && arg <= 57) {hex = (byte) (arg - 48);} else if (arg >= 65 && arg <= 70) {hex = (byte) (arg - 55);} else if (arg >= 97 && arg <= 102) {hex = (byte) (arg - 87);}return hex;}private byte[] getSelectCommand(byte[] aid) {final ByteBuffer cmd_pse = ByteBuffer.allocate(aid.length + 6);cmd_pse.put((byte) 0x00) // CLA Class.put((byte) 0xA4) // INS Instruction.put((byte) 0x04) // P1 Parameter 1.put((byte) 0x00) // P2 Parameter 2.put((byte) aid.length) // Lc.put(aid).put((byte) 0x00); // Lereturn cmd_pse.array();}/*** 整條Records解析成ArrayList<byte[]>*?* @param Records* @return*/private ArrayList<byte[]> parseRecords(byte[] Records) {int max = Records.length / 23;Log.d("h_bl", "消費記錄有" + max + "條");ArrayList<byte[]> ret = new ArrayList<byte[]>();for (int i = 0; i < max; i++) {byte[] aRecord = new byte[23];for (int j = 23 * i, k = 0; j < 23 * (i + 1); j++, k++) {aRecord[k] = Records[j];}ret.add(aRecord);}for (byte[] bs : ret) {Log.d("h_bl", "消費記錄有byte[]" + bs); // 有數據。解析正確。}return ret;}/*** ArrayList<byte[]>記錄分析List<String> 一條記錄是23個字節byte[] data,對其解碼如下* data[0]-data[1]:index data[2]-data[4]:over,金額溢出??? data[5]-data[8]:交易金額* ??代碼應該是(5,4) data[9]:如果等于0x06或者0x09,表示刷卡;否則是充值* data[10]-data[15]:刷卡機或充值機編號* data[16]-data[22]:日期String.format("%02X%02X.%02X.%02X %02X:%02X:%02X"* ,data[16], data[17], data[18], data[19], data[20], data[21], data[22]);*?* @param logs* @return*/private List<String> parseRecordsToStrings(ArrayList<byte[]>... Records) {List<String> recordsList = new ArrayList<String>();for (ArrayList<byte[]> record : Records) {if (record == null)continue;for (byte[] v : record) {StringBuilder r = new StringBuilder();int cash = Util.toInt(v, 5, 4);char t = (v[9] == TRANS_CSU || v[9] == TRANS_CSU_CPX) ? '-' : '+';r.append(String.format("%02X%02X.%02X.%02X %02X:%02X ", v[16], v[17], v[18], v[19], v[20], v[21], v[22]));r.append(" ? " + t).append(Util.toAmountString(cash / 100.0f));String aLog = r.toString();recordsList.add(aLog);}}return recordsList;}// byteArray轉化為intprivate int byteToInt(byte[] b, int n) {int ret = 0;for (int i = 0; i < n; i++) {ret = ret << 8;ret |= b[i] & 0x00FF;}if (ret > 100000 || ret < -100000)ret -= 0x80000000;return ret;}}
IsoDep主要用于讀取各城市公交卡信息如:武漢通,羊城通,深圳通,北京市政交通卡,長安通。
深圳通:
byte[] DFN_SRV = { (byte) 'P', (byte) 'A', (byte) 'Y',
(byte) '.', (byte) 'S', (byte) 'Z', (byte) 'T' };
武漢通:
byte[] DFN_SRV = { (byte) 0x41, (byte) 0x50,
(byte) 0x31, (byte) 0x2E, (byte) 0x57, (byte) 0x48, (byte) 0x43,
(byte) 0x54, (byte) 0x43, };
羊城通:
byte[] DFN_SRV = { (byte) 'P', (byte) 'A', (byte) 'Y',
(byte) '.', (byte) 'A', (byte) 'P', (byte) 'P', (byte) 'Y', };
長安通:
byte[] DFN_SRV = { (byte) 0xA0, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x86, (byte) 0x98,
(byte) 0x07, (byte) 0x01, };
北京市政交通卡:
byte[] DFI_EP = { (byte) 0x10, (byte) 0x01 };
5.非NDEF數據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){
}
6.非NDEF數據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();
}
7.非NDEF數據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);}
8.非NDEF數據NfcV讀取:
NfcV tech = NfcV.get(tag);if (tech != null) {try {tech.connect();if (tech.isConnected()) {byte[] tagUid = tag.getId();?int 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); ??byte[] response = tech.transceive(cmd);tech.close();if(response!=null){setNoteBody(new String(response, Charset.forName("utf-8")));}}} catch (IOException e) {}}
?
總結
以上是生活随笔為你收集整理的Android NFC标签读写 配置 过滤器总结 各类NFC数据类型NfcA NfcB IsoDep MifareClassic读取的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。