android - 读取 Mifare Classic 返回奇怪的字符

标签 android format nfc mifare contactless-smartcard

当使用 Android 读取 MIFARE 卡并将数据转换为 UTF-8 时,我会收到类似 � 的奇怪字符。 我正在尝试构建一个可以读取我们正在使用的某种身份证的应用程序。现在的问题是我在单词之间得到奇怪的字符,并且一些单词在 block 之间分开,所以我怎样才能安全地得到我正在寻找的单词? 例如我的读数是这样的:

43224...19032019... 在 block 2 sektor 2 bindex :8

并且以 19 开头的其余数字在新 block 中进行拆分:

我的名字����M����19

在 block 1 sektor 1 bindex :4

930402......NO934951

在 block 2 sektor 1 bindex :4

c5 42 4e 49 44 00 07 4f 4f 4f 4f 4f 4f 00 4b 42   "Åbnid" "OOOOOO" "KB"
44 44 44 20 44 44 44 44 44 00 82 4d 00 c9 31 39   "DDD DDDDD" "M" "19"
39 34 34 33 34 32 00 d0 4e 4f 39 36 36 36 35 31   "944342" "NO966651"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00
30 32 32 20 20 41 53 00 d3 54 4f 54 41 4c 20 4b   "022" "AS" "Total k"
4f 4e 54 52 4f 4c 4c 20 41 53 20 00 c9 30 32 38   "ONTROLL AS" "028"
37 30 34 33 33 00 c9 32 30 32 31 30 32 31 31 00   "70433" "20210211"
00 00 00 00 00 00 70 f7 88 00 00 00 00 00 00 00

This is how I read from the card:

Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
MifareClassic mfc = MifareClassic.get(tagFromIntent);

这是我用于在 for 循环中读取的代码:

 data = mfc.readBlock(bIndex + block); 

然后为了将数据转换为 UTF8 以进行打印,我使用:

   public String convertByteArrayToUTF8(byte[] bytes){
    String encoded = null;
    try {
        encoded = new String(bytes, StandardCharsets.UTF_8);
    }
    catch (Exception e){
        encoded = new String(bytes, Charset.defaultCharset());
    }
    return encoded;
}

我尝试过使用 ASCII、UTF-16 等,但没有成功。

最佳答案

首先对问题标题大声笑。当我是新手时,我处于同样的情况。没有在线教程可以为您提供从 Mifare 经典卡读取数据的确切代码。

先了解一下Mifare卡的内存结构。

Mifare Classic的内存分为扇区,扇区也分为16字节的 block 。

MIFARE Classic 1K 卡有 16 个扇区,每个扇区分为四个 block 。如果我们进行数学计算,我们可以算出内存结构是怎样的:16 字节(1 block )* 4 block * 16 扇区 = 1024 字节。

enter image description here

MIFARE Classic 4K 卡有 40 个扇区,其中 32 个扇区分为 4 个 block ,其余 8 个扇区分为 16 个 block 。 16字节(1 block )*4 block *32扇区+16字节(1 block )*16 block *8扇区=4096字节。内存结构如下:

enter image description here

方 block 上的数字表示其索引。每个扇区都由写在扇区最后一个 block 中的站点 key 保护。例如, block 3 包含扇区 1 的站点 key , block 7 包含扇区 2 的站点 key 。每个扇区中的最后一个 block 还包含访问条件信息,例如“写入”、“读取”和“读写”。下图演示了最后一个 block 是如何组成的:

enter image description here

此外,写入卡中的数据是二进制的,即; 0 和 1。

现在,读取数据需要遵循的步骤是:

第一步:检查设备是否支持NFC。

step2:检查设备是否有NXP芯片(尤其是读取Mifare classic卡)。

step3: 实例化NFC manager和NFC adpater & 定义你想要读取的卡的techlist。

第 4 步:请求访问设备 NFC 的权限。

step5:创建一个检测卡片的intent,指定要读取的MIME类型(大多数情况下都是MIME类型)。

step6: 在 onResume() 和 onPause() 中启用和禁用适配器的前台调度,以便您的应用程序在您的 Activity 处于前台时优先读取卡片。

step7:当卡片接触到设备时,您可以从intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

获取标签信息

step8:读取卡片信息即;卡片类型、技术列表等。

step9:要读取卡片中的数据,需要通过上面获取到的标签信息连接卡片。

step10:遍历所有扇区。使用默认 key 验证每个扇区 //https://developer.android.com/reference/android/nfc/tech/MifareClassic.html#authenticateSectorWithKeyA(int,%20byte[])

step11:认证成功后,读取每个扇区 block 中的二进制数据。

step12:将二进制数据转换为字符串数据,以便我们读取。

step13:到此为止,对数据做任何你想做的事情。

惊喜!在我的 github 存储库中获取完整的工作代码: https://github.com/codes29/RFIDReader

注意:我理解你作为新手的感受,并在没有适当教程的情况下完成了这项任务。因此,经过几天的努力,我更新了我编写的代码。

这是在成功验证并读取数据后您将获得的样本。我扫描的卡现在是空的。但如果这里有数据,那么它肯定会在这里而不是 0。

/tmp/mozilla_mobulous0/Screenshot_20190221-124444.png

干杯!兄弟,祝你编程愉快!

关于android - 读取 Mifare Classic 返回奇怪的字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54782247/

相关文章:

flutter - Flutter应用程序中是否可以从nfc芯片读取护照数据?

android - 如何在 SeekBar 拇指中间添加 TextView?

php - python 格式日期时间与 "st", "nd", "rd", "th"(英文序数后缀),如 PHP 的 "S"

java - NFC (Android Studio) - 如何通过单击按钮启用/禁用 NFC

c++ - 如何使用 std::ostringstream 截断整型的宽度?

java - java中具体的字符串格式

android - processCommandApdu 方法中 HostApduService 的问题

android - 句子或问题的正则表达式

android - 未安装的应用程序包似乎已损坏

android - 如何在布局中设置 ListView