NFC标签解析
本文讲NFC各种标签的解析实现,本文从Tag讲起,如何拿到Tag请看Android NFC之读卡器模式
import android.nfc.Tag;
import java.io.Closeable;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public abstract class CardReader {
public static String getId(Tag tag) {
return ByteArrayToHexString(tag.getId());
}
public static final String readTag(Tag tag) {
CardReader reader = with(tag);
if (reader == null) {
return "暂不支持此卡类型";
}
return reader.parse(tag);
}
public static final CardReader with(Tag tag) {
List<String> techs = Arrays.asList(tag.getTechList());
if (techs.contains("android.nfc.tech.IsoDep")) {
return new CustomIsoDepReader();
}
if (techs.contains("android.nfc.tech.NfcBarcode")) {
return new NfcBarcodeReader();
}
if (techs.contains("android.nfc.tech.MifareClassic")) {
return new MifareClassicReader();
}
if (techs.contains("android.nfc.tech.MifareUltralight")) {
return new MifareUltralightReader();
}
if (techs.contains("android.nfc.tech.Ndef")) {
return new NdefReader();
}
if (techs.contains("android.nfc.tech.NfcA")) {
return new NfcAReader();
}
if (techs.contains("android.nfc.tech.NfcB")) {
return new NfcBReader();
}
if (techs.contains("android.nfc.tech.NfcV")) {
return new NfcVReader();
}
if (techs.contains("android.nfc.tech.NfcF")) {
return new NfcFReader();
}
if (techs.contains("android.nfc.tech.NdefFormatable")) {
}
return null;
}
public abstract String parse(Tag tag);
protected static String ByteArrayToHexString(byte[] inarray) {
int i, j, in;
String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
String out = "";
for (j = 0; j < inarray.length; ++j) {
in = (int) inarray[j] & 0xff;
i = (in >> 4) & 0x0f;
out += hex[i];
i = in & 0x0f;
out += hex[i];
}
return out;
}
protected static byte[] HexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
protected void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
closeable = null;
}
}
}
1.Ndef
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
public class NdefReader extends CardReader {
@Override
public String parse(Tag tag) {
Ndef ndef = Ndef.get(tag);
try {
ndef.connect();
NdefMessage ndefMessage = ndef.getNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
if (records == null || records.length <= 0) {
return "getRecords() is null";
}
StringBuffer buffer = new StringBuffer();
for (NdefRecord record : records) {
buffer.append("\nNdefRecord:").append(record.toString());
}
return buffer.toString();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
} finally {
close(ndef);
}
}
}
2.MifareClassic
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.util.Log;
import java.io.IOException;
public class MifareClassicReader extends CardReader {
private static final String TAG = "MifareClassicReader";
@Override
public String parse(Tag tag) {
MifareClassic mifareClassic = MifareClassic.get(tag);
try {
mifareClassic.connect();
int type = mifareClassic.getType();
int sectorCount = mifareClassic.getSectorCount();
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;
}
StringBuffer buffer = new StringBuffer();
buffer.append("\n卡片类型:").append(typeS);
buffer.append("\n共").append(sectorCount).append("个扇区");
buffer.append("\n共").append(mifareClassic.getBlockCount()).append("个块");
buffer.append("\n存储空间:").append(mifareClassic.getSize()).append("B");
boolean auth = false;
for (int j = 0; j < sectorCount; j++) {
buffer.append("\nSector").append(j);
auth = mifareClassic.authenticateSectorWithKeyA(j, MifareClassic.KEY_DEFAULT);
int bCount;
int bIndex;
if (auth) {
buffer.append("验证成功");
bCount = mifareClassic.getBlockCountInSector(j);
bIndex = mifareClassic.sectorToBlock(j);
for (int i = 0; i < bCount; i++) {
byte[] data = mifareClassic.readBlock(bIndex);
buffer.append("\nBlock " + bIndex + " : " + ByteArrayToHexString(data) + "");
bIndex++;
}
} else {
buffer.append("验证失败");
}
}
return buffer.toString();
} catch (IOException e) {
Log.d(TAG, "parse", e);
return e.getMessage();
} finally {
close(mifareClassic);
}
}
}
3.MifareUltralight
import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import java.io.IOException;
public class MifareUltralightReader extends CardReader {
@Override
public String parse(Tag tag) {
MifareUltralight mifareUltralight = MifareUltralight.get(tag);
try {
mifareUltralight.connect();
StringBuffer buffer = new StringBuffer();
int type = mifareUltralight.getType();
switch (type) {
case MifareUltralight.TYPE_ULTRALIGHT:
buffer.append("TYPE_ULTRALIGHT");
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
buffer.append("TYPE_ULTRALIGHT_C");
break;
case MifareUltralight.TYPE_UNKNOWN:
buffer.append("TYPE_UNKNOWN");
break;
}
byte[] payload = mifareUltralight.readPages(0);
byte[] payload1 = mifareUltralight.readPages(4);
byte[] payload2 = mifareUltralight.readPages(8);
byte[] payload3 = mifareUltralight.readPages(12);
buffer.append("\nPage0-3:").append(ByteArrayToHexString(payload));
buffer.append("\npage4-7:").append(ByteArrayToHexString(payload1));
buffer.append("\npage8-11:").append(ByteArrayToHexString(payload2));
buffer.append("\npage12-15:").append(ByteArrayToHexString(payload3));
return buffer.toString();
} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
} finally {
close(mifareUltralight);
}
}
}
4.IsoDep
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.util.Log;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class IsoDepReader extends CardReader {
private static final String TAG = "IsoDepReader";
protected final static byte TRANS_CSU = 6;
protected final static byte TRANS_CSU_CPX = 9;
@Override
public String parse(Tag tag) {
IsoDep isoDep = IsoDep.get(tag);
try {
isoDep.connect();
StringBuffer buffer = new StringBuffer();
if (isoDep.isConnected()) {
Log.d("h_bl", "isoDep.isConnected");
byte[] DFN_PSE = {(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',};
isoDep.transceive(getSelectCommand(DFN_PSE));
byte[] DFN_SRV = {(byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x86, (byte) 0x98, (byte) 0x07, (byte) 0x01,};
isoDep.transceive(getSelectCommand(DFN_SRV));
byte[] ReadMoney = {(byte) 0x80,
(byte) 0x5C,
(byte) 0x00,
(byte) 0x02,
(byte) 0x04,
};
byte[] Money = isoDep.transceive(ReadMoney);
if (Money != null && Money.length > 4) {
int cash = byteToInt(Money, 4);
float ba = cash / 100.0f;
buffer.append("余额:" + ba);
}
byte[] ReadRecord = {(byte) 0x00,
(byte) 0xB2,
(byte) 0x01,
(byte) 0xC5,
(byte) 0x00,
};
byte[] Records = isoDep.transceive(ReadRecord);
Log.d("h_bl", "总消费记录" + Records);
ArrayList<byte[]> ret = parseRecords(Records);
List<String> retList = parseRecordsToStrings(ret);
buffer.append("\n" + "消费记录如下:");
for (String string : retList) {
Log.d("h_bl", "消费记录" + string);
buffer.append("\n" + string);
}
} else {
buffer.append("not connected");
}
return buffer.toString();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
} finally {
close(isoDep);
}
}
private byte[] getSelectCommand(byte[] aid) {
final ByteBuffer cmd_pse = ByteBuffer.allocate(aid.length + 6);
cmd_pse.put((byte) 0x00)
.put((byte) 0xA4)
.put((byte) 0x04)
.put((byte) 0x00)
.put((byte) aid.length)
.put(aid).put((byte) 0x00);
return cmd_pse.array();
}
private ArrayList<byte[]> parseRecords(byte[] Records) {
int max = Records.length / 23;
Log.d("h_bl", "消费记录有" + max + "条");
ArrayList<byte[]> ret = new ArrayList<byte[]>();
for (int i = 0; i < max; i++) {
byte[] aRecord = new byte[23];
for (int j = 23 * i, k = 0; j < 23 * (i + 1); j++, k++) {
aRecord[k] = Records[j];
}
ret.add(aRecord);
}
for (byte[] bs : ret) {
Log.d("h_bl", "消费记录有byte[]" + bs);
}
return ret;
}
private List<String> parseRecordsToStrings(ArrayList<byte[]>... Records) {
List<String> recordsList = new ArrayList<String>();
for (ArrayList<byte[]> record : Records) {
if (record == null)
continue;
for (byte[] v : record) {
}
}
return recordsList;
}
private int byteToInt(byte[] b, int n) {
int ret = 0;
for (int i = 0; i < n; i++) {
ret = ret << 8;
ret |= b[i] & 0x00FF;
}
if (ret > 100000 || ret < -100000)
ret -= 0x80000000;
return ret;
}
}
5.NfcA
import android.nfc.Tag;
import android.nfc.tech.NfcA;
import java.nio.charset.Charset;
public class NfcAReader extends CardReader {
@Override
public String parse(Tag tag) {
NfcA nfca = NfcA.get(tag);
try {
nfca.connect();
if (nfca.isConnected()) {
byte[] SELECT = {
(byte) 0x30,
(byte) 5 & 0x0ff,
};
byte[] response = nfca.transceive(SELECT);
nfca.close();
if (response != null) {
return new String(response, Charset.forName("utf-8"));
} else {
return "response is null";
}
} else {
return "not connected";
}
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}finally {
close(nfca);
}
}
}
6.NfcB
import android.nfc.Tag;
import android.nfc.tech.NfcB;
import android.widget.Toast;
import com.socsi.tools.nfccardreader.MainActivity;
import java.io.IOException;
public class NfcBReader extends CardReader {
@Override
public String parse(Tag tag) {
NfcB nfcb = NfcB.get(tag);
try {
nfcb.connect();
StringBuffer buffer = new StringBuffer();
if (nfcb.isConnected()) {
System.out.println("已连接");
byte[] applicationData = nfcb.getApplicationData();
byte[] protocolInfo = nfcb.getProtocolInfo();
buffer.append("ApplicationData:").append(ByteArrayToHexString(applicationData));
buffer.append("\nProtocolInfo:").append(ByteArrayToHexString(protocolInfo));
} else {
buffer.append("not connected");
}
return buffer.toString();
} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
} finally {
close(nfcb);
}
}
}
7.Felica
import android.nfc.Tag;
import android.nfc.tech.NfcF;
import android.util.Log;
public class NfcFReader extends CardReader {
@Override
public String parse(Tag tag) {
NfcF nfcf = NfcF.get(tag);
try {
nfcf.connect();
byte[] felicaIDm = new byte[]{0};
byte[] req = readWithoutEncryption(felicaIDm, 10);
byte[] res = nfcf.transceive(req);
return ByteArrayToHexString(res);
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}finally {
close(nfcf);
}
}
}
8.NfcV
import android.nfc.Tag;
import android.nfc.tech.NfcV;
import java.io.IOException;
import java.nio.charset.Charset;
public class NfcVReader extends CardReader {
@Override
public String parse(Tag tag) {
NfcV nfcV = NfcV.get(tag);
try {
nfcV.connect();
byte[] tagUid = tag.getId();
int blockAddress = 0;
int blocknum = 4;
byte[] cmd = new byte[]{
(byte) 0x22,
(byte) 0x23,
0, 0, 0, 0, 0, 0, 0, 0,
(byte) (blockAddress & 0x0ff), (byte) (blocknum - 1 & 0x0ff)
};
System.arraycopy(tagUid, 0, cmd, 2, tagUid.length);
byte[] response = nfcV.transceive(cmd);
if (response != null) {
return new String(response, Charset.forName("utf-8"));
} else {
return "respones is null";
}
} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
} finally {
close(nfcV);
}
}
}
9.NfcBarcode
import android.nfc.Tag;
import android.nfc.tech.NfcBarcode;
public class NfcBarcodeReader extends CardReader {
@Override
public String parse(Tag tag) {
NfcBarcode barcode = NfcBarcode.get(tag);
try {
barcode.connect();
byte[] bytes = barcode.getBarcode();
return ByteArrayToHexString(bytes);
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
} finally {
close(barcode);
}
}
}
主要的NFC类就这些,代码仅测试使用,如有错误请指正,谢谢!
|