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

Android 13中WriteNdefMessage后GetNdefMessage返回null问题求助

Android 13(targetSdk 33)NFC写入后读取返回null的问题解决

问题描述

传感器采用NFC技术,手机通过NFC获取水污染程度数据,原有逻辑为:调用GetNdefMessage读取数据,若数据有误则调用WriteNdefMessage重新写入标准数据后再次读取。将targetSdkVersion升级至33后,在Android 13设备上测试发现,执行WriteNdefMessage后立即调用GetNdefMessage返回null。已查阅Google官方文档未发现Android 31到33间NFC相关变更,尝试调整写入时机、切换ReaderMode与ForegroundDispatch等方案均未解决问题。

相关核心代码如下:

public class TestSensor extends AppCompatActivity {
    private NfcAdapter nfcAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onResume(){
        super.onResume();
        try {
            if (nfcAdapter != null) {
                Bundle options = new Bundle();
                options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
                nfcAdapter.enableReaderMode(this,new NfcReaderClass(), NfcAdapter.FLAG_READER_NFC_A |
                        NfcAdapter.FLAG_READER_NFC_B |
                        NfcAdapter.FLAG_READER_NFC_F |
                        NfcAdapter.FLAG_READER_NFC_V ,options);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    protected void onNewIntent(Intent intent){
        super.onNewIntent(intent);
    }

    @Override
    public void onPause(){
        super.onPause();
        try {
            if (nfcAdapter != null) {
                nfcAdapter.disableReaderMode(this);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}
class NfcReaderClass implements NfcAdapter.ReaderCallback {
    private Tag mTag = null;
    private Ndef m_Ndef = null;
    @Override
    public void onTagDiscovered(Tag tag) {
        try {
            if (tag != null){
                this.mTag = tag;
                writeNfcNdef();
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    public void writeNfcNdef(){
        try {
            this.m_Ndef = Ndef.get(this.mTag);
            if (this.m_Ndef != null){
                byte[] info2 = hexStringToByteArray("AA00");
                NdefRecord record =  RecordUtil.makeMimeTypeRecord("app/x-sensor", null, info2);
                NdefMessage msg = new NdefMessage(new NdefRecord[]{record});

                this.m_Ndef.connect();
                this.m_Ndef.writeNdefMessage(msg);
                this.m_Ndef.close();
                this.m_Ndef = Ndef.get(this.mTag);
                this.m_Ndef.connect();

                NdefMessage msg1 = this.m_Ndef.getNdefMessage();
                Log.e("msg","!!! "+ msg1);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

可能原因分析

  1. 标签写入后的状态同步延迟:NFC标签完成写入操作后,内部需要短暂时间更新存储状态,立即重新连接读取可能无法获取到最新数据。
  2. ReaderMode标志位冲突:当前设置的ReaderMode未跳过系统自动NDEF检测,系统后台的NFC操作可能与应用的读写逻辑产生干扰。
  3. 同一Tag实例复用问题:在同一个onTagDiscovered回调中,写入后直接复用原Tag实例重新获取Ndef对象,无法正确捕获标签写入后的状态变化。

解决方案

方案1:写入后添加延迟再读取(避免主线程阻塞)

给标签预留状态同步时间,通过Handler实现延迟读取,避免主线程阻塞:

public void writeNfcNdef(){
    try {
        this.m_Ndef = Ndef.get(this.mTag);
        if (this.m_Ndef != null && this.m_Ndef.isWritable()){
            byte[] info2 = hexStringToByteArray("AA00");
            NdefRecord record =  RecordUtil.makeMimeTypeRecord("app/x-sensor", null, info2);
            NdefMessage msg = new NdefMessage(new NdefRecord[]{record});

            this.m_Ndef.connect();
            this.m_Ndef.writeNdefMessage(msg);
            this.m_Ndef.close();

            // 延迟500ms后重新读取,适配标签状态同步
            new Handler(Looper.getMainLooper()).postDelayed(() -> {
                try {
                    Ndef newNdef = Ndef.get(mTag);
                    if (newNdef != null) {
                        newNdef.connect();
                        NdefMessage msg1 = newNdef.getNdefMessage();
                        Log.e("msg","!!! "+ msg1);
                        newNdef.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, 500);
        }
    } catch (Exception e){
        e.printStackTrace();
    }
}

方案2:调整ReaderMode标志位

添加FLAG_READER_SKIP_NDEF_CHECK标志,跳过系统自动NDEF检测,避免操作冲突:

@Override
public void onResume(){
    super.onResume();
    try {
        if (nfcAdapter != null) {
            Bundle options = new Bundle();
            options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
            nfcAdapter.enableReaderMode(this,new NfcReaderClass(), 
                    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, // 添加此标志
                    options);
        }
    }
    catch (Exception e){
        e.printStackTrace();
    }
}

方案3:拆分读写流程,依赖标签重检测触发读取

不在同一个onTagDiscovered回调中完成写+读操作,改为:

  1. 首次检测标签时读取数据,判断有误则执行写入;
  2. 写入完成后,提示用户轻微移动标签触发重新检测,再读取最新数据。
    调整后的NfcReaderClass逻辑:
class NfcReaderClass implements NfcAdapter.ReaderCallback {
    private boolean needRewrite = false;

    @Override
    public void onTagDiscovered(Tag tag) {
        try {
            Ndef ndef = Ndef.get(tag);
            if (ndef != null) {
                ndef.connect();
                NdefMessage msg = ndef.getNdefMessage();
                ndef.close();
                
                // 替换为实际的数据校验逻辑
                if (msg == null || msg.getRecords().length == 0) {
                    needRewrite = true;
                    writeNfcNdef(tag);
                } else {
                    // 处理正确数据
                    Log.e("msg","读取到有效数据: "+ msg);
                    needRewrite = false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void writeNfcNdef(Tag tag){
        try {
            Ndef ndef = Ndef.get(tag);
            if (ndef != null && ndef.isWritable()){
                byte[] info2 = hexStringToByteArray("AA00");
                NdefRecord record =  RecordUtil.makeMimeTypeRecord("app/x-sensor", null, info2);
                NdefMessage msg = new NdefMessage(new NdefRecord[]{record});

                ndef.connect();
                ndef.writeNdefMessage(msg);
                ndef.close();
                Log.e("msg","写入完成,请轻微移动标签重新读取");
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

额外注意事项

  • 确保所有NFC操作的connect()与close()调用配对,避免资源泄漏;
  • 操作前检查标签的isWritable()状态,避免写入不可写标签引发异常;
  • Android 13中NFC权限仍为android.permission.NFC,需确保已在Manifest中声明该权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 06:24:49