升级到API 33后onNewIntent中NFC的intent.getAction()返回null问题
问题分析与解决方案
Android 12+(API31+)NFC的关键变更
从API31开始,NFC前台调度(enableForegroundDispatch)有两个核心变更:
- PendingIntent必须指定可修改标记:系统需要修改PendingIntent中的Intent来添加NFC相关的Action和Extra,因此必须使用
PendingIntent.FLAG_MUTABLE(你的代码已经正确处理了这一点)。 - IntentFilter匹配逻辑更严格:API31+对前台调度的IntentFilter匹配做了收紧,之前宽松的匹配规则(比如宽泛的MIME类型)可能不再生效,导致系统无法正确触发对应的NFC Action。
你的代码问题所在
目前onNewIntent中intent.getAction()返回null,核心原因是前台调度的IntentFilter配置无法匹配NFC标签的类型,导致系统传递的Intent没有携带预期的Action:
- 你的
mFilters仅配置了ACTION_NDEF_DISCOVERED的过滤规则,且使用了addDataType("*/*")的宽泛MIME类型匹配。在API33中,这种宽泛匹配可能被系统限制,无法匹配实际的NDEF标签。 - 同时你配置了
mTechLists,但因为mFilters不为null,系统只会匹配符合mFilters规则的标签,不会触发ACTION_TECH_DISCOVERED的逻辑。
修复方案
方案1:补充TECH_DISCOVERED的IntentFilter
同时监听两种NFC触发Action,确保覆盖所有标签类型:
private void setUpNFC() { // ... 原有代码 ... IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); } catch (IntentFilter.MalformedMimeTypeException e) { FirebaseCrashlytics.getInstance().recordException(e); } // 新增TECH_DISCOVERED的过滤规则 IntentFilter tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED); mFilters = new IntentFilter[] {ndef, tech}; // ... 原有代码 ... }
方案2:移除IntentFilter,仅依赖TechLists
如果你的标签主要是基于技术类型(而非NDEF),可以将mFilters设为null,让系统匹配mTechLists中的技术类型:
private void setUpNFC() { // ... 原有代码 ... // 注释掉原有mFilters的配置,改为null // mFilters = new IntentFilter[] {ndef}; mFilters = null; // ... 原有代码 ... }
方案3:明确指定NDEF标签的MIME类型
如果你的NDEF标签有固定的MIME类型,替换*/*为具体类型(比如text/plain),避免宽泛匹配被系统限制:
try { // 替换为你实际的MIME类型 ndef.addDataType("text/plain"); } catch (IntentFilter.MalformedMimeTypeException e) { FirebaseCrashlytics.getInstance().recordException(e); }
额外排查点
- 检查
enableForegroundDispatch是否抛出异常:在catch块中添加日志,查看是否有SecurityException或其他异常,确认前台调度是否成功启用。 - 确认AndroidManifest中已声明NFC权限:
<uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="false" />
内容的提问来源于stack exchange,提问作者Orbit
相关产品推荐
相关产品推荐

