android nfc中MifareClassic格式的读写
来源:互联网 发布:cpda数据分析师考试 编辑:程序博客网 时间:2024/05/20 08:42
Android支持的数据格式
数据格式的Intent filter
AndroidManifest.xml文件中,要像向下列示例那样,在<activity>元素内的<meta-data>元素中指定你创建的资源文件:
<activity>... <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>nfc_tech_filter.xml文件(一个Tag标签只有全部匹配tech-list元素中的tech元素指定的nfc芯片时才认为被匹配):
<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>
也可创建多个资源文件(多个资源文件是OR关系,每个资源文件中的芯片是AND关系):
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list></resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.Ndef</tech> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list></resources>或者在同一个资源文件中创建多个<tech-list>元素(多个<tech-list>元素之间是OR关系,<tech-list>元素中的<tech>是AND关系):
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <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.MifareClassic</tech> </tech-list></resources>查看标签支持数据格式的方法:
通过Tag.getTechlist()方法,获得标签所支持的数据格式
通过Tag.getId()方法,获得标签的唯一ID标识
NfcAdapter == null:表示设备不支持NFC硬件
NfcAdapter.isEnable()方法:判断NFC是否开启
综上所述:
一个Tag通过Tag.getTechlist()方法获取它所支持的所有标签类型,如果清单文件中所引用的<tech-list>资源文件中所有的<tech>中的芯片是Tag标签所有支持标签的子集则被匹配的,可以写多个<tech-list>,每个<tech-list>时独立的,只要有其中一个<tech-list>中的所有的<tech>中的芯片类型全部匹配Tag所支持的芯片则认为是匹配的。多个<tech-list>是OR关系,<tech-list>中的<tech>是AND关系。
MifareClassic标签的外形结构
MifareClassic标签的数据结构
MifareClassic类的常用方法
get():根据Tag对象来获得MifareClassic对象;
Connect():允许对MifareClassic标签进行IO操作;
getType():获得MifareClassic标签的具体类型:TYPE_CLASSIC,TYPE_PLUA,TYPE_PRO,TYPE_UNKNOWN;
getSectorCount():获得标签总共有的扇区数量;
getBlockCount():获得标签总共有的的块数量;
getSize():获得标签的容量:SIZE_1K,SIZE_2K,SIZE_4K,SIZE_MINI
authenticateSectorWithKeyA(int SectorIndex,byte[] Key):验证当前扇区的KeyA密码,返回值为ture或false。
常用KeyA:默认出厂密码:KEY_DEFAULT,
各种用途的供货商必须配合该技术的MAD:KEY_MIFARE_APPLICATION_DIRECTORY
被格式化成NDEF格式的密码:KEY_NFC_FORUM
getBlockCountInSector(int):获得当前扇区的所包含块的数量;
sectorToBlock(int):当前扇区的第1块的块号;
WriteBlock(int,data):将数据data写入当前块;
readBlock(int):读取当前块的数据。
close():禁止对标签的IO操作,释放资源。
MifareClassic标签的读写流程
获得Adapter对象
获得Tag对象
获得MifareClassic对象
读取数据块的数据
Connect(),readBlock(),close()
获得Adapter对象
获得Tag对象
获得MifareClassic对象
将数据块写入标签
Connect(),writeBlock(),close()
例子程序:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <CheckBox android:id="@+id/checkbox_write" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="是否向NFC标签写入数据" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:text="请将NFC标签或贴纸靠近手机背面" android:textSize="16sp" /> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:src="@drawable/read_nfc_tag" /></LinearLayout>MainActivity:
package mobile.android.mifareultralight;import java.io.IOException;import java.nio.charset.Charset;import android.app.Activity;import android.app.PendingIntent;import android.content.Intent;import android.nfc.NfcAdapter;import android.nfc.Tag;import android.nfc.tech.MifareClassic;import android.os.Bundle;import android.util.Log;import android.widget.CheckBox;import android.widget.Toast;public class MifareultralightMainActivity extends Activity { private CheckBox mWriteData; private NfcAdaptermNfcAdapter; private PendingIntent mPendingIntent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mifareultralight); mWriteData = (CheckBox) findViewById(R.id.checkbox_write); mNfcAdapter = mNfcAdapter.getDefaultAdapter(this); if (mNfcAdapter == null) { Toast.makeText(this, "设备不支持NFC!", Toast.LENGTH_LONG).show(); finish(); return; } if (!mNfcAdapter.isEnabled()) { Toast.makeText(this, "请在系统设置中先启用NFC功能!", Toast.LENGTH_LONG).show(); finish(); return; } mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0); } @Override public void onResume() { super.onResume(); if (mNfcAdapter != null) mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); } @Override public void onNewIntent(Intent intent) { Tag tag = intent.getParcelableExtra(mNfcAdapter.EXTRA_TAG); String[] techList = tag.getTechList(); boolean haveMifareUltralight = false; for (String tech : techList) { if (tech.indexOf("MifareClassic") >= 0) { haveMifareUltralight = true; break; } } if (!haveMifareUltralight) { Toast.makeText(this, "不支持MifareClassic", Toast.LENGTH_LONG).show(); return; } if (mWriteData.isChecked()) { writeTag(tag); } else { String data = readTag(tag); if (data != null) { Log.i(data, "ouput"); Toast.makeText(this, data, Toast.LENGTH_LONG).show(); } } } @Override public void onPause() { super.onPause(); if (mNfcAdapter != null) mNfcAdapter.disableForegroundDispatch(this); } public void writeTag(Tag tag) { MifareClassic mfc = MifareClassic.get(tag); try { mfc.connect(); boolean auth = false; short sectorAddress = 1; auth = mfc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_NFC_FORUM); if (auth) { // the last block of the sector is used for KeyA and KeyB cannot be overwritted mfc.writeBlock(4, "1313838438000000".getBytes()); mfc.writeBlock(5, "1322676888000000".getBytes()); mfc.close(); Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { mfc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //字符序列转换为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(); } public String readTag(Tag tag) { MifareClassic mfc = MifareClassic.get(tag); for (String tech : tag.getTechList()) { System.out.println(tech); } boolean auth = false; //读取TAG try { String metaInfo = ""; //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 += "卡片类型:" + 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); 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"; } } 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; }}清单文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mobile.android.mifareultralight" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.NFC" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MifareultralightMainActivity" android:label="Mifareultralight" android:launchMode="singleTop" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
- android nfc中MifareClassic格式的读写
- android nfc中MifareClassic格式的读写
- android nfc中MifareClassic格式的读写
- android nfc中MifareClassic格式的读写
- NFC读写MifareClassic协议的NFC卡
- Android nfc模块读写MifareClassic卡50
- Android nfc模块读写MifareClassic卡50
- android nfc中Ndef格式的读写
- android nfc中Ndef格式的读写
- android nfc中Ndef格式的读写
- android nfc中Ndef格式的读写
- 读写MifareClassic协议的NFC卡
- NFC (二)读写MifareClassic协议的NFC卡
- NFC (二)读写MifareClassic协议的NFC卡
- Android NFC MifareClassic详解
- Android NFC相关资料之MifareClassic卡(读写)
- Android NFC近场通信03----读写MifareClassic卡
- Android NFC相关资料之MifareClassic卡(读写)
- 关于iOS8下注册本地通知的一些笔记
- Maven仓库管理-Nexus
- Linux最帅版主所经历的面试题,全部答对月薪10K+ ...答案公布
- 芯客-互联网硬件化的最强支柱
- 在linux下出现cannot restore segment prot after reloc: Permission denied
- android nfc中MifareClassic格式的读写
- 结构型模式-外观
- nyoj题目67:三角形面积
- apache worker 模块 线程连接数简单介绍
- 线程死锁
- android L 启动流程
- A*算法理论与实践
- 基于.NET的大型Web站点StackOverflow架构分析
- KDD 2014 “A Dirichlet Multinomial Mixture Model-based Approach for Short Text Clustering” 的主要思想