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(); } } }
可能原因分析
- 标签写入后的状态同步延迟:NFC标签完成写入操作后,内部需要短暂时间更新存储状态,立即重新连接读取可能无法获取到最新数据。
- ReaderMode标志位冲突:当前设置的ReaderMode未跳过系统自动NDEF检测,系统后台的NFC操作可能与应用的读写逻辑产生干扰。
- 同一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回调中完成写+读操作,改为:
- 首次检测标签时读取数据,判断有误则执行写入;
- 写入完成后,提示用户轻微移动标签触发重新检测,再读取最新数据。
调整后的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
相关产品推荐
相关产品推荐

