如何将NFC标签上的AAR重定向至新应用ID?适配问题排查
这个问题的核心在于Android Application Record(AAR)的优先级特性——系统处理NFC标签时会优先识别AAR记录,直接关联旧应用ID对应的应用,哪怕你的新应用配置了NDEF过滤器也会被跳过。下面给你几个可行的解决思路:
为什么当前配置不生效?
Android系统对带AAR的NFC标签有固定处理逻辑:
- 如果旧应用已安装,直接启动旧应用;
- 如果旧应用未安装,跳转到Play Store搜索该应用ID。
你的新应用配置的
NDEF_DISCOVERED过滤器优先级低于AAR,所以系统完全不会触发新应用的意图。
解决方案1:修改NFC标签内容(最推荐)
直接编辑NFC标签,把第二条AAR记录替换成新应用的AAR,或者直接移除AAR记录。这样系统扫描标签时,就会匹配你新应用中配置的NDEF_DISCOVERED过滤器(对应目标URL或旧MIME类型),直接启动新应用。
这是最彻底的解决办法,从根源上消除了旧AAR的干扰。
解决方案2:通过TECH_DISCOVERED绕过AAR限制(无法修改标签时用)
如果不能修改NFC标签,你可以利用TECH_DISCOVERED意图捕获标签,手动处理NDEF记录,绕过系统对AAR的默认处理:
1. 完善TECH_DISCOVERED的过滤器配置
确保res/xml/nfc_tech_filter.xml包含NDEF相关的NFC技术类型,覆盖常见的NFC标签制式:
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.NfcA</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcF</tech> <tech>android.nfc.tech.Ndef</tech> </tech-list> </resources>
2. 在SplashActivity中手动处理NFC意图
在Activity中重写onNewIntent()(配合singleTop启动模式),手动解析NDEF记录,判断是否是目标标签并拦截系统默认行为:
override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) if (NfcAdapter.ACTION_TECH_DISCOVERED == intent?.action) { val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) ?: return val ndef = Ndef.get(tag) if (ndef != null && ndef.isConnected) { try { val ndefMessage = ndef.cachedNdefMessage ndefMessage?.records?.forEach { record -> // 检查是否是目标URL记录 if (record.tnf == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.type, NdefRecord.RTD_URI)) { val url = NdefRecord.toUri(record.payload).toString() if (url.startsWith("http://website.com")) { // 在这里处理你的业务逻辑,比如打开新应用的对应页面 // 直接return阻止系统继续处理AAR return@forEach } } // 检查是否是旧应用的AAR记录 if (record.tnf == NdefRecord.TNF_EXTERNAL_TYPE && Arrays.equals(record.type, "android.com:pkg".toByteArray())) { val oldPackageId = String(record.payload, Charset.forName("UTF-8")) if (oldPackageId == "OLDAPPLICATIONID") { // 处理旧AAR对应的业务逻辑 return@forEach } } } } catch (e: Exception) { // 捕获读取标签的异常 } finally { ndef.close() } } } }
同时记得在Manifest中给SplashActivity设置android:launchMode="singleTop",避免重复创建实例,并且在onCreate()中也要处理首次启动时的NFC意图。
3. 权限补充
确保新应用已添加NFC相关权限:
<uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" />
额外说明
如果旧应用已经安装在设备上,系统还是会优先响应AAR启动旧应用——这种情况下,修改标签内容是唯一能完全避免旧应用启动的办法。如果无法修改标签,只能引导用户卸载旧应用,或者在新应用中做兼容处理。
内容的提问来源于stack exchange,提问作者Stéphane

