You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现Mifare Classic 1k NFC标签的读写操作(已获密钥及权限)

解决Mifare Classic 1K NFC标签的读写问题

嘿,看你已经搞定了密钥获取、NFC权限配置,还拿到了Tag对象,离成功读写Mifare Classic 1K标签只差最后几步啦!我帮你把完整的流程捋清楚,补全代码细节:

一、先确认设备支持Mifare Classic

首先你打印的tag.getTechList()输出里,必须包含android.nfc.tech.MifareClassic——如果没有的话,说明你的设备本身不支持Mifare Classic技术,那就没法继续操作这类标签了。

二、完整的认证与读写代码示例

你已经写了连接和部分认证逻辑,我把完整可运行的流程补全,核心是要针对扇区做认证(Mifare Classic 1K有16个扇区,每个扇区含4个块,最后一个块是密钥和控制块,不能随便改):

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if(tag != null) {
    Log.i("hey", Arrays.toString(tag.getTechList()));
    MifareClassic mfc = MifareClassic.get(tag);
    try {
        // 建立与标签的连接
        mfc.connect();
        
        // 选择要操作的扇区(示例选扇区0,你可以改成目标扇区)
        int targetSector = 0;
        // 替换成你获取到的A密钥(注意是byte数组格式)
        byte[] keyA = new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF};
        
        // 用A密钥认证扇区(如果访问条件要求用B密钥,就用authenticateSectorWithKeyB)
        boolean isAuthSuccess = mfc.authenticateSectorWithKeyA(targetSector, keyA);
        if(isAuthSuccess) {
            Log.i("NFC", "扇区认证成功!");
            
            // 获取该扇区第一个块的索引
            int firstBlockOfSector = mfc.sectorToBlock(targetSector);
            
            // 读取块数据(示例读扇区0的第一个块)
            byte[] readData = mfc.readBlock(firstBlockOfSector);
            Log.i("NFC", "读取到的数据:" + Arrays.toString(readData));
            
            // 准备写入的数据(必须是16字节,Mifare Classic每个块固定16字节)
            byte[] writeData = new byte[16];
            // 填充测试内容,剩下的字节补0
            System.arraycopy("Hello NFC!".getBytes(), 0, writeData, 0, "Hello NFC!".getBytes().length);
            
            // 写入块数据(注意:别写扇区的最后一个控制块,会搞坏卡片!这里写扇区0的第二个块)
            mfc.writeBlock(firstBlockOfSector + 1, writeData);
            Log.i("NFC", "数据写入成功!");
        } else {
            Log.e("NFC", "扇区认证失败!检查密钥是否正确,或者是否匹配访问条件");
        }
        
        // 操作完成记得关闭连接
        mfc.close();
    } catch (IOException e) {
        Log.e("NFC", "操作异常:" + e.getMessage());
        // 异常时也要确保关闭连接
        try {
            if(mfc.isConnected()) {
                mfc.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

三、必须注意的细节

  • 密钥与访问条件匹配:你提到已经拿到访问条件,要是条件要求只能用Key B认证,就把代码里的authenticateSectorWithKeyA换成authenticateSectorWithKeyB,别硬用A密钥碰钉子。
  • 控制块不能乱改:每个扇区的最后一个块是存储密钥和访问规则的控制块,除非你明确知道要修改什么,否则绝对不要写入这个块,会直接导致卡片报废。
  • 完善清单配置:除了你加的NFC权限,还要给处理NFC的Activity添加intent过滤,确保应用能接收到NFC触发的Intent:
<activity android:name=".YourNfcHandlingActivity">
    <!-- 基础的TAG_DISCOVERED过滤 -->
    <intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
    <!-- 精准匹配Mifare Classic的TECH_DISCOVERED过滤 -->
    <meta-data
        android:name="android.nfc.action.TECH_DISCOVERED"
        android:resource="@xml/nfc_tech_filter"/>
</activity>

然后在res/xml目录下创建nfc_tech_filter.xml文件:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.MifareClassic</tech>
    </tech-list>
</resources>

四、常见问题排查

  • 认证失败:检查密钥的byte数组是否正确(别把字符串当成byte数组用),扇区索引是否选对,以及访问条件是否允许当前密钥做认证。
  • 读写抛IOException:可能是连接中途断开,或者目标块被设为只读,回去核对访问条件里的块权限设置。
  • 设备不支持Mifare Classic:部分安卓设备(比如部分华为、三星机型)不兼容Mifare Classic,这种情况下只能换设备或者换其他类型的NFC标签。

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

火山引擎 最新活动