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
相关产品推荐
相关产品推荐

