有谁知道我如何通过Android NFC API找出我正在读取的标签中使用了哪种NFC芯片?理想情况下,我希望同时获得芯片型号和制造商。
标签对象中的某处可用吗?
为了澄清起见,我不是指电话中的读取器芯片,而是指NFC标签中的芯片。
最佳答案
我正在Android中开发用于NFC读/写/身份验证操作的应用程序。这是您想要的一些代码部分。
Android有3种主要的卡片类型,分别是Mifare Classic,Mifare Ultralight和Isodep(这是Desfire和Desfire EV1的类型)。因此,当我触摸到标签时,我将运行以下操作:
private String[] getTagInfo(Intent intent) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String prefix = "android.nfc.tech.";
String[] info = new String[2];
// UID
byte[] uid = tag.getId();
info[0] = "UID In Hex: " + Utils.convertByteArrayToHexString(uid) + "\n" +
"UID In Dec: " + Utils.convertByteArrayToDecimal(uid) + "\n\n";
// Tech List
String[] techList = tag.getTechList();
String techListConcat = "Technologies: ";
for(int i = 0; i < techList.length; i++) {
techListConcat += techList[i].substring(prefix.length()) + ",";
}
info[0] += techListConcat.substring(0, techListConcat.length() - 1) + "\n\n";
// Mifare Classic/UltraLight Info
info[0] += "Card Type: ";
String type = "Unknown";
for(int i = 0; i < techList.length; i++) {
if(techList[i].equals(MifareClassic.class.getName())) {
info[1] = "Mifare Classic";
MifareClassic mifareClassicTag = MifareClassic.get(tag);
// Type Info
switch (mifareClassicTag.getType()) {
case MifareClassic.TYPE_CLASSIC:
type = "Classic";
break;
case MifareClassic.TYPE_PLUS:
type = "Plus";
break;
case MifareClassic.TYPE_PRO:
type = "Pro";
break;
}
info[0] += "Mifare " + type + "\n";
// Size Info
info[0] += "Size: " + mifareClassicTag.getSize() + " bytes \n" +
"Sector Count: " + mifareClassicTag.getSectorCount() + "\n" +
"Block Count: " + mifareClassicTag.getBlockCount() + "\n";
} else if(techList[i].equals(MifareUltralight.class.getName())) {
info[1] = "Mifare UltraLight";
MifareUltralight mifareUlTag = MifareUltralight.get(tag);
// Type Info
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
type = "Ultralight";
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
type = "Ultralight C";
break;
}
info[0] += "Mifare " + type + "\n";
} else if(techList[i].equals(IsoDep.class.getName())) {
info[1] = "IsoDep";
IsoDep isoDepTag = IsoDep.get(tag);
info[0] += "IsoDep \n";
} else if(techList[i].equals(Ndef.class.getName())) {
Ndef ndefTag = Ndef.get(tag);
info[0] += "Is Writable: " + ndefTag.isWritable() + "\n" +
"Can Make ReadOnly: " + ndefTag.canMakeReadOnly() + "\n";
} else if(techList[i].equals(NdefFormatable.class.getName())) {
NdefFormatable ndefFormatableTag = NdefFormatable.get(tag);
}
}
return info;
}
但是,这并不能直接获得Desfire和Desfire EV1的类型。为此,您需要向卡发送一些字节:
static final byte GET_MANUFACTURING_DATA = (byte) 0x60;
public DesfireManufacturingData getManufacturingData() throws Exception {
byte[] respBuffer = sendRequest(GET_MANUFACTURING_DATA);
if (respBuffer.length != 28)
throw new Exception("Invalid response");
return new DesfireManufacturingData(respBuffer);
}
private byte[] sendRequest (byte command) throws Exception {
return sendRequest(command, null);
}
private byte[] sendRequest (byte command, byte[] parameters) throws Exception {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] recvBuffer = mTagTech.transceive(Utils.wrapMessage(command, parameters));
while (true) {
if (recvBuffer[recvBuffer.length - 2] != (byte) 0x91)
throw new Exception("Invalid response");
output.write(recvBuffer, 0, recvBuffer.length - 2);
byte status = recvBuffer[recvBuffer.length - 1];
if (status == OPERATION_OK) {
break;
} else if (status == ADDITIONAL_FRAME) {
recvBuffer = mTagTech.transceive(Utils.wrapMessage(GET_ADDITIONAL_FRAME, null));
} else if (status == PERMISSION_DENIED) {
throw new Exception("Permission denied");
}else if (status == LENGTH_ERROR) {
throw new Exception("Length Error");
}
else if (status == AUTHENTICATION_ERROR) {
throw new Exception("Authentication error");
}else if (status == PARAMETER_ERROR) {
throw new Exception("Parameter Error");
}else if (status == DUPLICATE_ERROR) {
throw new Exception("Duplicate Error");
}else if (status == NO_SUCH_KEY) {
throw new Exception("No such key");
}else {
throw new Exception("Unknown status code: " + Integer.toHexString(status & 0xFF));
}
}
return output.toByteArray();
}
初始化制造数据后,您可以轻松获取其零件。 DesfireManufacturingData类用于评估标记对有意义部分的响应,但我仅给出其链接:Desfire Manufacturing Data。另外,我必须说这是我在Internet上使用开放源代码找到的最全面的项目,但是它仅具有Desfire标签的读取操作,而没有写入和认证的操作。希望这可以帮助!