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

Android NFC设置NTAG216密码遇Transceive failed异常求助

NTAG216设置密码失败问题排查与解决

问题描述

我是Android NFC开发新手,尝试为NTAG216 Mifare Ultralight标签设置密码时卡壳多日。使用的是空白标签,确认当前无保护,但设置命令执行失败。更换不同设备测试,仍出现相同错误。目前writePage和readPages方法可正常工作,transceive方法执行get_version、fast_read命令也正常,但设置密码和PACK时失败。

相关代码

package com.lancine.nfcapp;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.NfcA;
import android.os.Build;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.ui.AppBarConfiguration;
import com.lancine.nfcapp.databinding.ActivityMainBinding;
import java.io.IOException;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback {

    private AppBarConfiguration appBarConfiguration;
    private ActivityMainBinding binding;
    NfcAdapter mAdapter;
    PendingIntent pendingIntent;
    Tag tag;

    @SuppressLint("UnspecifiedImmutableFlag")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE);
        } else {
            pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_ONE_SHOT);
        }

        mAdapter = NfcAdapter.getDefaultAdapter(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        //mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
        if (mAdapter != null) {
            Bundle options = new Bundle();
            options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
            mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NFC_BARCODE | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS, options);
        }
    }

    @Override
    public void onTagDiscovered(Tag tag) {
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createOneShot(150, 10));
        } else {
            Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            v.vibrate(200);
        }

        this.setPassword(tag);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mAdapter != null) {
            mAdapter.disableReaderMode(this);
        }
    }

    public void setPassword(Tag tag) {
        (new Thread(() -> {
            NfcA nfcA = null;
            try {
                nfcA = NfcA.get(tag);
                if(nfcA != null) {
                    nfcA.connect();
                    byte[] data = nfcA.transceive(new byte[] {
                            (byte)0xA2, // WRITE
                            (byte)(229 & 0x0ff), // block address
                            (byte)0x34, (byte)0x36, (byte)0x37, (byte)0x32
                    });
                    System.out.println("Comment" + Arrays.toString(data));
                    nfcA.close();
                }
            } catch (IOException e) {
                Log.e("TAG", "IOException", e);
                e.printStackTrace();
            }
        })).start();
    }
}

错误栈信息

W/System.err: java.io.IOException: Transceive failed
W/System.err: at android.nfc.TransceiveResult.getResponseOrThrow(TransceiveResult.java:52)
W/System.err: at android.nfc.tech.BasicTagTechnology.transceive(BasicTagTechnology.java:151)
W/System.err: at android.nfc.tech.MifareUltralight.transceive(MifareUltralight.java:215)
W/System.err: at com.lancine.nfcapp.MainActivity.lambda$nfcCommand$0$com-lancine-nfcapp-MainActivity(MainActivity.java:153)
W/System.err: at com.lancine.nfcapp.MainActivity$$ExternalSyntheticLambda0.run(D8$$SyntheticClass)
W/System.err: at java.lang.Thread.run(Thread.java:761)

NXP TagInfo读取的标签信息

详细协议信息:

ID: 04:DE:58:42:EC:64:80
ATQA: 0x4400
SAK: 0x00

# Memory content:
[00] *  04:DE:58 0A (UID0-UID2, BCC0)
[01] *  42:EC:64:80 (UID3-UID6)
[02] .  4A 48 00 00 (BCC1, INT, LOCK0-LOCK1)
[03] .  E1:11:6D:00 (OTP0-OTP3)
[04] .  03 0B D1 01 |....|
[05] .  07 54 02 66 |.T.f|
[06] .  72 59 65 6F |rYeo|
[07] .  79 FE 00 00 |y...|
[08] .  32 22 2C 22 |2","|
[09] .  63 61 72 74 |cart|
[0A] .  5F 69 64 22 |_id"|
[0B] .  3A 22 31 30 |:"10|
[0C] .  30 30 30 30 |0000|
[0D] .  30 30 22 2C |00",|
[0E] .  22 65 74 61 |"eta|
[0F] .  62 5F 69 64 |b_id|
[10] .  22 3A 22 31 |":"1|
[11] .  30 30 30 30 |0000|
[12] .  30 30 22 2C |00",|
[13] .  22 65 74 61 |"eta|
[14] .  62 5F 6E 6F |b_no|
[15] .  6D 22 3A 22 |m":"|
[16] .  4C 59 43 45 |LYCE|

[E1] .r 00 00 00 00 |....|
[E2] .r 00 00 00 BD (LOCK2-LOCK4, CHK)
[E3] .r 04 00 00 E1 (CFG, MIRROR, AUTH0)
[E4] .r 00 05 -- -- (ACCESS)
[E5] +P XX XX XX XX (PWD0-PWD3)
[E6] +P XX XX -- -- (PACK0-PACK1)

  *:locked & blocked, x:locked,
  +:blocked, .:un(b)locked, ?:unknown
  r:readable (write-protected),
  p:password protected, -:write-only
  P:password protected write-only

问题分析与解决

  1. 核心问题定位
    从TagInfo输出看,标签的AUTH0配置为0xE1,这意味着从页0xE1开始的所有存储区都需要密码验证才能读写。你尝试直接写入密码页0xE5,但未先完成密码验证,导致命令被拒绝。

  2. 修正步骤

    • 先使用默认密码(全0x00)完成验证,获得写入权限
    • 改用MifareUltralight类操作,更适配Mifare Ultralight系列标签
    • 写入密码后可按需配置PACK(密码验证响应码)
  3. 修正后的代码示例

public void setPassword(Tag tag) {
    new Thread(() -> {
        MifareUltralight mifare = null;
        try {
            mifare = MifareUltralight.get(tag);
            if(mifare != null) {
                mifare.connect();
                // 用默认全0密码验证
                byte[] authResp = mifare.transceive(new byte[]{(byte)0x1B, 0x00, 0x00, 0x00, 0x00});
                Log.d("TAG", "验证响应: " + Arrays.toString(authResp));
                
                // 写入新密码到0xE5页
                byte[] pwdResp = mifare.transceive(new byte[]{
                        (byte)0xA2,
                        (byte)0xE5,
                        (byte)0x34, (byte)0x36, (byte)0x37, (byte)0x32
                });
                Log.d("TAG", "密码写入响应: " + Arrays.toString(pwdResp));
                
                // 写入PACK到0xE6页(前2字节有效,后2字节无意义)
                byte[] packResp = mifare.transceive(new byte[]{
                        (byte)0xA2,
                        (byte)0xE6,
                        (byte)0xAB, (byte)0xCD, 0x00, 0x00
                });
                Log.d("TAG", "PACK写入响应: " + Arrays.toString(packResp));
                
                mifare.close();
            }
        } catch (IOException e) {
            Log.e("TAG", "操作失败", e);
        }
    }).start();
}
  1. 额外注意事项
    • 若后续不需要密码保护,需将AUTH0页(0xE3最后1字节)改为0xFF,否则写入密码后所有0xE1及之后的页都需要验证密码才能访问
    • 确保标签未被物理锁死,从LOCK2-LOCK4的状态看,当前配置区未被锁死,可正常修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 23:45:41