标签错误地列举为MIFARE经典,SAK = 32
我有一个Sony Xperia Z3。我正在使用它与MIFARE Classic智能卡进行交互。标签错误地列举为MIFARE经典,SAK = 32
当使用原生MIFARE卡时,我可以正确读取卡。
但是,如果我使用的是仿真的MIFARE Classic,我得到的SAK不正确。在0x38代替我使用MifareClassic.get(tag)
java.lang.RuntimeException: Tag incorrectly enumerated as MIFARE Classic, SAK = 32
时,我不知道为什么我的手机是不正确的的SAK得到为0x20(32)和下面的错误。
同样的卡正确读取支持MIFARE作为Nexus S的其他设备等
任何想法,为什么这个异常?
TA
SAK值不是您可以用来区分不同NFC标签的魔术值。相反,它有点掩盖价值,它定义了RF协议的一些功能。
不幸的是,谷歌的Android代码使用SAK对Mifare卡识别,你可以在这个代码在这里看到:MifareClassic.java
在你的Xperia Z3会发生什么事是可能的是,NFC控制器和NFC堆栈正确检测到标签为Mifare兼容并报告。一旦你尝试使用标签,你会遇到你提到的问题。
Nexus S可能运行MifareClassic.java代码的固定版本并避免该问题。
你能做些什么:从应用的角度来看,没有什么是真的。这是Android操作系统中的一个错误。如果你有root用户访问权限,你可以很难做到,并且即时修补成员函数。
尝试调用MifareClassic.get(tag)
欲了解更多信息之前,使用这个补丁为tag = cleanupTag(tag)
读MifareClassicTool Sony Z3 issue
private Tag cleanupTag(Tag oTag){
if (oTag == null)
return null;
String[] sTechList = oTag.getTechList();
Parcel oParcel = Parcel.obtain();
oTag.writeToParcel(oParcel, 0);
oParcel.setDataPosition(0);
int len = oParcel.readInt();
byte[] id = null;
if (len >= 0) {
id = new byte[len];
oParcel.readByteArray(id);
}
int[] oTechList = new int[oParcel.readInt()];
oParcel.readIntArray(oTechList);
Bundle[] oTechExtras = oParcel.createTypedArray(Bundle.CREATOR);
int serviceHandle = oParcel.readInt();
int isMock = oParcel.readInt();
IBinder tagService;
if (isMock == 0) {
tagService = oParcel.readStrongBinder();
} else {
tagService = null;
}
oParcel.recycle();
int nfca_idx = -1;
int mc_idx = -1;
short oSak = 0;
short nSak = 0;
for (int idx = 0; idx < sTechList.length; idx++) {
if (sTechList[idx].equals(NfcA.class.getName())) {
if (nfca_idx == -1) {
nfca_idx = idx;
if (oTechExtras[idx] != null
&& oTechExtras[idx].containsKey("sak")) {
oSak = oTechExtras[idx].getShort("sak");
nSak = oSak;
}
} else {
if (oTechExtras[idx] != null
&& oTechExtras[idx].containsKey("sak")) {
nSak = (short) (nSak | oTechExtras[idx].getShort("sak"));
}
}
} else if (sTechList[idx].equals(MifareClassic.class.getName())) {
mc_idx = idx;
}
}
boolean modified = false;
if (oSak != nSak) {
oTechExtras[nfca_idx].putShort("sak", nSak);
modified = true;
}
if (nfca_idx != -1 && mc_idx != -1 && oTechExtras[mc_idx] == null) {
oTechExtras[mc_idx] = oTechExtras[nfca_idx];
modified = true;
}
if (!modified) {
return oTag;
}
Parcel nParcel = Parcel.obtain();
nParcel.writeInt(id.length);
nParcel.writeByteArray(id);
nParcel.writeInt(oTechList.length);
nParcel.writeIntArray(oTechList);
nParcel.writeTypedArray(oTechExtras, 0);
nParcel.writeInt(serviceHandle);
nParcel.writeInt(isMock);
if (isMock == 0) {
nParcel.writeStrongBinder(tagService);
}
nParcel.setDataPosition(0);
Tag nTag = Tag.CREATOR.createFromParcel(nParcel);
nParcel.recycle();
return nTag;
}
谢谢。标签被检测到并且SAK是正确的。但问题是,当我们尝试从Mifare卡中读取内存时,我们发现标签丢失的例外。任何想法? – jlanza
的SAK可以帮助你知道什么类型的协议都可以用卡来使用。这里的事实是,Z3是我测试过的返回SAK值(0x20)的唯一移动设备。实际上SAK是由卡片响应Select命令而生成的,因此每个移动设备/芯片组应返回相同的值。为什么Z3上的芯片正在以另一种方式做它?这是问题;) – jlanza