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

Android无法读取NFC 4K卡数据求助 附完整配置及实现代码

NFC 4K卡读取失败修复方案

现有代码存在的问题

  • 仅实现了标签发现的回调逻辑,未针对Mifare Classic 4K卡编写认证、读块的核心读卡逻辑
  • enableReaderMode方法传入的flags参数使用Integer.MAX_VALUE不符合规范,无法正确匹配读卡技术
  • AndroidManifest中intent-filter配置了text/plain的mimeType限制,会过滤非NDEF文本格式的卡,影响非标准NDEF的4K卡识别

具体修复步骤

1. 修正AndroidManifest配置

删除intent-filter标签下的<data android:mimeType="text/plain" />配置,避免拦截非文本NDEF格式的NFC卡。
修改后对应配置如下:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <action android:name="android.nfc.action.TECH_DISCOVERED" />
    <action android:name="android.nfc.action.TAG_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" />

2. 修正ReaderMode的flags参数

将enableReaderMode方法中的Integer.MAX_VALUE替换为明确的NFC技术标志位,同时添加跳过系统NDEF检查的标志,提升读卡效率:

private void enableReaderMode() {
    showToast("Enabling reader mode...");
    Activity activity = MainActivity.this;
    nfcAdapter = NfcAdapter.getDefaultAdapter(activity);
    if (nfcAdapter != null) {
        int flags = NfcAdapter.FLAG_READER_NFC_A 
                | NfcAdapter.FLAG_READER_NFC_B 
                | NfcAdapter.FLAG_READER_NFC_F 
                | NfcAdapter.FLAG_READER_NFC_V
                | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK;
        nfcAdapter.enableReaderMode(activity, this, flags, null);
    }
}

3. 补充Mifare Classic 4K卡的读卡逻辑

Mifare Classic 4K卡属于加密卡,读卡前需要先验证对应扇区的密钥,默认通用密钥为FF FF FF FF FF FF,如果是定制卡需要替换为对应密钥。在onTagDiscovered方法中添加如下逻辑:

@Override
public void onTagDiscovered(Tag tag) {
    Log.d(TAG, "New tag discovered...");
    MifareClassic mifareClassic = MifareClassic.get(tag);
    if (mifareClassic == null) {
        Log.d(TAG, "非Mifare Classic卡,不支持读取");
        return;
    }
    try {
        mifareClassic.connect();
        // 验证卡类型
        int cardSize = mifareClassic.getSize();
        if (cardSize != MifareClassic.SIZE_4K) {
            Log.d(TAG, "当前卡不是4K容量,实际容量:" + cardSize + "字节");
            mifareClassic.close();
            return;
        }
        int sectorCount = mifareClassic.getSectorCount();
        Log.d(TAG, "卡总扇区数:" + sectorCount);
        // 默认密钥,可替换为实际卡的密钥
        byte[] keyA = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
        for (int sector = 0; sector < sectorCount; sector++) {
            // 认证当前扇区密钥A,也可使用authenticateSectorWithKeyB验证密钥B
            boolean authSuccess = mifareClassic.authenticateSectorWithKeyA(sector, keyA);
            if (!authSuccess) {
                Log.d(TAG, "扇区" + sector + "密钥认证失败,跳过读取");
                continue;
            }
            int blockCount = mifareClassic.getBlockCountInSector(sector);
            int firstBlockIndex = mifareClassic.sectorToBlock(sector);
            // 遍历读取当前扇区所有数据块,跳过最后一块的密钥区
            for (int i = 0; i < blockCount - 1; i++) {
                byte[] blockData = mifareClassic.readBlock(firstBlockIndex + i);
                Log.d(TAG, "扇区" + sector + " 块" + (firstBlockIndex + i) + " 数据:" + bytesToHex(blockData));
            }
        }
        mifareClassic.close();
    } catch (IOException e) {
        Log.e(TAG, "读卡异常:" + e.getMessage(), e);
        try {
            if (mifareClassic.isConnected()) {
                mifareClassic.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

// 字节数组转16进制字符串工具方法
private String bytesToHex(byte[] src) {
    StringBuilder stringBuilder = new StringBuilder();
    if (src == null || src.length <= 0) {
        return null;
    }
    for (byte b : src) {
        int v = b & 0xFF;
        String hv = Integer.toHexString(v);
        if (hv.length() < 2) {
            stringBuilder.append(0);
        }
        stringBuilder.append(hv).append(" ");
    }
    return stringBuilder.toString().trim();
}

注意事项

  • 读卡操作默认在子线程执行,若需将读取结果展示到UI,需主动切到主线程操作
  • 若默认密钥认证失败,说明卡为加密卡,需获取对应卡的正确密钥才能正常读取
  • 部分搭载国产NFC芯片的安卓设备对Mifare Classic卡的兼容性较差,读卡失败可更换设备尝试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 00:36:04