Android设备读写NFC标签

来源:互联网 发布:大数据风控 汽车金融 编辑:程序博客网 时间:2024/05/21 07:05

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-sdk        android:minSdkVersion="14"        android:targetSdkVersion="21" />    <uses-permission android:name="android.permission.NFC" />    <uses-feature        android:name="android.hardware.nfc"        android:required="true" />    <application        android:allowBackup="true"        android:icon="@drawable/nfc"        android:label="@string/app_name" >        <activity            android: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-data                android: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">    <TextView        android: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"       />   <TextView        android: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"       />       <RelativeLayout        android: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"           >        <RadioButton            android:id="@+id/rb_read"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="读取存储"             />        <RadioButton            android: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" />        <RadioButton            android: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 >           <TextView             android:text="Sector"              android:width="60dp"/>                      <EditText               android:id="@+id/etSector"               android:width="120dp"               android:numeric="integer"              android:focusable="true"/>           <TextView             android:text="(starting at 1 To 15)"              android:textColor="#FF00FF"             android:width="150dp"/>       </TableRow>                 <TableRow >           <TextView             android: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"/>           <TextView             android: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 >           <TextView             android: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"       />    <TextView        android: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;}}

项目源码地址,点我下载


其中在主界面activity中进行标签的数据读写时,要切记如何读取失败的话,很可能是块密码不对,要更换密码。一般的标签,块密码是默认的,默认的有3种,可以根据实际情况进行更换。新手,两年前的代码中写的比较乱了,不想改了,有不懂的,或者有问题的,可以留言探讨。


1 0
原创粉丝点击