我想在我的应用程序中使用NFC读取,在那里我读取NFC卡的ID。我有两种不同的NFC卡。当我用我电脑中的USB NFC阅读器读取它们时,我得到了两张卡的9位数字,这很酷。我可以根据这个数字来识别卡片。
当我想要在我的应用程序中阅读它们时,问题就发生了,就像这样:
new NfcAdapter.ReaderCallback() {
@Override
public void onTagDiscovered( final Tag tag ) {
runOnUiThread(new Runnable() {
@Override
public void run() {
System.out.println(tag.toString());
// I get the ID here to identify the card
String id = Long.toString(Utils.toDec(tag.getId())).trim();
}
});
}
},
1 | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
options);当我记录所发现的标签的toString()方法时,我得到了第一张卡的如下信息:
Tech [android.nfc.tech.NfcA, android.nfc.tech.MifareClassic]当我读取String id = Long.toString(Utils.toDec(tag.getId())).trim();下面的ID时,我得到了与我的计算机中相同的9位数字,这太棒了,它是卡的唯一id。
第二张卡的toString()
Tech [android.nfc.tech.IsoDep, android.nfc.tech.NfcA]当我读取标签ID时,我得到的是17位数字,而不是9位数字...我试着在发现的标签中记录所有的东西,但是我找不到我可以通过USB阅读器从计算机的卡中读取的9位数字。所以我无法识别这张NFC卡。
我该如何解决这个问题呢?我想通过USB阅读器和我的应用程序识别卡,所以2个数字必须相同,就像第一张卡一样…
谢谢!:)
发布于 2020-10-23 21:54:12
因此,根据该卡的数据表https://www.nxp.com/docs/en/data-sheet/MF3DX2_MF3DHX2_SDS.pdf的7.4节(以及亚马逊列表),该卡的UID是一个7字节的UID。
因此,它不是一种为了兼容而具有多个ID的卡,但它所使用的标准确实允许4,7,10字节的UID,请参阅http://emutag.com/iso/14443-3.pdf标准的第19页
根据ISO 1444-3标准,较大的UID被分成多个部分发送,数据表
根据ISO/IEC 14443-3的
在第一防冲突循环期间,级联标签向UID2和BCC返回88h的值以及UID、UID0的前3个字节。第二个防冲突循环将字节UID3返回给UID6和BCC
在应用笔记https://www.nxp.com/docs/en/application-note/AN10927.pdf中解释了该过程和问题
因此,在应用笔记3.2部分
在某些情况下,阅读器基础设施可能能够处理双倍大小的UID,但(后台)系统只能处理4字节的UID。反之亦然,读取器基础设施可能无法处理双倍大小的UID,但(后台)系统需要唯一性,并且可以处理双倍大小的UID。
因此,USB读取器和运行它的代码可能执行了错误的防冲突,因为它无法处理它返回的4Byte UID以外的内容,它可能不会响应卡返回的数据并处理级联标记位(因此它实际上可能只返回7字节UID的前3个字节。
您没有提供所使用的USB读卡器的详细信息(制造商和型号),也没有提供用于读取它的源代码或应用程序的详细信息,因此无法查看它是否可以返回正确大小的UID。
但应用笔记附录6给出了将7字节UID转换为4字节UID的代码(不幸的是,这不是用C编写的,但您应该能够将其转换为Java ),但USB读取器可能也会返回正确的4字节UID,因此这可能没有帮助。
此外,为了更好地进行诊断,将值打印为十六进制而不是十进制,因为这样可以更好地告诉您发生了什么。
添加了
一种将字节数组转换为可打印十六进制字符串https://stackoverflow.com/a/332101/2373819的方法
此外,如果您提供了来自卡的实际UID值的更多信息,则可能会看到USB读取器是如何出错的(即UID 88h的第一个字节?)
更新说明其他卡很容易看到,这是一个Mifare经典,像EV1这样的新版本也有一个7字节的UID (非常旧的型号有一个4字节的UID),所以也应该显示更大的十进制的UID (如果是像EV1版本的现代卡),但这也有一个4字节的UID作为前4个字节的7个字节,以兼容较老的版本。
因为您正在使用通用的Tag Technology类型读取UID,所以它可能会将其截断为4个字节,或者它可能是一个旧版本。在使用getID之前,尝试在正确的特定类中获取标记。
MifareClassic mMifareClassic = MifareClassic.get(tag);
byte[] uid = mMifareClassic.getID();您可以使用switch tag.getTechList();为每种类型的标记使用正确的标记技术类
或者尝试读取Block 0以直接获取UID。
摘要
问题是,当卡只有恩智浦Mifare Desfire卡的7字节UID时,USB读卡器给出的似乎是4字节的UID。
在MifareClassic卡上,它应该是7字节UID的前4个字节,因为这是较新的7字节UID卡被设计为与旧的4字节UID卡兼容,因此您可以取阵列的一部分来使它们匹配。
在恩智浦Mifare Desfire卡上
A)第一个防冲突命令中的4个字节?(这将包括级联标签88h值)
B) 7字节UID的前4个字节?所以再一次,你可以取一片来使它们匹配。
备注
这些值的某些表示首先给出最高有效位,而不是最低有效位。
例如,从您的注释中可以看出,其中一个长UID是十进制的36125410196403972,也就是十六进制的8057DE821F3704,但是数据手册中说最低有效字节应该是04,表示恩智浦是制造商,但正如您在8057DE821F37中看到的那样,04颠倒了过来,最高有效位在前,最低有效位在后。
因此,您可以尝试并尝试只取前4个字节的组合,看看是否能使它们全部匹配。
或者让USB读卡器为两张卡读取正确的完整7字节UID (因为仅使用4字节并不能保证唯一性(即使是7字节UID或任何大小的UID也不能用于唯一性和安全性,因为它们太容易被伪造)。
https://stackoverflow.com/questions/64497556
复制相似问题