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

扫描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>

问题分析

  1. Manifest配置错误:存在无android:name的空Activity标签,且启动页LAUNCHER过滤器未绑定到MainActivity,导致APP启动后进入的不是目标页面,前台NFC调度无法生效。
  2. Intent未正确更新:注释掉super.onNewIntent(intent)和setIntent(intent),导致Activity无法获取最新的NFC触发Intent。
  3. IntentFilter缺失必要Category:前台调度的IntentFilter未添加Intent.CATEGORY_DEFAULT,可能导致Intent匹配失败。
  4. 工具方法缺失:代码中调用的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:25:20