You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android设备下如何获取读卡器连接的多张卡片名称

如何在Android上获取读卡器中多张卡片的名称

嘿,这个问题我之前帮不少开发者处理过——核心是得通过APDU指令序列主动和读卡器交互,毕竟大多数支持多卡片的读卡器不会主动推送所有卡片信息,得你一步步去问它。以下是具体的实现思路和步骤:

1. 先让读卡器告诉你有几张卡片

首先你得枚举读卡器内的所有卡片,这一步要发送读卡器对应的枚举指令。不同厂商的读卡器指令可能略有差异,但大部分兼容PC/SC标准的读卡器,你可以试试这些操作:

  • 先发送初始化指令:00 A4 04 00 08 A0 00 00 00 03 00 00 00,让读卡器进入可交互状态
  • 再发送卡片数量查询指令:FF 00 48 00 00,读卡器会返回响应,你从中解析出当前连接的卡片数量

如果你的读卡器是自定义指令集,一定要参考厂商提供的开发文档,别硬套标准指令哦。

2. 逐个选中卡片,建立专属通信

拿到卡片数量后,你需要逐个选中每张卡片——只有选中特定卡片后,后续的指令才会作用于它。选中卡片的核心是用卡片的UID(唯一标识)来指定目标,比如标准的选中指令格式是:00 A4 00 00 [UID长度字节] [UID的字节数组]。

举个例子,如果某张卡片的UID是12 34 56 78,那选中指令就是00 A4 00 00 04 12 34 56 78。发送这个指令后,读卡器就会把通信目标切换到这张卡片上。

3. 查询卡片名称(或类型/应用名称)

选中卡片后,就可以发送指令查询它的名称了,常见的两种方式:

  • 查询默认应用名称:发送00 A4 04 00 00(空AID查询指令),读卡器会返回卡片上默认应用的信息,其中通常包含应用名称(如果卡片支持的话)
  • 通过厂商信息映射名称:先发送FF CA 00 00 00获取卡片UID,再发送FF 00 00 00 00读取制造商信息,然后根据厂商代码(比如NXP对应MIFARE系列)映射出卡片的常见名称

4. 维护多卡片的动态列表

如果读卡器支持卡片热插拔(插入/移除),你需要定期轮询卡片数量,更新你的卡片列表:

  • 每隔几秒重新发送卡片数量查询指令
  • 对比新老列表,新增或移除对应的卡片信息
  • 所有USB通信操作都要放在子线程里,别阻塞UI线程!

简化代码示例

这里给你一个核心逻辑的代码片段,实际要根据你的读卡器指令调整:

// 假设已经拿到UsbDeviceConnection conn和对应的UsbEndpoint endpoint

// 1. 查询卡片数量
byte[] getCardCountCmd = hexStringToByteArray("FF 00 48 00 00");
byte[] countResponse = sendApdu(conn, endpoint, getCardCountCmd);
int cardCount = parseCardCount(countResponse); // 自己实现响应解析逻辑

// 2. 遍历每张卡片查询信息
for (int i = 0; i < cardCount; i++) {
    // 获取当前卡片的UID
    byte[] getUidCmd = hexStringToByteArray("FF CA 00 00 00");
    byte[] uidResponse = sendApdu(conn, endpoint, getUidCmd);
    String cardUid = bytesToHexString(uidResponse);

    // 选中该卡片
    byte[] selectCmd = buildSelectCardCmd(cardUid); // 构建选中指令,传入UID生成对应字节数组
    sendApdu(conn, endpoint, selectCmd);

    // 查询卡片名称
    byte[] getNameCmd = hexStringToByteArray("00 A4 04 00 00");
    byte[] nameResponse = sendApdu(conn, endpoint, getNameCmd);
    String cardName = parseCardName(nameResponse); // 解析响应中的名称字段

    // 打印或保存卡片信息
    Log.d("CardManager", "卡片UID: " + cardUid + ",名称: " + cardName);
}

// 辅助方法:十六进制字符串转字节数组
private byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

关键提醒

  • 一定要看读卡器文档:不同厂商的读卡器指令差异很大,比如有些国产读卡器用自定义指令枚举多卡片,别盲目用标准PC/SC指令
  • APDU响应要先判断状态码:响应的最后两个字节是状态码,90 00表示操作成功,其他码都是失败,要先判断再解析数据
  • 线程安全很重要:USB通信是同步阻塞的,所有指令发送和解析都要放在子线程,避免ANR

内容的提问来源于stack exchange,提问作者Rishwanth L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:55:58