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

Android NFC HCE双向通信:读卡器向HCE设备发送数据的实现方案咨询

NFC双向通信:读卡器向HCE设备发送数据及替代方案

一、实现读卡器向HCE设备发送数据

你的当前代码中,读卡器端尝试用Ndef.writeNdefMessage()写入数据,但HCE的HostApduService只处理了SELECT和READ_BINARY指令,未处理写入相关的APDU,导致数据无法被HCE接收。以下是具体修改方案:

1. HCE端:添加写入指令处理逻辑

在processCommandApdu方法中,增加对**WRITE_BINARY(0x00 D0)**指令的处理,接收读卡器发送的数据:

override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray {
    // 保留原有SELECT和READ_BINARY逻辑
    if (Arrays.equals(SELECT_APPLICATION, commandApdu)) {
        mAppSelected = true
        mCcSelected = false
        mNdefSelected = false
        return SUCCESS_SW
    } else if (mAppSelected && Arrays.equals(SELECT_CAPABILITY_CONTAINER, commandApdu)) {
        mCcSelected = true
        mNdefSelected = false
        return SUCCESS_SW
    } else if (mAppSelected && Arrays.equals(SELECT_NDEF_FILE, commandApdu)) {
        mCcSelected = false
        mNdefSelected = true
        return SUCCESS_SW
    } else if (commandApdu[0] == 0x00.toByte() && commandApdu[1] == 0xb0.toByte()) {
        // READ_BINARY逻辑保留
        return responseApdu
    } 
    // 新增WRITE_BINARY指令处理
    else if (mNdefSelected && commandApdu[0] == 0x00.toByte() && commandApdu[1] == 0xd0.toByte()) {
        // 提取偏移量(APDU的第3、4字节)
        val offset = ((commandApdu[2].toInt() and 0xFF) shl 8) or (commandApdu[3].toInt() and 0xFF)
        // 提取写入的数据(从第5字节开始)
        val receivedData = commandApdu.copyOfRange(5, commandApdu.size)
        // 处理数据:比如保存到本地变量、更新NDEF消息等
        // 示例:mNdefData = receivedData
        return SUCCESS_SW // 返回成功状态字(0x9000)
    }
    return FAILURE_SW
}

2. 读卡器端:两种发送数据的方式

方式一:基于IsoDep直接发送APDU(推荐,灵活性高)

HCE本质是模拟ISO-DEP协议的卡片,读卡器可通过IsoDep直接发送自定义APDU指令,与HCE端交互:

@Override
public void onTagDiscovered(Tag tag) {
    runOnUiThread(() -> readResult.setText(""));
    
    IsoDep isoDep = IsoDep.get(tag);
    if (isoDep != null) {
        try {
            isoDep.connect();
            // 1. 先发送SELECT指令选中HCE应用(与HCE端的SELECT_APPLICATION一致)
            byte[] selectApdu = SELECT_APPLICATION; // 替换为你定义的SELECT指令字节数组
            byte[] response = isoDep.transceive(selectApdu);
            
            // 检查是否选中成功
            if (Arrays.equals(response, new byte[]{(byte)0x90, 0x00})) {
                // 2. 发送自定义写入APDU,示例:发送数据"hello HCE"
                byte[] writeApdu = new byte[]{0x00, (byte)0xD0, 0x00, 0x00, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F};
                response = isoDep.transceive(writeApdu);
                
                if (Arrays.equals(response, new byte[]{(byte)0x90, 0x00})) {
                    runOnUiThread(() -> readResult.setText("数据发送成功"));
                } else {
                    runOnUiThread(() -> readResult.setText("发送失败:响应异常"));
                }
            }
            isoDep.close();
        } catch (Exception e) {
            runOnUiThread(() -> readResult.setText("发送失败:" + e.getMessage()));
        }
    } else {
        runOnUiThread(() -> readResult.setText("设备不支持ISO-DEP协议"));
    }
}

方式二:基于NDEF写入(需HCE完整模拟NDEF标签)

如果坚持用Ndef.writeNdefMessage(),需确保HCE端完整实现NDEF Type4标签的逻辑,包括处理WRITE_BINARY指令更新NDEF数据,这样读卡器的写入操作才能被HCE正确接收。

二、其他NFC双向通信方案

  • NFC Peer-to-Peer(P2P)模式:两个NFC设备直接以对等模式连接,基于NFCIP-1协议交换数据,无需HCE模拟卡片,可通过Ndef或IsoDep在P2P模式下通信。
  • 自定义APDU协议:脱离标准NDEF/Type4标签规范,在HCE端自定义一套APDU指令集,读卡器按约定发送指令,适合特定业务场景,灵活性最高。
  • Android Beam(兼容旧设备):Android 10之前的原生功能,通过NDEF消息在设备间快速传输数据,现已被Nearby Share替代,但部分旧设备仍支持。

内容的提问来源于stack exchange,提问作者Kamal Kumar Majhi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:44:55