为何关闭应用后NFC_TAG仍被检测?如何限定仅在指定组件扫描?
解决NFC仅在指定Fragment/Activity中扫描的问题
问题场景
应用当前就算关闭了,还会一直检测NFC标签,想要改成只在特定Fragment或Activity页面里才触发NFC扫描。当前Manifest配置如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Testing" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTask" android:label="@string/app_name"> <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> </activity> </application> </manifest>
解决方案
1. 删掉Manifest里的NFC静态Intent过滤器
你现在给MainActivity加了TAG_DISCOVERED的静态Intent过滤器,这会让系统一检测到NFC标签就唤醒应用,不管应用有没有在前台运行。第一步得把这个过滤器删掉:
修改后的Activity配置:
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTask" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- 移除NFC相关的intent-filter --> </activity>
2. 在目标页面动态注册NFC监听
只在需要NFC扫描的Fragment或Activity里,通过NfcAdapter动态开启和关闭监听,确保只有页面在前台时才检测标签。
举个Fragment的实现例子:
- 先初始化NFC相关实例:
private var nfcAdapter: NfcAdapter? = null private var pendingIntent: PendingIntent? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) nfcAdapter = NfcAdapter.getDefaultAdapter(requireContext()) // 创建PendingIntent,检测到标签时会把Intent发送给当前Activity pendingIntent = PendingIntent.getActivity( requireContext(), 0, Intent(requireContext(), MainActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) }
- 页面可见时开启监听:
override fun onResume() { super.onResume() nfcAdapter?.enableForegroundDispatch(requireActivity(), pendingIntent, null, null) }
- 页面不可见时关闭监听:
override fun onPause() { super.onPause() nfcAdapter?.disableForegroundDispatch(requireActivity()) }
- 处理扫描到的标签数据:
在宿主Activity的onNewIntent里接收NFC Intent,再传给对应的Fragment:
override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) if (NfcAdapter.ACTION_TAG_DISCOVERED == intent?.action) { // 找到当前显示的目标Fragment val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) if (currentFragment is YourTargetNFCFragment) { currentFragment.handleNfcTag(intent) } } }
然后在目标Fragment里加个方法处理标签内容:
fun handleNfcTag(intent: Intent) { val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) // 这里写处理标签的逻辑,比如读取NDEF数据等 }
3. 补充说明
- 动态注册的
enableForegroundDispatch只有在当前Activity处于前台时生效,页面退到后台或应用关闭时,监听会自动失效(我们也在onPause里手动注销了),这样就不会在应用关闭时触发NFC检测了。 - 如果需要过滤特定类型的NFC标签(比如NDEF格式、特定技术类型),可以在
enableForegroundDispatch的第三个和第四个参数里设置对应的过滤规则,实现更精准的扫描。
内容的提问来源于stack exchange,提问作者SenjaKids
相关产品推荐
相关产品推荐

