随着nfc智能手机越来越普及,nfc在生活中的应用也越来越多,加上最近自己也正好有点时间,因此打算研究一下nfc标签的读取,在网上找了一些资料,很多文章都写的很好,不过都是针对某种特定数据格式的nfc标签的读写,也由各种nfc的app可以读取各种类型的nfc标签,但是又没有源码,由此,本文主要是针对常用的nfc标签做基本读取操作,第一次发文章,如果有问题请大家指正。
nfc的基本介绍就不做说明了,网上有很多资料,下面主要描述nfc数据过滤、NDEF数据读取和非NDEF数据读取:
1、nfc数据过滤
nfc主要有三种过滤器,分别是NDEF_DISCOVERED,TECH_DISCOVERED,TAG_DISCOVERED,主要说明如下:
NDEF_DISCOVERED:当检测到标签中含有NDEF格式的数据,并且在应用中声明了可以接收ndef数据的intent时,触发该action的intent;
TECH_DISCOVERED:当没有应用响应NDEF_DISCOVERED时,会发出tech的intent;
TAG_DISCOVERED:当前两个intent都没有触发时,默认触发tag类型的intent;
(1) NDEF_DISCOVERED过滤定义:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"
android:host="developer.android.com"
android:pathPrefix="/index.html" />
</intent-filter>
(2)TECH_
DISCOVERED过滤定义:
<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" />
nfc_tech_filter文件:
<?xml version="1.0" encoding="utf-8"?>
<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>
(3) TAG_ DISCOVERED过滤:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
</intent-filter>
2、各类nfc数据读取
(1)NDEF数据读取
TNF_ABSOLUTE_URI读取:
private void parseAbsoluteUriRecode(NdefRecord record) {
byte[] payload = record.getPayload();
Uri uri = Uri.parse(new String(payload, Charset.forName("utf-8")));
setNoteBody(new String(payload, Charset.forName("utf-8")));
}
<span style="font-size: 13.3333px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> TNF_WELL_KNOWN的URI读取:</span>
<pre name="code" class="java">private void parseWellKnownUriRecode(NdefRecord record) {
Preconditions.checkArgument(Arrays.equals(record.getType(),
NdefRecord.RTD_URI));
byte[] payload = record.getPayload();
String prefix = URI_PREFIX_MAP.get(payload[0]);
byte[] fulluri = Bytes.concat(
prefix.getBytes(Charset.forName("utf-8")),
Arrays.copyOfRange(payload, 1, payload.length));
Uri uri = Uri.parse(new String(fulluri, Charset.forName("utf-8")));
setNoteBody(new String(fulluri, Charset.forName("utf-8")));
}
TNF_WELL_KNOWN的TEXT读取:
private void parseWellKnownTextRecode(NdefRecord record) {
Preconditions.checkArgument(Arrays.equals(record.getType(),
NdefRecord.RTD_TEXT));
String payloadStr = "";
byte[] payload = record.getPayload();
Byte statusByte = record.getPayload()[0];
String textEncoding = "";
textEncoding = ((statusByte & 0200) == 0) ? "utf-8" : "utf-16";
int languageCodeLength = 0;
languageCodeLength = statusByte & 0077;
try {
payloadStr = new String(payload, languageCodeLength + 1,
payload.length - languageCodeLength - 1, textEncoding);
} catch (UnsupportedEncodingException e) {
}
setNoteBody(payloadStr);
}
TNF_ABSOLUTE_URI的record类型和TNF_EXTERNAL_TYPE类型读取:
private void parseOtherRecode(NdefRecord record) {
byte[] payload = record.getPayload();
Uri uri = Uri.parse(new String(payload, Charset.forName("utf-8")));
setNoteBody(new String(payload, Charset.forName("utf-8")));
}
(2)非NDEF数据读取
MifareUltralight读取:
public String readTagUltralight(Tag tag) {
MifareUltralight mifare = MifareUltralight.get(tag);
try {
mifare.connect();
int size=mifare.PAGE_SIZE;
byte[] payload = mifare.readPages(0);
String result="page1:"+ByteArrayToHexString(payload)+"\n"+"总容量:"+String.valueOf(size)+"\n";
//这里只读取了其中几个page、
byte[] payload1 = mifare.readPages(4);
byte[] payload2 = mifare.readPages(8);
byte[] payload3 = mifare.readPages(12);
result+="page4:"+ByteArrayToHexString(payload1)+"\npage8:"+ByteArrayToHexString(payload2)+"\npage12:"+ByteArrayToHexString(payload3)+"\n";
//byte[] payload4 = mifare.readPages(16);
//byte[] payload5 = mifare.readPages(20);
return result;
//+ new String(payload4, Charset.forName("US-ASCII"));
//+ new String(payload5, Charset.forName("US-ASCII"));
} catch (IOException e) {
Log.e(TAG, "IOException while writing MifareUltralight message...",
e);
return "读取失败!";
} catch (Exception ee) {
Log.e(TAG, "IOException while writing MifareUltralight message...",
ee);
return "读取失败!";
} finally {
if (mifare != null) {
try {
mifare.close();
} catch (IOException e) {
Log.e(TAG, "Error closing tag...", e);
}
}
}
}
MifareClassic读取:
public String readTagClassic(Tag tag) {
boolean auth = false;
MifareClassic mfc = MifareClassic.get(tag);
// 读取TAG
try {
String metaInfo = "";
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_DEFAULT);
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 + " : "
+ ByteArrayToHexString(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;
}
IsoDep读取:
IsoDep isodep = IsoDep.get(tagFromIntent);
isodep.connect();
//select the card manager applet
byte[] mf = { (byte) '1', (byte) 'P',
(byte) 'A', (byte) 'Y', (byte) '.', (byte) 'S', (byte) 'Y',
(byte) 'S', (byte) '.', (byte) 'D', (byte) 'D', (byte) 'F',
(byte) '0', (byte) '1', };
String result="";
byte[] mfRsp = isodep.transceive(getSelectCommand(mf));
Log.d(TAG, "mfRsp:" + HexToString(mfRsp));
//select Main Application
byte[] wht = { (byte) 0x41, (byte) 0x50,//此处以武汉通为例,其它的卡片参考对应的命令,网上可以查到
(byte) 0x31, (byte) 0x2E, (byte) 0x57, (byte) 0x48, (byte) 0x43,
(byte) 0x54, (byte) 0x43, };
byte[] sztRsp = isodep.transceive(getSelectCommand(wht));
byte[] balance = { (byte) 0x80, (byte) 0x5C, 0x00, 0x02, 0x04};
byte[] balanceRsp = isodep.transceive(balance);
Log.d(TAG, "balanceRsp:" + HexToString(balanceRsp));
if(balanceRsp!=null && balanceRsp.length>4)
{
int cash = byteToInt(balanceRsp, 4);
float ba = cash / 100.0f;
result+=" 余额:"+String.valueOf(ba);
}
setNoteBody(result);
isodep.close();
NfcB读取:
nfcbTag = NfcB.get(tag);
try {
nfcbTag.connect();
if (nfcbTag.isConnected()) {
System.out.println("已连接");
Toast.makeText(MainActivity.this, "身份证已连接",
Toast.LENGTH_SHORT).show();
new CommandAsyncTask().execute();
}
// nfcbTag.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
NfcA读取:
NfcA nfca = NfcA.get(tagFromIntent);
try{
nfca.connect();
if (nfca.isConnected()) {//NTAG216的芯片
byte[] SELECT = {
(byte) 0x30,
(byte) 5 & 0x0ff,//0x05
};
byte[] response = nfca.transceive(SELECT);
nfca.close();
if(response!=null){
setNoteBody(new String(response, Charset.forName("utf-8")));
}
}
}
catch(Exception e){
}
NfcF读取:
NfcF nfc = NfcF.get(tag);
try {
nfc.connect();
byte[] felicaIDm = new byte[]{0};
byte[] req = readWithoutEncryption(felicaIDm, 10);
byte[] res = nfc.transceive(req);
nfc.close();
setNoteBody(ByteArrayToHexString(res));
} catch (Exception e) {
Log.e(TAG, e.getMessage() , e);
}
NfcV读取:
NfcV tech = NfcV.get(tag);
if (tech != null) {
try {
tech.connect();
if (tech.isConnected()) {
byte[] tagUid = tag.getId(); // store tag UID for use in addressed commands
int blockAddress = 0;
int blocknum = 4;
byte[] cmd = new byte[] {
(byte)0x22, // FLAGS
(byte)0x23, // 20-READ_SINGLE_BLOCK,23-所有块
0, 0, 0, 0, 0, 0, 0,0,
(byte)(blockAddress & 0x0ff),(byte)(blocknum-1 & 0x0ff)
};
System.arraycopy(tagUid, 0, cmd, 2, tagUid.length); // paste tag UID into command
byte[] response = tech.transceive(cmd);
tech.close();
if(response!=null){
setNoteBody(new String(response, Charset.forName("utf-8")));
}
}
} catch (IOException e) {
}
}
Ndef与NdefFormatable读取:
NdefMessage[] messages = getNdefMessages(getIntent());
byte[] payload = messages[0].getRecords()[0].getPayload();
setNoteBody(new String(payload));
NdefMessage[] getNdefMessages(Intent intent) {//读取nfc数据
// Parse the intent
NdefMessage[] msgs = null;
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
} else {
// Unknown tag type
byte[] empty = new byte[] {};
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
NdefMessage msg = new NdefMessage(new NdefRecord[] {
record
});
msgs = new NdefMessage[] {
msg
};
}
} else {
Log.d(TAG, "Unknown intent.");
finish();
}
return msgs;
}
最后提供一下源代码下载地址:http://download.csdn.net/detail/shjn2004/9610180