Android Kotlin下HCE模拟NFC卡无响应问题求助
我在Android应用中尝试通过HCE模拟NFC卡,使用另一台安装了NFC Tools应用的手机作为读卡器时,无法读取任何内容,且Apdu服务接收不到任何命令。测试设备为搭载Android 12的Galaxy A31,已完成以下配置:
Manifest配置
<service android:name=".MyHostApduService" 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/hce_service" /> </service>
MyHostApduService代码
class MyHostApduService : HostApduService() { companion object { val TAG = "Host Card Emulator" val STATUS_SUCCESS = "9000" val STATUS_FAILED = "6F00" val CLA_NOT_SUPPORTED = "6E00" val INS_NOT_SUPPORTED = "6D00" val AID = "A0000002471001" val SELECT_INS = "A4" val DEFAULT_CLA = "00" val MIN_APDU_LENGTH = 12 } override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray? { Log.i(TAG, "APDU Command Received: ${commandApdu.joinToString()}") val hexCommandApdu = toHex(commandApdu) if (hexCommandApdu.length < MIN_APDU_LENGTH) { return hexStringToByteArray(STATUS_FAILED) } if (hexCommandApdu.substring(0, 2) != DEFAULT_CLA) { return hexStringToByteArray(CLA_NOT_SUPPORTED) } if (hexCommandApdu.substring(2, 4) != SELECT_INS) { return hexStringToByteArray(INS_NOT_SUPPORTED) } if (hexCommandApdu.substring(10, 24) == AID) { return hexStringToByteArray(STATUS_SUCCESS) } else { return hexStringToByteArray(STATUS_FAILED) } } override fun onDeactivated(reason: Int) { Log.d(TAG, "Deactivated: $reason") } private val HEX_CHARS = "0123456789ABCDEF" private fun hexStringToByteArray(data: String) : ByteArray { val result = ByteArray(data.length / 2) for (i in data.indices step 2) { val firstIndex = HEX_CHARS.indexOf(data[i]); val secondIndex = HEX_CHARS.indexOf(data[i + 1]); val octet = firstIndex.shl(4).or(secondIndex) result.set(i.shr(1), octet.toByte()) } return result } private val HEX_CHARS_ARRAY = "0123456789ABCDEF".toCharArray() private fun toHex(byteArray: ByteArray) : String { val result = StringBuffer() byteArray.forEach { val octet = it.toInt() val firstIndex = (octet and 0xF0).ushr(4) val secondIndex = octet and 0x0F result.append(HEX_CHARS_ARRAY[firstIndex]) result.append(HEX_CHARS_ARRAY[secondIndex]) } return result.toString() } }
hce_service.xml配置
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/service_name" android:requireDeviceUnlock="false"> <aid-group android:description="@string/service_name" android:category="other"> <aid-filter android:name="F0010203040506"/> <aid-filter android:name="F0394148148100"/> </aid-group> </host-apdu-service>
问题排查与解决步骤
核心问题:AID不匹配
你在Service代码中硬编码的AID是A0000002471001,但xml配置里的AID过滤器是F0010203040506和F0394148148100,两者完全不匹配。读卡器(NFC Tools)只会发送匹配你xml中注册AID的SELECT指令,而你的Service只响应A0000002471001,自然收不到任何命令。
解决:将xml里的AID过滤器修改为与Service中一致的A0000002471001,或者调整Service中的AID常量匹配xml里的任意一个AID。确认HCE服务的优先级与默认设置
Android系统会优先选择优先级更高的HCE服务,可在xml的<aid-group>标签中添加android:priority="1000"(数值越高优先级越高),确保你的服务被系统选中。另外,进入设备系统设置的「NFC」-「卡模拟」选项,确认你的应用已设置为默认卡模拟服务,部分设备需要手动指定。调整NFC Tools的测试方式
NFC Tools的默认「读取NFC卡」功能通常只会扫描标准卡的AID,不会主动触发自定义HCE服务。你需要手动创建「读取自定义AID」任务,输入你注册的AID值后再进行测试。验证设备兼容性与物理操作
确认Galaxy A31的NFC功能已开启,测试时两台手机的NFC天线(通常位于顶部或背部中心)对齐,保持近距离接触,避免因天线位置不对导致通信失败。
内容的提问来源于stack exchange,提问作者Matteo

