我正在使用Android Cilico F750,专用的RFID阅读器是CF-RS103。 RFID标签类型为MIFARE Ultralight类型C。
使用专用读卡器进行读取时,标签的ID为:2054270212(10位数字)。
但是,使用Android手机读取时,id为:36113912876727556(17位数字),而反向ID为:1316602805183616(16位数字)。
有人知道为什么会这样吗,以及是否有可能将10位ID转换为17位ID,反之亦然。
我使用意图来检测标签并解决意图,我使用了这个:
public void resolveIntent(Intent intent){
String action = intent.getAction();
if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
||NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
||NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))
{
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] msgs;
if(rawMsgs!=null)
{
msgs= new NdefMessage[rawMsgs.length];
for(int i=0; i<rawMsgs.length; i++)
{
msgs[i]=(NdefMessage) rawMsgs[i];
}
}
else
{
byte[] empty = new byte[0];
byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] payload = dumpTagData(tag).getBytes();
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,id,payload);
NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
msgs= new NdefMessage[] {msg};
}
displayMsgs(msgs);
}}
这是我的助手功能:
private void displayMsgs(NdefMessage[] msgs)
{
if(msgs==null || msgs.length==0) {
return;
}
StringBuilder builder = new StringBuilder();
List<ParsedNdefRecord> records= NdefMessageParser.parse(msgs[0]);
final int size = records.size();
for(int i=0;i<size;i++)
{
ParsedNdefRecord record = records.get(i);
String str = record.str();
builder.append(str).append("\n");
}
text.setText(builder.toString());
}
private String dumpTagData(Tag tag) {
StringBuilder sb = new StringBuilder();
byte[] id = tag.getId();
sb.append("ID (hex): ").append(toHex(id)).append('\n');
sb.append("ID (reversed hex):").append(toReversedHex(id)).append('\n');
sb.append("ID (dec): ").append(toDec(id)).append('\n');
sb.append("ID (reversed dec):").append(toReversedDec(id)).append('\n');
String prefix = "android.nfc.tech.";
sb.append("Technologies: ");
for (String tech: tag.getTechList()) {
sb.append(tech.substring(prefix.length()));
sb.append(", ");
}
sb.delete(sb.length() - 2, sb.length());
for (String tech: tag.getTechList()) {
if (tech.equals(MifareClassic.class.getName())) {
sb.append('\n');
String type = "Unknown";
try {
MifareClassic mifareTag = MifareClassic.get(tag);
switch (mifareTag.getType()) {
case MifareClassic.TYPE_CLASSIC:
type = "Classic";
break;
case MifareClassic.TYPE_PLUS:
type = "Plus";
break;
case MifareClassic.TYPE_PRO:
type = "Pro";
break;
}
sb.append("Mifare Classic type: ");
sb.append(type);
sb.append('\n');
sb.append("Mifare size: ");
sb.append(mifareTag.getSize() + " bytes");
sb.append('\n');
sb.append("Mifare sectors: ");
sb.append(mifareTag.getSectorCount());
sb.append('\n');
sb.append("Mifare blocks: ");
sb.append(mifareTag.getBlockCount());
} catch (Exception e) {
sb.append("Mifare classic error: " + e.getMessage());
}
}
if (tech.equals(MifareUltralight.class.getName())) {
sb.append('\n');
MifareUltralight mifareUlTag = MifareUltralight.get(tag);
String type = "Unknown";
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
type = "Ultralight";
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
type = "Ultralight C";
break;
}
sb.append("Mifare Ultralight type: ");
sb.append(type);
}
}
return sb.toString();
}
private String toHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = bytes.length - 1; i >= 0; --i) {
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
if (i > 0) {
sb.append(" ");
}
}
return sb.toString();
}
private String toReversedHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; ++i) {
if (i > 0) {
sb.append(" ");
}
int b = bytes[i] & 0xff;
if (b < 0x10)
sb.append('0');
sb.append(Integer.toHexString(b));
}
return sb.toString();
}
private long toDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = 0; i < bytes.length; ++i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}
private long toReversedDec(byte[] bytes) {
long result = 0;
long factor = 1;
for (int i = bytes.length - 1; i >= 0; --i) {
long value = bytes[i] & 0xffl;
result += value * factor;
factor *= 256l;
}
return result;
}`
编辑:我设法通过将7字节的十六进制ID截断为4字节来解决此问题。 如果十进制ID的总长度小于10位,则使用以下语句对十进制ID进行格式化:如果DEC ID小于10位,则基本上从左侧添加零:
String strFinal=String.format("%010d", Long.parseLong(str));
这份描述ID如何从HEX8转换为DEC10的文档也对我有很大帮助:https://www.batag.com/download/rfidreader/LF/RAD-A200-R00-125kHz.8H10D.EM.V1.1.pdf
非常感谢@Andrew和@Karam帮助我解决了这个问题!
答案 0 :(得分:0)
我不知道您为什么总是尝试始终转换为十进制? 并且请尝试说明有关用于读取UID的代码的更多信息。
关于您的电话号码,并将17位数字转换为10位数字;我将它们都转换为十六进制:
36139312876727556(17位数)以十六进制表示:8064837A71AD04。
2054270212(10位数),以十六进制表示:7A71AD04
您会注意到,您只需修剪前三个字节即可获得10位数字。
而且我确实相信他们都不是UID。但正如Andrew所说的7字节,您已经在您的照片中阅读了它:(04:B5:71:7A:83:64:80)
答案 1 :(得分:0)
所以我认为答案是,因为您将7字节ID转换为十进制,所以由于转换为十进制,所以得到的数字长度是可变的。
“字节数据类型是一个8位带符号的二进制补码整数。最小值为-128,最大值为127(包括127)。”
来自https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
可以生成一个具有1,2或3个字符的十进制数字,因此id的长度可以不同。
从理论上讲,转换也应该出现负数,这似乎也出错了。
如果您希望它可以被人类阅读,则最好将其作为十六进制字符串处理。
Java中将ID的2页转换为十六进制的正确方法是
StringBuilder Uid;
for (int i = 0; i < result.length; i++) {
// byte 4 is a check byte
if (i == 3) continue;
Uid.append(String.format("%02X ", result[i]));
}
根据卡https://www.nxp.com/docs/en/data-sheet/MF0ICU2_SDS.pdf的规格表进行注释(第7.3.1节)
有一个校验字节是ID的一部分,尽管在同一张卡上它始终是相同的,并且仍然会为您提供唯一的ID,但从技术上讲,它不是ID的一部分。
或者如果阅读水平不高
https://developer.android.com/reference/android/nfc/Tag#getId()
将为您获取ID。
请注意,“ 36139312876727556(17digit)和反向ID”在转换为十六进制并反向实际时为7个字节,并以正确的数字开头。
10位数字看起来像7字节数字的前4个字节也被反转了。
答案 2 :(得分:0)
PC上的读卡器配置错误,默认情况下,将其配置为当卡具有7字节ID时将ID显示为10位十进制数字(4字节)。
因此,它必须丢失一些数据,它是通过将ID截断为7字节ID的前4
个字节来实现的
使用PC上的软件将输出格式更改为适合Mifare Ultralight C卡(8 Hex?)上的ID大小
或
请改用Mifare Classic卡,因为它们的ID为4字节
或
将7个字节的ID截断为4个字节,例如将代码中的bytes.length
更改为4
(硬编码为7字节ID中的前4个字节),并处理以下事实:存在大量(大约1670万)的Mifare Ultralight C看起来与您要显示的ID相同的卡片
这是因为规格是卖家在亚马逊https://www.amazon.co.uk/Chafon-CF-RS103-Multiple-Support-Compatible-Black/dp/B017VXVZ66上提供的(我无法在制造商的网站上找到任何详细信息)
它说:“默认输出10位十进制,通过软件控制输出格式。”
“支持Windows,Linux和android系统,但只能在Windows pc中设置输出格式。无需编程和软件,只需即插即用。”
唯一明智的答案是移动所有内容以使用7字节ID。