Android 13跨应用启动抛出ActivityNotFoundException问题求助
Android 13启动第三方应用抛出ActivityNotFoundException的解决方案
问题背景
使用Intent和PackageManager启动第三方应用的逻辑在Android 12及以下版本运行正常,但在Android 13中抛出如下异常:
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.app.globalfitanywhere/com.app.globalfitanywhere.view.activity.SplashActivity}; have you declared this activity in your AndroidManifest.xml, or does your intent not match its declared ?
已查阅官方文档了解到需匹配双方的IntentFilter,但对具体实现存在疑惑,以下是相关代码及解决方案:
相关代码展示
启动方核心代码
private fun prepareToLaunchApp(appPackage: String) { val isAppInstalled = appInstalledOrNot(appPackage) if (isAppInstalled) { val myAction: Uri = Uri.parse("https://$appPackage?emailId=${preference.email}")// need to change this to nutrition val packageManager = requireActivity().packageManager val intent = packageManager.getLaunchIntentForPackage(appPackage) if (intent != null) { intent.action = Intent.ACTION_VIEW intent.data = myAction startActivity(intent) } } else { shareApp(appPackage, requireActivity()) } }
启动方Manifest配置
<activity android:name=".ui.HomeActivity" android:screenOrientation="portrait" android:windowSoftInputMode="adjustResize" tools:ignore="LockedOrientationActivity" />
接收方Manifest配置
<activity android:name=".view.activity.SplashActivity" android:exported="true" android:screenOrientation="portrait" tools:ignore="LockedOrientationActivity" android:theme="@style/SplashScreen"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
接收方Intent处理代码
override fun onResume() { super.onResume() SharedPrefsManager.setString(GlobalKeys.UNIVERSAL_EMAIL_ID, "") val intent = intent val data1 = intent.data if (data1 != null) { val uri: Uri = Uri.parse(intent.dataString) emailId = uri.getQueryParameter("emailId").toString() SharedPrefsManager.setString(GlobalKeys.UNIVERSAL_EMAIL_ID, emailId) Log.e("###", "param userid==> $emailId") } }
解决方案
问题根源是Android 13收紧了隐式Intent的启动规则:修改getLaunchIntentForPackage返回的显式Intent的action和data后,该Intent变为隐式Intent,但接收方Activity没有对应的IntentFilter匹配此请求。
1. 给接收方Activity添加匹配的IntentFilter
在接收方SplashActivity的Manifest配置中,新增一个<intent-filter>来匹配你传递的ACTION_VIEW和Uri格式:
<activity android:name=".view.activity.SplashActivity" android:exported="true" android:screenOrientation="portrait" tools:ignore="LockedOrientationActivity" android:theme="@style/SplashScreen"> <!-- 原有启动器过滤器 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- 新增匹配ACTION_VIEW和自定义Uri的过滤器 --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <!-- 匹配你的Uri scheme和host(这里host是应用包名) --> <data android:scheme="https" android:host="com.app.globalfitanywhere" /> </intent-filter> </activity>
2. 优化启动方Intent构建逻辑(可选)
直接构建隐式Intent并指定目标包名,避免修改显式Intent带来的适配问题:
private fun prepareToLaunchApp(appPackage: String) { val isAppInstalled = appInstalledOrNot(appPackage) if (isAppInstalled) { val myAction: Uri = Uri.parse("https://$appPackage?emailId=${preference.email}") val intent = Intent(Intent.ACTION_VIEW, myAction) // 指定包名,避免系统弹出应用选择器 intent.setPackage(appPackage) // 提前判断是否有可处理的Activity,避免异常 if (intent.resolveActivity(requireActivity().packageManager) != null) { startActivity(intent) } } else { shareApp(appPackage, requireActivity()) } }
3. 关键注意事项
- 确保接收方Activity的
android:exported="true"(你的配置已满足) - 如果使用自定义Uri scheme(非https/http),需同步修改IntentFilter中的
android:scheme值 - Android 13中,隐式启动其他应用的Activity必须满足:目标Activity有匹配的IntentFilter且exported为true
内容的提问来源于stack exchange,提问作者harsh patel
相关产品推荐
相关产品推荐

