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种,可以根据实际情况进行更换。新手,两年前的代码中写的比较乱了,不想改了,有不懂的,或者有问题的,可以留言探讨。
- Android设备读写NFC标签
- Android NFC 标签 读写
- Android平台上读写NFC标签
- Android平台上读写NFC标签
- Android平台上读写NFC标签 原理
- Android开发——NFC标签读写
- NFC标签的读写
- Android 使用NFC通过标签协议栈读写标签数据
- Android基础——NFC标签初始化设置、NFC标签读写数据和获取ID、NFC标签前台调度系统
- NFC之读写NFC标签的文本
- Android应用实例之----MifareUltralight格式的nfc标签读写
- android NFC 读写
- android nfc MifareUltralight读写
- android NFC的读写
- Android读写NFC
- Android NFC标签添加联系人
- android nfc常用标签读取
- Android NFC标签写入问题
- 我的2016 “CSDN博客之星” 韩俊强的博客
- 数据结构与算法(C语言版)__哈希和映射
- 安装Oracle 11gR2 64bit时,克隆数据库卡在2%,日志提示“Caused by: PRCT-1400 : 未能执行 getcrshome”的解决方法
- xcode8删除文件后的警告处理
- UML图之验收篇
- Android设备读写NFC标签
- 深入理解计算机系统--第二章(信息的表示和处理)
- Jboss EAP 6.2以上版本管理用户权限
- 单链表建立 插入 删除
- <<摸着石头过河>>摘录一
- struts.xml配置
- Android实现微信支付纪录篇
- phoenix-4.8.0整合hbase-1.2.0-cdh5.8.0
- codevs1029遍历问题