Android Kotlin NFC标签无法被应用读取,请求技术支持
1. 修正TECH_DISCOVERED的Intent Filter配置
你的AndroidManifest.xml中仅添加了TECH_DISCOVERED的meta-data,但缺少对应的intent-filter声明,导致系统无法将TECH_DISCOVERED的Intent路由到你的Activity。需要补充:
<intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>
同时,nfc_tech_filter.xml将多个NFC技术放在同一个<tech-list>下,这要求标签同时支持所有列出的技术才会触发——但NfcA和NfcB是互斥的标准(一个标签只会支持其中一种),所以需要拆分为独立的tech-list:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcA</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> </tech-list> </resources>
2. 添加TAG_DISCOVERED作为兜底Intent Filter
如果标签不包含NDEF数据,或者数据格式不匹配你的NDEF_DISCOVERED过滤规则,系统会优先调用内置NFC应用。添加TAG_DISCOVERED的Intent Filter可以捕获所有未被更具体规则匹配的NFC标签:
<intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>
3. 启用前台调度系统(Foreground Dispatch)
当应用处于前台时,启用前台调度可确保系统优先将NFC Intent发送到你的应用,而非跳转至系统内置功能。在MainActivity中添加以下代码:
override fun onResume() { super.onResume() nfcAdapter?.let { adapter -> val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) adapter.enableForegroundDispatch(this, pendingIntent, null, null) } } override fun onPause() { super.onPause() nfcAdapter?.disableForegroundDispatch(this) }
注:Android 12及以上需使用PendingIntent.FLAG_MUTABLE(NFC场景通常需要该标记)。
4. 验证标签的NDEF数据格式
你的NDEF_DISCOVERED过滤规则仅匹配text/plain类型的MIME数据,如果标签中的NDEF记录是其他类型(如URI、自定义MIME),则不会触发你的Intent Filter。可通过第三方NFC工具查看标签具体数据格式,调整过滤规则以匹配。
5. 完善Intent处理逻辑
虽然已设置singleTop,但需确保在onCreate中也处理初始Intent(比如应用刚启动时就检测到NFC标签的情况):
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) nfcAdapter = NfcAdapter.getDefaultAdapter(this) // 处理启动时的NFC Intent handleNfcIntent(intent) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) setIntent(intent) // 更新当前Intent handleNfcIntent(intent) } private fun handleNfcIntent(intent: Intent?) { intent ?: return Log.d("CHKI", "NEW NFC DETECTED") when (intent.action) { NfcAdapter.ACTION_NDEF_DISCOVERED -> Log.d("CHKI", "ACTION_NDEF_DISCOVERED") NfcAdapter.ACTION_TECH_DISCOVERED -> Log.d("CHKI", "ACTION_TECH_DISCOVERED") NfcAdapter.ACTION_TAG_DISCOVERED -> Log.d("CHKI", "ACTION_TAG_DISCOVERED") } }
内容的提问来源于stack exchange,提问作者ankushlokhande

