Android设备读写NFC标签
2016就這樣靜悄悄的過去了,最近也是頹廢的不行,都沒怎么充實自己了,每天練練車,打打游戲和麻將,書都基本沒翻個幾頁,家里完全沒有狀態。2017,加油吧,為了事業和家庭,Fighting!
關于接觸到NFC這東西,是我2年前導師項目中認識到的,當時自己也是剛學Android,由于項目需要,所以自己當時承擔了這方面的工作,由此也開啟了我Android生涯。想當初我也是翻遍了網上的所有資料,基本上沒有一個是完完全全寫好的,能直接拿來用的,當時能讀出一個標簽的id也是樂的不行,所以我當時在想,要是我弄好了,就分享下經驗,順便共享下代碼。但是為什么現在才寫呢,因為當時做完后也沒有繼續做這個了,導致這個事情也是一拖再拖,直到最近導師又需要這個,又拿出來把代碼改了改,才想起以前說要記錄的這事。
NFC(Near Field Communication)近場通信,屬于RFID中的一種,它是一種無源、低頻、近距離的通信方式。通過掃描方提供的電能,利用電磁感應原理來驅動標簽與掃描方進行通信。是一種快速,且安全的通信方式。現在廣泛運用于公交卡、地鐵票、門禁卡、校園卡等場景。現在應用比較廣泛的是MifareClassic 1K卡,屬于NfcA型標簽,NFC標簽共有4種類型的標簽,具體類型和用途不一,這里就不說了。而當時我項目中用到的就是NfcA型卡,對NfcA卡進行數據讀取和寫入。至于NFC標簽內部數據存放格式,讀寫的過程以及標簽扇區(sector)和塊(block)的概念,也就不說了,相信你可以通過其他途徑可以獲取到,這里我就只介紹NFC讀寫的代碼了。
完成后整個功能界面如下,由于主要是測試的玩,所以界面什么的就不用太在意了,功能實現就好了。
? ? ? ? ? ? ? ? ??
整個應用分為3大功能模塊:讀取標簽內存,將內存數據轉為Ascii碼,寫入數據。
? ? ? ? 后面的是sector和block是寫入數據時,自己要將數據寫入的扇區和塊,data是要寫入的數據。
首先你得擁有NFC標簽,相信這個不難,校園卡,地鐵票,公交卡什么的,都可以的。其次你得有讀寫的設備,作為Android開發者,相信你也不會專門買個讀寫的設備,不然就和Android聯系不上了,我們要做的是開發一個簡易版的NFC標簽讀寫軟件,所以你得有一個NFC讀寫的手機或Pad。好了,準備好了之后就可以測試玩一玩了。你也可以先從應用市場上下載NFC的應用,來測試你的設備是否支持NFC功能或者你的標簽有沒有問題。
1).新建Android項目,在res文件夾下新建一個xml的文件夾,里面放的是Android支持的NFC類型的配置數據。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>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.MifareUltralight</tech> <tech>android.nfc.tech.MifareClassic</tech></tech-list> </resources>2)在AndroidManifest中進行權限聲明:
?
?
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.nfc_test3"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="14"android:targetSdkVersion="21" /><uses-permission android:name="android.permission.NFC" /><uses-featureandroid:name="android.hardware.nfc"android:required="true" /><applicationandroid:allowBackup="true"android:icon="@drawable/nfc"android:label="@string/app_name" ><activityandroid:name="com.example.nfc_read_write.NfcRW"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /></intent-filter><intent-filter><action android:name="android.nfc.action.TAG_DISCOVERED" ></action><category android:name="android.intent.category.DEFAULT" ></category></intent-filter><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" /></activity></application></manifest>3)布局界面代碼如下activity_nfc_main:
?
?
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#748694"><LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:background="#A9A9A9"><TextViewandroid:id="@+id/tv1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="請將標簽靠近設備背面......" android:textSize="15sp"android:gravity="center"android:textColor="#0000ff"/><View android:layout_width="match_parent"android:layout_height="0.2dp"android:background="#000000"/><TextViewandroid:id="@+id/tv2"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="18sp"android:text="標簽的UID序列號為:"/><View android:layout_width="match_parent"android:layout_height="0.2dp"android:background="#000000"/><RelativeLayoutandroid:layout_width="fill_parent" android:layout_height="wrap_content" ><RadioGroup android:id="@+id/rdgb"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_read"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="讀取存儲" /><RadioButtonandroid:id="@+id/rb_Change"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:text="轉換為ASCll" /><RadioButtonandroid:id="@+id/rb_write"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:text="寫入數據" /></RadioGroup></RelativeLayout><View android:layout_width="match_parent"android:layout_height="0.2dp"android:background="#000000"/><TableLayout android:layout_width="fill_parent" android:layout_height="wrap_content" ><TableRow ><TextViewandroid:text="Sector" android:width="60dp"/><EditText android:id="@+id/etSector" android:width="120dp" android:numeric="integer"android:focusable="true"/><TextViewandroid:text="(starting at 1 To 15)" android:textColor="#FF00FF"android:width="150dp"/></TableRow> <TableRow ><TextViewandroid:text="Block" android:width="60dp"/><EditText android:id="@+id/etBlock" android:width="120dp" android:inputType="numberSigned"android:maxLength="1"android:digits="012"android:focusableInTouchMode="true"/><TextViewandroid:text="(starting at 0 To 2)" android:textColor="#FF00FF"android:width="150dp"/></TableRow> </TableLayout> <TableLayout android:layout_width="fill_parent" android:layout_height="wrap_content" ><TableRow ><TextViewandroid:text="Data" android:width="60dp"/><EditText android:id="@+id/etData" android:layout_width="match_parent"android:hint="Max 16 bytes(e.g.0CF6...)"/> </TableRow></TableLayout><View android:layout_width="match_parent"android:layout_height="0.2dp"android:background="#000000"/><TextViewandroid:id="@+id/tv3"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="內存詳細存儲信息......" android:textSize="15sp"android:gravity="center"/></LinearLayout></ScrollView>?
4)主界面 NfcRW.java
?
?
?
package com.example.nfc_read_write;import java.io.IOException; import java.util.logging.Logger;import com.example.nfc_test3.R;import android.app.Activity; import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; 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.MifareClassic; import android.nfc.tech.NfcA; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; import android.widget.EditText; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast;public class NfcRW extends Activity {TextView tv1, tv2, tv3;EditText etSector, etBlock, etData;// private NfcAdapter nfcAdapter;private PendingIntent mPendingIntent;private IntentFilter[] mFilters;private String[][] mTechLists;private int mCount = 0;String info = "";private int bIndex;private int bCount;private int BlockData;private String BlockInfo;private RadioButton mRead, mWriteData, mChange;private byte[] b3;byte[] code=MifareClassic.KEY_NFC_FORUM;//讀寫標簽中每個塊的密碼private byte[] data3, b0;private String temp = "";private NfcAdapter mNfcAdapter;private Context mContext;int block[] = { 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 24,25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 46,48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62 };// private StringBuilder metaInfo=new StringBuilder();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_nfc_main);mContext = this;checkNFCFunction(); // NFC Checkinit();mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);// Setup an intent filter for all MIME based dispatchesIntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);try {ndef.addDataType("*/*");} catch (MalformedMimeTypeException e) {throw new RuntimeException("fail", e);}mFilters = new IntentFilter[] { ndef, };// 根據標簽類型設置mTechLists = new String[][] { new String[] { NfcA.class.getName() } };}private void checkNFCFunction() {// TODO Auto-generated method stubmNfcAdapter = NfcAdapter.getDefaultAdapter(this);// check the NFC adapter firstif (mNfcAdapter == null) {// mTextView.setText("NFC apdater is not available");Dialog dialog = null;CustomDialog.Builder customBuilder = new CustomDialog.Builder(mContext);customBuilder.setTitle("很遺憾").setMessage("沒發現NFC設備,請確認您的設備支持NFC功能!").setIcon(R.drawable.dialog_icon2).setPositiveButton("是",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {dialog.dismiss();finish();}});dialog = customBuilder.create();dialog.setCancelable(false);// backdialog.setCanceledOnTouchOutside(false);SetDialogWidth(dialog).show();return;} else {if (!mNfcAdapter.isEnabled()) {Dialog dialog = null;CustomDialog.Builder customBuilder = new CustomDialog.Builder(mContext);customBuilder.setTitle("提示").setMessage("請確認NFC功能是否開啟!").setIcon(R.drawable.dialog_icon2).setPositiveButton("現在去開啟......",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {dialog.dismiss();Intent setnfc = new Intent(Settings.ACTION_NFC_SETTINGS);startActivity(setnfc);}});dialog = customBuilder.create();dialog.setCancelable(false);// backdialog.setCanceledOnTouchOutside(false);SetDialogWidth(dialog).show();return;}}}private Dialog SetDialogWidth(Dialog dialog) {// TODO 自動生成的方法存根DisplayMetrics dm = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);int screenWidth = dm.widthPixels;int screenHeight = dm.heightPixels;WindowManager.LayoutParams params = dialog.getWindow().getAttributes();if (screenWidth > screenHeight) {params.width = (int) (((float) screenHeight) * 0.875);} else {params.width = (int) (((float) screenWidth) * 0.875);}dialog.getWindow().setAttributes(params);return dialog;}private void init() {// TODO 自動生成的方法存根tv1 = (TextView) findViewById(R.id.tv1);tv2 = (TextView) findViewById(R.id.tv2);tv3 = (TextView) findViewById(R.id.tv3);etSector = (EditText) findViewById(R.id.etSector);etBlock = (EditText) findViewById(R.id.etBlock);etData = (EditText) findViewById(R.id.etData);mRead = (RadioButton) findViewById(R.id.rb_read);mWriteData = (RadioButton) findViewById(R.id.rb_write);mChange = (RadioButton) findViewById(R.id.rb_Change);}@Overrideprotected void onResume() {// TODO 自動生成的方法存根super.onResume();enableForegroundDispatch();// mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters,// mTechLists);}private void enableForegroundDispatch() {// TODO 自動生成的方法存根if (mNfcAdapter != null) {mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,mFilters, mTechLists);}}@Overrideprotected void onNewIntent(Intent intent) {// TODO 自動生成的方法存根super.onNewIntent(intent);tv1.setText("發現新的 Tag: " + ++mCount + "\n");// mCount 計數String intentActionStr = intent.getAction();// 獲取到本次啟動的actionif (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intentActionStr)// NDEF類型|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(intentActionStr)// 其他類型|| NfcAdapter.ACTION_TAG_DISCOVERED.equals(intentActionStr)) {// 未知類型// 在intent中讀取Tag idTag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);byte[] bytesId = tag.getId();// 獲取id數組info += ByteArrayChange.ByteArrayToHexString(bytesId) + "\n";tv2.setText("標簽UID: " + "\n" + info);// 讀取存儲信息if (mRead.isChecked()) {// mChange=false;tv3.setText("讀取成功! " + readTag(tag));// readNfcVTag(tag);etSector.setText("");etBlock.setText("");etData.setText("");}// 寫數據if (mWriteData.isChecked()) {//writeTag(tag);String str= etData.getText().toString();writeTag(tag,str);}// 轉換為ASCllif (mChange.isChecked()) {tv3.setText(change(tag));Toast.makeText(getBaseContext(), "轉換成功", 1).show();etSector.setText("");etBlock.setText("");etData.setText("");}}}// 寫數據public void writeTag(Tag tag, String str) {MifareClassic mfc = MifareClassic.get(tag);try {if (mfc != null) {mfc.connect();} else {Toast.makeText(mContext, "寫入失敗", 1).show();return;}Log.i("write", "----connect-------------");boolean CodeAuth = false;byte[] b1 = str.getBytes();if (b1.length <= 720) {//System.out.println("------b1.length:" + b1.length);int num = b1.length / 16;System.out.println("num= " + num);int next = b1.length / 48 + 1;System.out.println("扇區next的值為" + next);b0 = new byte[16];if (!(b1.length % 16 == 0)) {for (int i = 1, j = 1; i <= num; i++) {CodeAuth = mfc.authenticateSectorWithKeyA(j, code);System.arraycopy(b1, 16 * (i - 1), b0, 0, 16);mfc.writeBlock(block[i - 1], b0);if (i % 3 == 0) {j++;}}//Log.d("下一個模塊", "測試");CodeAuth = mfc.authenticateSectorWithKeyA(next,// 非常重要------code);//Log.d("獲取第5塊的密碼", "---成功-------");byte[] b2 = { 0 };b0 = new byte[16];System.arraycopy(b1, 16 * num, b0, 0, b1.length % 16);System.arraycopy(b2, 0, b0, b1.length % 16, b2.length);mfc.writeBlock(block[num], b0);mfc.close();Toast.makeText(this, "寫入成功", Toast.LENGTH_SHORT).show();return;} else {for (int i = 1, j = 1; i <= num; i++) {if (i % 3 == 0) {j++;System.out.println("扇區j的值為:" + j);}CodeAuth = mfc.authenticateSectorWithKeyA(j,// 非常重要---------code);System.arraycopy(b1, 16 * (i - 1), b0, 0, 16);mfc.writeBlock(block[i - 1], b0);str += ByteArrayChange.ByteArrayToHexString(b0);System.out.println("Block" + i + ": " + str);}mfc.close();Toast.makeText(this, "寫入成功", Toast.LENGTH_SHORT).show();return;}} else {Toast.makeText(getBaseContext(), "字符過長,內存不足", 1).show();return;}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {mfc.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}// //讀取數據public String readTag(Tag tag) {MifareClassic mfc = MifareClassic.get(tag);for (String tech : tag.getTechList()) {System.out.println(tech);// 顯示設備支持技術}boolean auth = false;// 讀取TAGtry {// metaInfo.delete(0, metaInfo.length());//清空StringBuilder;StringBuilder metaInfo = new StringBuilder();// 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.append(" 卡片類型:" + 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_NFC_FORUM);// 逐個獲取密碼/** byte[]* codeByte_Default=MifareClassic.KEY_DEFAULT;//FFFFFFFFFFFF* byte[]* codeByte_Directory=MifareClassic.KEY_MIFARE_APPLICATION_DIRECTORY* ;//A0A1A2A3A4A5 byte[]* codeByte_Forum=MifareClassic.KEY_NFC_FORUM;//D3F7D3F7D3F7*/if (auth) {metaInfo.append("Sector " + j + ":驗證成功\n");// 讀取扇區中的塊bCount = mfc.getBlockCountInSector(j);bIndex = mfc.sectorToBlock(j);for (int i = 0; i < bCount; i++) {byte[] data = mfc.readBlock(bIndex);metaInfo.append("Block " + bIndex + " : "+ ByteArrayChange.ByteArrayToHexString(data)+ "\n");bIndex++;}} else {metaInfo.append("Sector " + j + ":驗證失敗\n");}}return metaInfo.toString();} 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;}// 轉換Hex為字符串public String change(Tag tag) {MifareClassic mfc = MifareClassic.get(tag);Log.d("----------", "change----------");boolean auth = false;// 讀取TAGString ChangeInfo = "";String Ascll = "";// Enable I/O operations to the tag from this TagTechnology object.try {mfc.connect();int sectorCount = mfc.getSectorCount();// 獲取TAG中包含的扇區數for (int j = 1; j < sectorCount; j++) {// Authenticate a sector with key A.auth = mfc.authenticateSectorWithKeyA(j,MifareClassic.KEY_NFC_FORUM);if (auth) {Log.i("change 的auth驗證成功", "開始讀取模塊信息");byte[] data0 = mfc.readBlock(4 * j);byte[] data1 = mfc.readBlock(4 * j + 1);byte[] data2 = mfc.readBlock(4 * j + 2);data3 = new byte[data0.length + data1.length + data2.length];System.arraycopy(data0, 0, data3, 0, data0.length);System.arraycopy(data1, 0, data3, data0.length,data1.length);System.arraycopy(data2, 0, data3, data0.length+ data1.length, data2.length);ChangeInfo = ByteArrayChange.ByteArrayToHexString(data3);temp = "扇區" + (j) + "里的內容為:"+ ToStringHex.decode(ChangeInfo) + "\n";}Ascll += temp;}return Ascll;} catch (IOException e) {// TODO 自動生成的 catch 塊e.printStackTrace();Toast.makeText(getBaseContext(), "轉換失敗", 1).show();} finally {if (mfc != null) {try {mfc.close();} catch (IOException e) {Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();}}}return "";}public int StringToInt(String s) {if (!(TextUtils.isEmpty(s)) || s.length() > 0) {BlockData = Integer.parseInt(s);} else {Toast.makeText(NfcRW.this, "Block輸入有誤", 1).show();}System.out.println(BlockData);return BlockData;}@Overridepublic void onPause() {super.onPause();disableForegroundDispatch();}private void disableForegroundDispatch() {// TODO 自動生成的方法存根if (mNfcAdapter != null) {mNfcAdapter.disableForegroundDispatch(this);}} }5)由于標簽中的數據都是byte型,需要轉為16進制Ascii碼數據。
?
ByteArrayChange.java
?
package com.example.nfc_read_write;public class ByteArrayChange {//轉換法1 格式為0xabcd1234 字母小寫/* public static String ByteArrayToHexString(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();}*///轉換法2 格式為 ABCD1234 字母大寫public static String ByteArrayToHexString(byte[] bytesId) { //Byte數組轉換為16進制字符串// TODO 自動生成的方法存根int i, j, in;String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};String output = "";for (j = 0; j < bytesId.length; ++j) {in = bytesId[j] & 0xff;i = (in >> 4) & 0x0f;output += hex[i];i = in & 0x0f;output += hex[i];}return output;} }
6)在進行讀取16進制數據時,我們將其內容轉換(翻譯)為我們比較熟悉的中文
?
?ToStringHex.java
?
package com.example.nfc_read_write;import java.io.ByteArrayOutputStream;public class ToStringHex {// 將字符串編碼成16進制數字,適用于所有字符(包括中文)private static String hexString = "0123456789ABCDEF";/*** 將字符串編碼成16進制數字,適用于所有字符(包括中文)*/public static String encode(String str) {// 根據默認編碼獲取字節數組byte[] bytes = str.getBytes();StringBuilder sb = new StringBuilder(bytes.length * 2);// 將字節數組中每個字節拆解成2位16進制整數for (int i = 0; i < bytes.length; i++) {sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));}return sb.toString();}/** 將16進制數字解碼成字符串,適用于所有字符(包括中文)* * @param bytes* @return*/public static String decode(String bytes) {ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);// 將每2位16進制整數組裝成一個字節for (int i = 0; i < bytes.length(); i += 2)baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));return new String(baos.toByteArray());}// 轉化十六進制編碼為ASCll字符串public static String toStringHex(String s) {byte[] baKeyword = new byte[s.length() / 2]; // ------------------for (int i = 0; i < baKeyword.length; i++) {try {baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));} catch (Exception e) {e.printStackTrace();}}try {s = new String(baKeyword, "utf-8");// UTF-16le:Not} catch (Exception e1) {e1.printStackTrace();}return s;} }?
項目源碼地址,點我下載。
PS:現已更新,可以下載了,好像現在CSDN上傳文件時,必須說要下載積分,以前不要積分的全部不能下載了,現在更新了。2017-08-12
?
注:關于NFC的Android 軟件,大家可以去應用市場下載 ? NFC玩家 ? 和 ? Mifare Classic ?Tool(MCT) ? 這2個app,然后對比下,基本原理差不多的。
??其中在主界面activity中進行標簽的數據讀寫時,要切記如何讀取失敗的話,很可能是塊密碼不對,要更換密碼。一般的標簽,塊密碼是默認的,默認的有3種,可以根據實際情況進行更換。新手,兩年前的代碼中寫的比較亂了,不想改了,有不懂的,或者有問題的,可以留言探討。
?
?
?
?
總結
以上是生活随笔為你收集整理的Android设备读写NFC标签的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 布谷鸟沙盒分析静态文件_“案例沙盒方法”
- 下一篇: 一起来看流星雨剧情简介/剧情介绍/剧情分