android nfc中MifareClassic格式的读写
2015-01-15 10:42
393 查看
Android支持的数据格式
数据格式的Intent filter
AndroidManifest.xml文件中,要像向下列示例那样,在<activity>元素内的<meta-data>元素中指定你创建的资源文件:
nfc_tech_filter.xml文件(一个Tag标签只有全部匹配tech-list元素中的tech元素指定的nfc芯片时才认为被匹配):
也可创建多个资源文件(多个资源文件是OR关系,每个资源文件中的芯片是AND关系):
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
或者在同一个资源文件中创建多个<tech-list>元素(多个<tech-list>元素之间是OR关系,<tech-list>元素中的<tech>是AND关系):
查看标签支持数据格式的方法:
通过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()
例子程序:
MainActivity:
清单文件:
数据格式的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 NfcAdapter mNfcAdapter; 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格式密码修改(键值keyA修改)
- android NFC开发案例+MifareClassic格式密码键值keyA修改
- Android应用实例之----MifareUltralight格式的nfc标签读写
- android nfc中Ndef格式的读写
- android nfc MifareUltralight读写
- Android NFC 开发教程(3): Mifare Tag 读写示例
- android nfc中Ndef格式的读写
- android nfc中Ndef格式的读写
- android nfc中Ndef格式的读写
- android nfc中Ndef格式的读写
- Android&nbsp;NFC&nbsp;Mifare&nbsp;Tag&nbsp;读写示例
- android nfc中Ndef格式的读写
- Android NFC 使用MifareUltralight读写数据
- Android NFC MifareClassic详解
- NFC的PN532读写命令格式
- Android&nbsp;NFC开发读写NDEF数据实例
- Android nfc模块读写MifareClassic卡50
- [Android基础]读写xml、json格式的数据