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

Android平台基于Flutter实现NFC标签模拟(HCE)技术求助

Android平台Flutter实现NFC HCE标签模拟方案

核心前提确认

  • 设备兼容性:仅支持具备NFC HCE功能的Android设备,可通过原生代码检查PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
  • 门禁协议适配:HCE仅支持ISO 14443-4标准的AID模拟,无法兼容MIFARE Classic(需硬件加密模块支持),先确认门禁系统使用的NFC协议类型

关键实现步骤

1. 配置AndroidManifest.xml

添加NFC权限、声明HCE服务及AID过滤规则:

<!-- 基础权限与特性声明 -->
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />

<!-- HCE服务声明 -->
<service android:name=".HceService"
         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:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
                   android:description="@string/hce_service_desc"
                   android:requireDeviceUnlock="false">
    <aid-group android:description="@string/aid_group_desc"
               android:category="other">
        <!-- 替换为门禁系统识别的真实AID -->
        <aid-filter android:name="F0010203040506"/>
    </aid-group>
</host-apdu-service>

2. 实现原生HCE服务

创建HceService类继承HostApduService,处理门禁读卡器的APDU命令:

import android.nfc.cardemulation.HostApduService;
import android.os.Bundle;
import java.util.Arrays;

public class HceService extends HostApduService {
    // 门禁读卡器发送的SELECT AID命令(需与真实卡片的命令匹配)
    private static final byte[] SELECT_APDU = {
        (byte)0x00, (byte)0xA4, (byte)0x04, (byte)0x00,
        (byte)0x07, (byte)0xF0, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06,
        (byte)0x00
    };
    // 模拟门禁授权成功的响应
    private static final byte[] SUCCESS_RESPONSE = { (byte)0x90, (byte)0x00 };
    // 命令不匹配时的失败响应
    private static final byte[] FAILURE_RESPONSE = { (byte)0x6A, (byte)0x82 };

    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
        // 匹配读卡器的SELECT命令,返回模拟卡片的响应
        if (Arrays.equals(apdu, SELECT_APDU)) {
            return SUCCESS_RESPONSE;
        }
        return FAILURE_RESPONSE;
    }

    @Override
    public void onDeactivated(int reason) {
        // 处理卡片模拟失活的逻辑(比如重置状态)
    }
}

3. Flutter与原生层交互(可选)

若需在Flutter端动态修改模拟数据,通过MethodChannel实现跨层通信:

Flutter端代码:

import 'package:flutter/services.dart';

class HceController {
  static const MethodChannel _channel = MethodChannel('hce_control_channel');

  /// 更新门禁响应数据
  static Future<void> updateResponse(List<int> responseBytes) async {
    await _channel.invokeMethod('updateResponse', {'data': responseBytes});
  }
}

原生层HceService中添加MethodChannel处理:

import io.flutter.plugin.common.MethodChannel;

public class HceService extends HostApduService {
    private static byte[] customResponse = SUCCESS_RESPONSE;

    @Override
    public void onCreate() {
        super.onCreate();
        new MethodChannel(getApplicationContext(), "hce_control_channel")
            .setMethodCallHandler((call, result) -> {
                if (call.method.equals("updateResponse")) {
                    List<Integer> dataList = call.argument("data");
                    byte[] newResponse = new byte[dataList.size()];
                    for (int i = 0; i < dataList.size(); i++) {
                        newResponse[i] = dataList.get(i).byteValue();
                    }
                    customResponse = newResponse;
                    result.success(null);
                } else {
                    result.notImplemented();
                }
            });
    }

    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
        if (Arrays.equals(apdu, SELECT_APDU)) {
            return customResponse;
        }
        return FAILURE_RESPONSE;
    }

    // ...其他代码
}

常见问题排查

  • AID不匹配:用NFC工具读取真实门禁卡的AID,确保与配置的aid-filter完全一致
  • 设备不支持:部分低端Android设备无HCE功能,可在系统设置中查看是否有"NFC卡片模拟"选项
  • 权限问题:确保APP已获取NFC权限,且运行时处于前台状态
  • MIFARE Classic限制:若门禁使用该协议,HCE无法模拟,需更换支持ISO 14443-4的门禁系统或设备

内容的提问来源于stack exchange,提问作者Jude Dcoutho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:36:00