有谁知道我如何通过 Android NFC API 找出我正在阅读的标签中使用了哪个 NFC 芯片?理想情况下,我喜欢同时获得芯片型号和制造商。
在 Tag 对象的某处可用吗?
为澄清起见,我不是指手机中的读取器芯片,而是 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。另外,我必须说这是我在互联网上找到的最全能的开源项目,但它只有对 Desfire 标签的读取操作,没有写入和验证。希望这可以帮助!
如果您有带 NFC 的 Android 设备,则有各种可用的应用程序可以做到这一点(以及更多),例如NXP TagInfo或NFC TagInfo。
对于带有桌面阅读器的 PC,也许RFIDIOt可能有用。对于其他平台,可能存在(或可以创建)类似的应用程序,但我不熟悉它们。