如何实现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




