android nfc中MifareClassic格式的读写
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标签的数据结构
注意事项(假设1k空间):
第一扇区的第一块一般用于制造商占用块
0-15个扇区:一个扇区对应4个块,所以总共有64个块,序号分别为0-63,第一个扇区对应:0-3块,第二个扇区对应:4-7块...
每个扇区的最后一个块用来存放密码或控制位,其余为数据块,一个块占用16个字节,keyA占用6字节,控制位占用4字节,keyB占用6字节
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写入当前块;注意:data必须刚好是16Byte,末尾不能用0填充,应该用空格
readBlock(int):读取当前块的数据。
close():禁止对标签的IO操作,释放资源。
MifareClassic标签的读写流程
获得Adapter对象
获得Tag对象
获得MifareClassic对象
读取数据块的数据
Connect(),readBlock(),close()
获得Adapter对象
获得Tag对象
获得MifareClassic对象
将数据块写入标签
Connect(),writeBlock(),close()
官方文档:
Working with tag technologies and the ACTION_TECH_DISCOVERED intent
When a device scans a tag that has NDEF data on it, but could not be mapped to a MIME or URI, the tag dispatch system tries to start an activity with the ACTION_TECH_DISCOVERED intent. The ACTION_TECH_DISCOVERED is also used when a tag with non-NDEF data is scanned. Having this fallback allows you to work with the data on the tag directly if the tag dispatch system could not parse it for you. The basic steps when working with tag technologies are as follows:
- Filter for an
ACTION_TECH_DISCOVEREDintent specifying the tag technologies that you want to handle. SeeFiltering for NFC intents for more information. In general, the tag dispatch system tries to start aACTION_TECH_DISCOVEREDintent when an NDEF message cannot be mapped to a MIME type or URI, or if the tag scanned did not contain NDEF data. For more information on how this is determined, see The Tag Dispatch System. - When your application receives the intent, obtain the
Tagobject from the intent:Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
- Obtain an instance of a
TagTechnology, by calling one of thegetfactory methods of the classes in theandroid.nfc.techpackage. You can enumerate the supported technologies of the tag by callinggetTechList()before calling agetfactory method. For example, to obtain an instance ofMifareUltralightfrom aTag, do the following:MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
Reading and writing to tags
Reading and writing to an NFC tag involves obtaining the tag from the intent and opening communication with the tag. You must define your own protocol stack to read and write data to the tag. Keep in mind, however, that you can still read and write NDEF data when working directly with a tag. It is up to you how you want to structure things. The following example shows how to work with a MIFARE Ultralight tag.
package com.example.android.nfc; import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) {
MifareUltralight ultralight = MifareUltralight.get(tag);
try {
ultralight.connect();
ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII")));
} catch (IOException e) {
Log.e(TAG, "IOException while closing MifareUltralight...", e);
} finally {
try {
ultralight.close();
} catch (IOException e) {
Log.e(TAG, "IOException while closing MifareUltralight...", e);
}
}
} public String readTag(Tag tag) {
MifareUltralight mifare = MifareUltralight.get(tag);
try {
mifare.connect();
byte[] payload = mifare.readPages(4);
return new String(payload, Charset.forName("US-ASCII"));
} catch (IOException e) {
Log.e(TAG, "IOException while writing MifareUltralight
message...", e);
} finally {
if (mifare != null) {
try {
mifare.close();
}
catch (IOException e) {
Log.e(TAG, "Error closing tag...", e);
}
}
}
return null;
}
}
例子程序:
- <?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中Ndef格式的读写
1. 在onCreate()中获取NfcAdapter对象: NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); 2.在onNewI ...
- 【转】Android NFC学习笔记
一:NFC的tag分发系统 如果想让android设备感应到NFC标签,你要保证两点 1:屏幕没有锁住 2:NFC功能已经在设置中打开 当系统检测到一个NFC标签的时候,他会自动去寻找最合适的acti ...
- Android NFC开发概述
NFC手机相比普通手机来说,有以下3个附加功能: 1.可以当成POS机来用,也就是“读取”模式 2.可以当成一张卡来刷,也就是NFC技术最核心的移动支付功能 3.可以像蓝牙.Wi-Fi一样做点 ...
- ANDROID NFC读M1卡
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.Cons ...
- Android NFC M1卡读写&芯片卡读写(CPU卡读写)(RFID读写)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/sgn5200/article/detai ...
- Android NFC近场通信03----读写MifareClassic卡
Android NFC近场通信02----读写MifareClassic卡 一.MifareClassic卡 相关 一般来 ...
- NFC(11)MifareUltralight格式规范及读写示例
注意 MifareUltralight 不支三种过滤方式之一,只支持第四种(用代码,activity singleTop ) 见 NFC(4)响应NFC设备时启动activity的四重过滤机制 Mi ...
- Android开发中 .9.png格式图形设计:
Android .9.png设计 宿舍大神在做android项目,有幸得知.9.png的图形格式. 不知道大家是否注意过聊天气泡和锁屏时随着你文字的增多和你的滑动而跟着变化并且分辨率没有变低的图形?是 ...
- 在Android源码树中添加userspace I2C读写工具(i2c-util)
在Android源码树中添加userspace I2C读写工具(i2c-util) http://blog.csdn.net/21cnbao/article/details/7919055 分类: A ...
随机推荐
- Node.js-安装配置【1】-在Windows XP系统配置环境变量
家里有台老古董台式机,安装的是Windows XP系统,摸索了一下,成功的在上面安装配置好了Node.js V4.4.7 一.安装Node.js(过程略) 二.npm配置全局和缓存路径(过程略) 三. ...
- [BZOJ3139][HNOI2013] 比赛
Description 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局,两支球队各 ...
- 【BZOJ3669】[Noi2014]魔法森林 LCT
终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...
- A star 寻路
大白话说一下几个点: 通俗的来说,其实就是以一个规则来 从A点走到B点. 怎么来判断我们走的格子是一个合适的格子? 就是靠一个规则来计算,这个规则就是估价函数. 估价函数: 常用:曼哈顿算法 F = ...
- 【Oracle】Oracle 序列步长问题
问题: 数据库中客户表的ID 变化为 21\31\41 有序数字,而不是1\2\3 依次增长 [问题原因]: SEQ_CUSTOMNOTEEN 设置了缓存20,每次取20个数,然后一个一个给你,如果中 ...
- CSS常用属性
//边界线 border: 1px solid #E4E4E4; //绝对 定位 position: absolute; //相对定位 position: relative; //超出部分隐藏 ove ...
- 随鼠标轮动翻动层————jquery小练习
闲来无事在网站上看见一个网页制作的不错,就仿照做来看看.特此记录下来. 亮点:随鼠标上下滚动,展示页面随之不同,翻动效果. 功能点:鼠标向上,向下判断事件. css 代码 html { overflo ...
- Node.js的学习路线
http://www.admin10000.com/document/4624.html 顺便关注一下博客:http://blog.fens.me/series-nodejs/ php socket框 ...
- Unity学习疑问记录之界面适配
Unity3d UGUI 界面适配 实例解析 三种适配方式 http://www.mamicode.com/info-detail-475563.html
- google protobuf初体验
最近在读别人代码的时候发现一个的东西,名字叫protobuf, 感觉挺好用的,写在这里,留个记录.那么什么是protobuf 呢?假如您在网上搜索,应该会得到类似这样的文字介绍: Google Pro ...