![](/img/trans.png)
[英]In android studio, how to prevent errors with buffered reader reading from a url, when the phone has no internet
[英]Why when reading NFCtag with Android phone you get different tag ID then when reading with dedicated reader?
我使用的是 Android Cilico F750,專用 RFID 閱讀器是 CF-RS103。 RFID 標簽類型為 MIFARE Ultralight type C。
用專用讀卡器讀取時,標簽id為:2054270212(10位)。
但是當用 Android 手機讀取時,id 是:36139312876727556(17digit),反向 id 是:1316602805183616(16digit)。
有誰知道為什么會發生這種情況,以及是否可以將 10digit id 轉換為 17digit 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 字節來解決這個問題。 然后如果總長度小於 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 幫助我解決了這個問題!
我不知道你為什么總是試圖轉換為十進制? 請嘗試解釋更多有關您用於讀取 UID 的代碼的信息。
關於您的數字並將 17 位數字轉換為 10 位數字; 我將它們都轉換為十六進制:
36139312876727556(17 位)十六進制:8064837A71AD04。
2054270212(10 位)十六進制:7A71AD04
正如您所注意到的,您只需 tim 前三個字節即可獲得 10 位數字。
我相信他們兩個都不是 UID。 但是安德魯所說的 7 字節,你已經在你的照片中讀到了:(04:B5:71:7A:83:64:80)
所以我認為答案是,因為您將 7 字節 ID 轉換為十進制,所以由於轉換為十進制,您將獲得可變長度的數字。
“字節數據類型是一個 8 位有符號二進制補碼整數。它的最小值為 -128,最大值為 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()
會給你身份證。
請注意,“36139312876727556(17digit) and reversed id”在轉換為十六進制和反向實際時為 7 個字節,並以正確的數字開頭。
10 位數字看起來就像 7 字節數字的前 4 個字節也顛倒了。
PC上的讀卡器配置錯誤,當卡有7字節ID時,默認將ID顯示為10位十進制數(4字節)。
因此它必須丟失一些數據,它是通過將 ID 截斷為 7 字節 ID 的前4
個字節來實現的
使用 PC 上的軟件將輸出格式更改為適合 Mifare Ultralight C 卡(8 Hex?)上的 ID 大小的格式。
或者
改用 Mifare Classic 卡,因為這些卡有 4 字節 ID
或者
將代碼中的 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 pcs中設置輸出格式。無需編程和軟件,即插即用。”
唯一明智的答案是移動一切以使用 7 字節 ID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.