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

Android HostApduService卡模拟标签ID动态,无法用ignore屏蔽重复读取

解决手机模拟NFC卡重复读取及固定ID问题

一、让模拟NFC卡拥有固定标签ID

HostApduService默认每次模拟的ID是随机生成的,要固定ID可通过以下方式实现:

  • 在你的HostApduService实现类中,根据模拟的NFC技术类型,重写对应方法返回固定字节数组:
    • 若模拟ISO-DEP类型卡片,重写getUid()方法
    • 若模拟NFC-F类型卡片,重写getNfcFId()方法
      示例代码:
    @Override
    public byte[] getUid() {
        // 自定义固定UID,需符合对应NFC标准长度(如ISO-DEP通常4-7字节)
        return new byte[]{(byte)0x12, (byte)0x34, (byte)0x56, (byte)0x78};
    }
    
  • 注意:部分Android设备或系统版本可能限制自定义UID,需实际测试适配;同时UID不要与常见实体卡冲突,避免识别异常。

二、让nfcAdapter.ignore()对模拟卡生效

如果暂时无法固定ID,可通过识别模拟卡的特征标记忽略,而非依赖UID:

  • 读取卡的ATR(Answer To Reset)数据:模拟卡的ATR通常有固定格式,可与实体EMV卡区分。在读卡器端获取Tag对象的getHistoricalBytes(),将其哈希值作为模拟卡的唯一特征。
  • 维护临时集合记录正在处理的模拟卡特征,避免重复触发读取逻辑,处理完成后结合ignore()方法屏蔽后续请求。
    示例逻辑:
    private Set<String> processingCards = new HashSet<>();
    
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null) {
            byte[] historicalBytes = tag.getHistoricalBytes();
            if (historicalBytes != null) {
                String cardFeature = Arrays.hashCode(historicalBytes) + "";
                if (!processingCards.contains(cardFeature)) {
                    processingCards.add(cardFeature);
                    // 执行卡读取处理逻辑
                    processCard(tag);
                    // 处理完成后设置忽略,移除集合标记
                    nfcAdapter.ignore(tag, 5000, new NfcAdapter.OnTagRemovedListener() {
                        @Override
                        public void onTagRemoved() {
                            processingCards.remove(cardFeature);
                        }
                    }, null);
                }
            }
        }
    }
    

三、额外适配提示

  • 固定UID时需严格遵循NFC规范:比如ISO 14443 Type A的UID长度支持4、7或10字节,Type B为4字节,不要随意设置长度导致识别失败。
  • 部分设备支持通过Manifest配置固定UID,可在HostApduService的声明中添加meta-data(兼容性有限,优先用代码重写方式):
    <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/apduservice"/>
        <!-- 部分设备支持的固定UID配置 -->
        <meta-data android:name="android.nfc.cardemulation.uid"
                   android:value="12345678"/>
    </service>
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 15:31:11