Android Reader模式下无法与Android HCE通信的技术求助
问题分析与解决方案
核心问题定位
你的场景中iPhone阅读器能正常通信但Android阅读器(S21)不行,主要原因集中在APDU格式错误、Android NFC系统的NDEF自动处理干扰、HCE服务未被正确选中、代码常量缺失这几点:
- APDU长度字段用了16位整数,不符合短APDU的单字节Lc要求,Android HCE对格式校验更严格,导致指令被拒绝
- Android NFC系统会自动检测NDEF标签并优先处理,干扰HCE服务激活,导致后续自定义APDU无法路由
- Android阅读器未显式发送SELECT AID指令,HCE服务未进入激活状态
- HCE代码中引用了未定义的
SELECT_PSW常量,指令匹配逻辑失效
具体修复步骤
1. 修正Flutter端APDU格式
将自定义APDU的长度字段改为单字节:
List<int> commandSignaturePin(List<int> data) { var result = <int>[]; result.addAll(commandPinVerify); // 替换为单字节长度,符合短APDU规范 result.add(data.length); result.addAll(data); return result; } final commandPinVerify = [0x00, 0x20, 0x00, 0x80];
2. 关闭Android端NDEF自动检测
修改poll方法参数,避免系统自动处理NDEF干扰HCE通信:
var tag = await FlutterNfcKit.poll( iosMultipleTagMessage: "Multiple tags found!", androidCheckNDEF: false, // 关闭自动NDEF检测 iosAlertMessage: "Scan your tag", readIso14443A: true, readIso14443B: false, readIso15693: false, readIso18092: false);
3. 显式发送SELECT AID指令
在自定义指令前先发送SELECT AID,确保HCE服务激活:
// 定义和HCE端一致的SELECT AID指令 final selectAidApdu = [0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01, 0x00]; // 先发送SELECT指令激活HCE服务 var selectResult = await FlutterNfcKit.transceive(Uint8List.fromList(selectAidApdu), timeout: Duration(seconds: 5)); print("SELECT AID结果: ${selectResult}"); // 再发送自定义指令 final pswApdu = commandSignaturePin("ciao".codeUnits); final ss = Uint8List.fromList(pswApdu); var result = await FlutterNfcKit.transceive(ss, timeout: Duration(seconds: 20)); print("自定义指令结果: ${result}");
4. 修复Android HCE服务的常量定义
在MyHostApduService中补充缺失的常量和变量定义:
public class MyHostApduService extends HostApduService { private final static String TAG = "MyHostApduService"; private static final byte[] SELECT_APPLICATION = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x07,(byte) 0xD2,(byte) 0x76,(byte) 0x00,(byte) 0x00,(byte) 0x85,(byte) 0x01,(byte) 0x01,(byte) 0x00}; // 补充缺失的SELECT_PSW常量 private static final byte[] SELECT_PSW = {(byte)0x00, (byte)0x20, (byte)0x00, (byte)0x80}; private static final byte[] SUCCESS_SW = new byte[] {(byte)0x90,(byte)0x00}; private static final byte[] FAILURE_SW = new byte[] {(byte)0x6a,(byte)0x82}; private boolean mAppSelected; private boolean mCcSelected; private boolean mNdefSelected; // 补充datiRicevuti变量定义 private String datiRicevuti; // 原有其他代码保持不变 }
额外验证建议
- 查看HCE服务的Logcat输出,确认是否收到SELECT AID和自定义指令
- 确保Android阅读器设备的NFC功能未被省电模式限制
- 测试时保持两台设备的NFC感应区域对齐,避免通信中断
内容的提问来源于stack exchange,提问作者Simone
相关产品推荐
相关产品推荐

