扫描NFC标签时onNewIntent中intent.getAction()始终返回null的解决办法
解决NFC扫描后onNewIntent中intent.getAction()返回null的问题
问题场景
运行自研APP扫描NFC标签时,onNewIntent方法被触发,但intent.getAction()始终返回null,无法识别NFC相关动作。
原代码
MainActivity Java代码
public class MainActivity extends AppCompatActivity { TextView nfcText; private final String[][] techList = new String[][] { new String[] {NfcA.class.getName(), NfcB.class.getName(), NfcF.class.getName(), NfcV.class.getName(), NdefFormatable.class.getName(), TagTechnology.class.getName(), IsoDep.class.getName(), MifareClassic.class.getName(), MifareUltralight.class.getName(), Ndef.class.getName()} }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onResume() { super.onResume(); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_IMMUTABLE); IntentFilter filter = new IntentFilter(); //filter.addCategory(Intent.CATEGORY_DEFAULT); filter.addAction(NfcAdapter.ACTION_TAG_DISCOVERED); filter.addAction(NfcAdapter.ACTION_NDEF_DISCOVERED); filter.addAction(NfcAdapter.ACTION_TECH_DISCOVERED); NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); nfcAdapter.enableForegroundDispatch(this, pendingIntent, new IntentFilter[]{filter}, this.techList); } @Override protected void onNewIntent(Intent intent) { //super.onNewIntent(intent); //setIntent(intent); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) { nfcText = (TextView) findViewById(R.id.nfcText); nfcText.setText(byteArrayToHexString(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID))); } } }
AndroidManifest.xml代码
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.nfcactivity"> <uses-sdk android:minSdkVersion="10"></uses-sdk> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.NfcActivity"> <activity > android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <data android:mimeType="text/plain"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
问题分析
- Manifest配置错误:存在无
android:name的空Activity标签,且启动页LAUNCHER过滤器未绑定到MainActivity,导致APP启动后进入的不是目标页面,前台NFC调度无法生效。 - Intent未正确更新:注释掉
super.onNewIntent(intent)和setIntent(intent),导致Activity无法获取最新的NFC触发Intent。 - IntentFilter缺失必要Category:前台调度的
IntentFilter未添加Intent.CATEGORY_DEFAULT,可能导致Intent匹配失败。 - 工具方法缺失:代码中调用的
byteArrayToHexString未实现,会引发编译错误。
解决方案
1. 修正AndroidManifest.xml配置
删除空Activity标签,将启动页过滤器移到MainActivity中,确保MainActivity为APP入口:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.nfcactivity"> <uses-sdk android:minSdkVersion="10"></uses-sdk> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.NfcActivity"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <data android:mimeType="text/plain"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
2. 修复MainActivity代码
恢复onNewIntent的super调用和Intent更新,完善IntentFilter,补充byteArrayToHexString方法:
public class MainActivity extends AppCompatActivity { TextView nfcText; private final String[][] techList = new String[][] { new String[] {NfcA.class.getName(), NfcB.class.getName(), NfcF.class.getName(), NfcV.class.getName(), NdefFormatable.class.getName(), TagTechnology.class.getName(), IsoDep.class.getName(), MifareClassic.class.getName(), MifareUltralight.class.getName(), Ndef.class.getName()} }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); nfcText = findViewById(R.id.nfcText); // 提前初始化避免重复查找 } @Override protected void onResume() { super.onResume(); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_IMMUTABLE); IntentFilter filter = new IntentFilter(); filter.addCategory(Intent.CATEGORY_DEFAULT); // 添加必要Category filter.addAction(NfcAdapter.ACTION_TAG_DISCOVERED); filter.addAction(NfcAdapter.ACTION_NDEF_DISCOVERED); filter.addAction(NfcAdapter.ACTION_TECH_DISCOVERED); NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter != null) { // 空判断避免NFC未支持的设备崩溃 nfcAdapter.enableForegroundDispatch(this, pendingIntent, new IntentFilter[]{filter}, this.techList); } } @Override protected void onPause() { super.onPause(); // 页面暂停时关闭前台调度,避免资源泄漏 NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter != null) { nfcAdapter.disableForegroundDispatch(this); } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); // 更新当前Activity的Intent String action = intent.getAction(); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { byte[] tagId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); nfcText.setText(byteArrayToHexString(tagId)); } } // 实现byte数组转十六进制字符串的工具方法 private String byteArrayToHexString(byte[] bytes) { if (bytes == null) return ""; StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X ", b)); } return sb.toString().trim(); } }
额外说明
- 在
onPause中关闭前台调度,避免APP后台时仍占用NFC资源。 - 提前初始化
nfcText,避免每次触发NFC都重复调用findViewById。 - 添加
NfcAdapter空判断,适配无NFC功能的设备(尽管Manifest中声明了required为true,但仍建议保留以增强鲁棒性)。
内容的提问来源于stack exchange,提问作者hunny
相关产品推荐
相关产品推荐

