android - 阅读 Mifare Classic 会返回奇怪的字符
问题描述
在使用 Android 读取 MIFARE 卡并将数据转换为 UTF-8 时,我会得到奇怪的字符,例如 �。我正在尝试构建一个可以读取我们正在使用的某种身份证的应用程序。现在的问题是我在单词之间得到了奇怪的字符,并且一些单词在块之间被分割了,所以我怎样才能安全地得到我正在寻找的单词?例如,我的读数是这样的:
43224���19032019�� 在区块 2 sektor 2 bindex :8
并拆分以 19 开头的其余数字在一个新块中:
�我的名字����M����19
在第 1 区块 sektor 1 bindex :4
930402……NO934951
在第 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” “总 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
这就是我从卡中读取的方式:
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 字节的块。
MIFARE Classic 1K 卡有 16 个扇区,每个扇区分为四个块。如果我们进行数学计算,我们可以计算出内存结构是怎样的:16 字节(1 块)* 4 块 * 16 扇区 = 1024 字节。
MIFARE Classic 4K卡有40个扇区,其中32个分为4个区块,其余8个分为16个区块。16 字节(1 块)* 4 块 * 32 扇区 + 16 字节(1 块)* 16 块 * 8 扇区 = 4096 字节。内存结构如下:
块上的数字表示它的索引。每个扇区都受到扇区最后一个块中写入的站点密钥的保护。例如,块 3 包含扇区 1 的站点密钥,块 7 包含扇区 2。每个扇区的最后一个块还包含访问条件信息,例如“写入”、“读取”和“读写”。下图演示了最后一个块的组成:
而且,卡中写入的数据是二进制的,即;0 & 1。
现在,您需要按照以下步骤读取数据:
step1:检查设备是否支持NFC。
step2:检查设备是否有NXP芯片(尤其是读取Mifare经典卡)。
第三步:实例化 NFC 管理器和 NFC 适配器并定义您要读取的卡的技术列表。
step4:请求访问设备NFC的权限。
step5:创建一个检测卡的意图并指定您要读取的MIME类型(在大多数情况下它是所有MIME类型)。
step6:在 onResume() 和 onPause() 中启用和禁用适配器的前台调度,以便您的应用程序在您的活动处于前台时获得读取卡的优先级。
step7:当卡与设备接触时,您可以从以下位置获取标签信息intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
step8:读取卡信息ie;卡类型,技术列表等。
step9:要读取卡中的数据,您需要通过上面检索到的标签信息连接到卡。
step10:遍历所有扇区。使用默认密钥验证每个扇区 // https://developer.android.com/reference/android/nfc/tech/MifareClassic.html#authenticateSectorWithKeyA(int,%20byte[])
step11:认证成功后读取每个扇区块中的二进制数据。
step12:将二进制数据转换为字符串数据,以便我们读取。
step13:就是这样,对数据做任何你想做的事情。
惊喜!在我的 github 存储库中获取完整的工作代码: https ://github.com/codes29/RFIDReader
注意:我很同情您作为新手的感受,并在没有合适教程的情况下完成了这项任务。因此,我更新了经过几天努力编写的代码。
这是成功验证并读取数据后您将获得的示例。我扫描的卡现在是空的。但是如果这里有数据,那么它肯定会在这里而不是 0。
干杯! 快乐的编码兄弟!
推荐阅读
- android - 在 Google Play 控制台上更新应用时出现错误
- substrate - 如何检查“墨水”的“储值”!在最新的“Polkadot/Substrate Portal”中
- android - ARCore Baisc 应用程序崩溃
- cassandra - 为高速查询构建 Cassandra 表
- go - 来自自定义导出器的 Prometheus 指标显示在 /metrics 中,但不在 /graph (k8s) 中
- mysql - ERROR 3680 (HY000): 无法使用 MySQL 创建数据库方法创建架构目录
- python - 检索频道 discord.py 中的成员列表 rewrite
- validation - 颤振我得到未处理的异常,方法验证不能调用 null
- c# - C# - 字典 - 如何在字典中获取特定类值的最大值?
- javascript - 哪个孩子拥有最多的糖果算法问题