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

Android HCE与ACR122U NFC读卡器兼容问题排查及代码求助

Android HCE NDEF模拟兼容ACR122U的解决方案

核心问题分析

ACR122U读卡器遵循的ISO 14443-3/4初始化流程、APDU命令逻辑,与Android/iOS作为读卡器时的行为存在差异,主要体现在SELECT命令响应格式、ATS(Answer To Select)参数、NDEF数据读取命令处理三个方面。以下是针对性的代码修改和配置建议:


1. 修改KHostApduService的APDU响应逻辑

确保服务能正确处理ACR122U发送的标准NFC APDU命令,尤其是NDEF应用选择、数据读取命令:

class KHostApduService : HostApduService() {
    // NDEF标准应用AID
    private val NDEF_AID = "D2760000850101"
    // 成功响应状态码
    private val SELECT_OK_SW = "9000"
    // 未知命令状态码
    private val UNKNOWN_CMD_SW = "6F00"
    // 示例NDEF数据(可替换为自定义内容)
    private val NDEF_DATA = "0000031D5402656E48656C6C6F2046726F6D20416E64726F696420484345"

    override fun processCommandApdu(commandApdu: ByteArray?, extras: Bundle?): ByteArray {
        commandApdu ?: return hexStringToByteArray(UNKNOWN_CMD_SW)
        val cmdHex = byteArrayToHexString(commandApdu)

        // 处理NDEF应用SELECT命令
        if (cmdHex.startsWith("00A40400")) {
            val aidLength = cmdHex.substring(8, 10).toInt(16)
            val targetAid = cmdHex.substring(10, 10 + aidLength * 2)
            if (targetAid.equals(NDEF_AID, ignoreCase = true)) {
                // 返回符合ISO标准的FCI(File Control Information)响应
                val fciResponse = "6F108407${NDEF_AID}A5059F0400$SELECT_OK_SW"
                return hexStringToByteArray(fciResponse)
            }
        }
        // 处理NDEF数据READ BINARY命令
        else if (cmdHex.startsWith("00B00000")) {
            val readLength = cmdHex.substring(8, 10).toInt(16)
            val dataSegment = NDEF_DATA.substring(0, readLength * 2)
            return hexStringToByteArray("$dataSegment$SELECT_OK_SW")
        }

        return hexStringToByteArray(UNKNOWN_CMD_SW)
    }

    override fun onDeactivated(reason: Int) {}

    // 工具方法:字节数组转十六进制字符串
    private fun byteArrayToHexString(bytes: ByteArray): String {
        val hexArray = "0123456789ABCDEF".toCharArray()
        val hexChars = CharArray(bytes.size * 2)
        bytes.forEachIndexed { j, byte ->
            val v = byte.toInt() and 0xFF
            hexChars[j * 2] = hexArray[v ushr 4]
            hexChars[j * 2 + 1] = hexArray[v and 0x0F]
        }
        return String(hexChars)
    }

    // 工具方法:十六进制字符串转字节数组
    private fun hexStringToByteArray(s: String): ByteArray {
        val len = s.length
        val data = ByteArray(len / 2)
        var i = 0
        while (i < len) {
            data[i / 2] = ((Character.digit(s[i], 16) shl 4) + Character.digit(s[i+1], 16)).toByte()
            i += 2
        }
        return data
    }
}

2. 检查并修正HCE配置文件

AndroidManifest.xml中的服务声明

确保权限、IntentFilter和元数据配置正确:

<service
    android:name=".KHostApduService"
    android:exported="true"
    android:permission="android.permission.BIND_NFC_SERVICE">
    <intent-filter>
        <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
    </intent-filter>
    <meta-data
        android:name="android.nfc.cardemulation.host_apdu_service"
        android:resource="@xml/apduservice"/>
</service>

res/xml/apduservice.xml的AID过滤配置

必须包含NDEF标准应用AID:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/hce_service_description"
    android:requireDeviceUnlock="false">
    <aid-group android:description="@string/ndef_aid_group"
        android:category="other">
        <aid-filter android:name="D2760000850101"/> <!-- NDEF标准AID -->
    </aid-group>
</host-apdu-service>

3. 调整ACR122U读卡器配置

使用PC/SC工具向读卡器发送以下命令,修正其通信模式:

  • 切换到兼容ISO 14443-4的模式:FF00000004D4010000
  • 关闭自动PICC检测(避免读卡器主动触发防碰撞冲突):FF00000002D402
  • 设置通信速率为106kbps(匹配Android HCE默认速率):FF00000003D40301

额外注意事项

  • 若仍存在兼容性问题,可在KHostApduService的onCreate方法中自定义ATS响应:setAtrResponse(hexStringToByteArray("3B8F8001804F0CA000000306030001000000006A"))
  • 检查ACR122U固件版本,旧版本固件兼容性较差,建议升级至最新官方固件

内容的提问来源于stack exchange,提问作者Padmaja Rani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:20:32