Android使用<activity-alias>切换应用图标触发ActivityNotFoundException
问题描述
我在Android应用里做了会员图标切换逻辑:用户是premium或semi-premium会员时调用changeIconToPremium()切换金色图标,非会员调用changeIconToDefault()切回默认图标。但运行时一直抛出ActivityNotFoundException,提示找不到com.fireframe.noxwallpapers.MainActivity。我的应用启动页是SplashScreen,切换图标后还是要以它作为启动页,求修复。
错误信息
FATAL EXCEPTION: main Process: com.fireframe.noxwallpapers, PID: 18833 android.content.ActivityNotFoundException: Unable to find explicit activity class {com.fireframe.noxwallpapers/com.fireframe.noxwallpapers.MainActivity}; have you declared this activity in your AndroidManifest.xml, or does your intent not match its declared <intent-filter>? at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2249) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1878) at android.app.Activity.startActivityForResult(Activity.java:5743) at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:780) at android.app.Activity.startActivityForResult(Activity.java:5701) at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:761) at android.app.Activity.startActivity(Activity.java:6199) at android.app.Activity.startActivity(Activity.java:6166) at com.fireframe.noxwallpapers.SplashScreen.endSplash$lambda$0(SplashScreen.kt:151) at com.fireframe.noxwallpapers.SplashScreen.$r8$lambda$L59SC2q6eERHvWVIWOUzibvW7Lg(Unknown Source:0) at com.fireframe.noxwallpapers.SplashScreen$$ExternalSyntheticLambda0.run(Unknown Source:2) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:230) at android.os.Looper.loop(Looper.java:319) at android.app.ActivityThread.main(ActivityThread.java:8893) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
原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.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.SET_WALLPAPER" /> <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> <uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <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.NoxWallpapers" tools:replace="android:fullBackupContent" tools:targetApi="31"> <!-- Launcher activity --> <activity android:name=".SplashScreen" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- MainActivity --> <activity android:name="com.fireframe.noxwallpapers.MainActivity" android:exported="false" android:label="@string/app_name" android:screenOrientation="portrait"> <!-- No need for category DEFAULT in the intent-filter --> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <!-- MainActivityPremium alias --> <activity-alias android:name="com.fireframe.noxwallpapers.MainActivityPremium" android:enabled="false" android:exported="false" android:icon="@mipmap/ic_golden_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_golden_launcher_round" android:targetActivity="com.fireframe.noxwallpapers.MainActivity"> <!-- No need for category DEFAULT in the intent-filter --> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity-alias> <!-- 其他Activity和Service配置省略 --> </application> </manifest>
原MainActivity相关代码
//Admob //initializing if ((subPerfHelper.getStatus() == "premium") || (subPerfHelper.getStatus() == "semi-premium")) { binding.bannerAd1.visibility = View.GONE if (subPerfHelper.getIconStatus() == "default"){ changeIconToPremium() subPerfHelper.setIconStatus("premium") } } else { if (subPerfHelper.getIconStatus() == "premium"){ changeIconToDefault() subPerfHelper.setIconStatus("default") } MobileAds.initialize(this) {} // banner ads val adRequest = AdRequest.Builder().build() binding.bannerAd1.loadAd(adRequest) binding.bannerAd1.adListener = object : AdListener() { override fun onAdFailedToLoad(adError: LoadAdError) { binding.bannerAd1.visibility = View.GONE } override fun onAdLoaded() { binding.bannerAd1.visibility = View.VISIBLE } } } private fun changeIconToPremium() { //Disable default icon val packageManager = packageManager packageManager.setComponentEnabledSetting( ComponentName(this,"com.fireframe.noxwallpapers.MainActivity"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ) //Enable golden icon packageManager.setComponentEnabledSetting( ComponentName(this,"com.fireframe.noxwallpapers.MainActivityPremium"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) } private fun changeIconToDefault() { //Disable golden icon val packageManager = packageManager packageManager.setComponentEnabledSetting( ComponentName(this,"com.fireframe.noxwallpapers.MainActivityPremium"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ) //Enable default icon packageManager.setComponentEnabledSetting( ComponentName(this,"com.fireframe.noxwallpapers.MainActivity"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) }
修复方案
问题根源
你之前错误地把图标切换逻辑绑定到了MainActivity上,切换时直接禁用了MainActivity组件,导致SplashScreen跳转时找不到MainActivity。而且Android的应用图标对应的是带有LAUNCHER intent-filter的组件,正确的做法是给启动页SplashScreen创建别名,而不是后续的MainActivity。
步骤1:修改AndroidManifest.xml
给SplashScreen创建两个activity-alias,分别对应默认图标和金色会员图标,把原SplashScreen的LAUNCHER过滤移到默认别名中:
<!-- 基础启动页Activity,不带LAUNCHER过滤 --> <activity android:name=".SplashScreen" android:exported="true"/> <!-- 默认图标启动别名(默认启用) --> <activity-alias android:name=".SplashScreenDefault" android:enabled="true" android:exported="true" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:targetActivity=".SplashScreen"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <!-- 金色会员图标启动别名(默认禁用) --> <activity-alias android:name=".SplashScreenPremium" android:enabled="false" android:exported="true" android:icon="@mipmap/ic_golden_launcher" android:roundIcon="@mipmap/ic_golden_launcher_round" android:targetActivity=".SplashScreen"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <!-- MainActivity保持原样,移除多余的intent-filter --> <activity android:name="com.fireframe.noxwallpapers.MainActivity" android:exported="false" android:label="@string/app_name" android:screenOrientation="portrait"> </activity>
步骤2:修改MainActivity中的图标切换方法
现在操作SplashScreen的两个别名,不再动MainActivity:
private fun changeIconToPremium() { val packageManager = packageManager // 禁用默认图标别名 packageManager.setComponentEnabledSetting( ComponentName(this, "com.fireframe.noxwallpapers.SplashScreenDefault"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ) // 启用金色会员图标别名 packageManager.setComponentEnabledSetting( ComponentName(this, "com.fireframe.noxwallpapers.SplashScreenPremium"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) } private fun changeIconToDefault() { val packageManager = packageManager // 禁用金色会员图标别名 packageManager.setComponentEnabledSetting( ComponentName(this, "com.fireframe.noxwallpapers.SplashScreenPremium"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ) // 启用默认图标别名 packageManager.setComponentEnabledSetting( ComponentName(this, "com.fireframe.noxwallpapers.SplashScreenDefault"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) }
步骤3:验证SplashScreen跳转逻辑
确保SplashScreen跳转到MainActivity的代码正常,示例:
// SplashScreen.kt中跳转代码 private fun endSplash() { Handler(Looper.getMainLooper()).postDelayed({ startActivity(Intent(this, MainActivity::class.java)) finish() }, 2000) // 根据你的需求调整延迟时间 }
内容的提问来源于stack exchange,提问作者ManavPatni
相关产品推荐
相关产品推荐

