Unity开发Android应用:动态更换图标重复问题求助
Android动态换图标重复问题解决方法
问题现象
开发Android动态换图标功能时,切换到自定义图标(非默认)会出现桌面图标重复,仅切换回默认图标时显示正常。已尝试清理缓存、重启设备,给MainActivity添加LAUNCHER intent-filter后问题仍存在。
核心原因
桌面图标重复的本质是同一应用中存在多个启用状态的带有android.intent.category.LAUNCHER的组件:
- 切换到自定义别名时,MainActivity(若添加了LAUNCHER过滤)和目标activity-alias同时处于启用状态,两个组件都会被桌面识别为启动入口,导致重复图标;
- 切换回MainActivity时,其他别名被禁用,只有MainActivity的LAUNCHER有效,所以显示正常。
解决方案
1. 修正AndroidManifest.xml配置
将默认图标的LAUNCHER intent-filter从MainActivity移到单独的activity-alias中,确保所有启动入口都通过activity-alias管理,同一时间仅启用一个:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:label="@string/app_name" android:supportsRtl="true"> <!-- 主Activity,移除LAUNCHER过滤 --> <activity android:name=".MainActivity" android:exported="true"> </activity> <!-- 默认图标别名,默认启用 --> <activity-alias android:name=".DefaultLauncherAlias" android:enabled="true" android:exported="true" android:icon="@mipmap/ic_launcher" <!-- 替换为你的默认图标 --> android:label="@string/app_name" android:targetActivity=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <!-- 自定义图标别名,默认禁用 --> <activity-alias android:name=".OneLauncherAlias" android:enabled="false" android:exported="true" android:icon="@drawable/testicon_1" android:label="@string/app_name" android:targetActivity=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:name=".TwoLauncherAlias" android:enabled="false" android:exported="true" android:icon="@drawable/testicon_2" android:label="@string/app_name" android:targetActivity=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> <activity-alias android:name=".ThreeLauncherAlias" android:enabled="false" android:exported="true" android:icon="@drawable/testicon_3" android:label="@string/app_name" android:targetActivity=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity-alias> </application> </manifest>
2. 修正MainActivity的ChangeIcon方法
确保每次切换时仅启用目标组件,其余所有带有LAUNCHER的组件(包括默认别名)都被禁用,同时优化代码避免重复创建ComponentName:
public class MainActivity extends AppCompatActivity { private static MainActivity instance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); instance = this; // 其他初始化逻辑 } public static MainActivity getInstance() { return instance; } public void ChangeIcon(Context context, String[] iconList, String iconType) { PackageManager manager = context.getPackageManager(); for (String componentNameStr : iconList) { int actionType = componentNameStr.equals(iconType) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; ComponentName componentName = new ComponentName(context, String.format("%s.%s", getPackageName(), componentNameStr)); manager.setComponentEnabledSetting(componentName, actionType, PackageManager.DONT_KILL_APP); } } public void ShowToast(Context context, String message) { Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } }
3. 修正Unity端TestScript代码
更新IconTypeArr,替换原来的MainActivity为默认别名DefaultLauncherAlias:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class TestScript : MonoBehaviour { public Button _toast; public Button _main; public Button _appIcon01; public Button _appIcon02; public Button _appIcon03; private AndroidJavaObject activityContext = null; private AndroidJavaClass javaClass = null; private AndroidJavaObject javaClassInstance = null; // 更新数组,用默认别名代替MainActivity private string[] IconTypeArr = { "DefaultLauncherAlias", "OneLauncherAlias", "TwoLauncherAlias", "ThreeLauncherAlias" }; private void Awake() { using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity"); } using (javaClass = new AndroidJavaClass("com.test.testApp.player.MainActivity")) { if (javaClass != null) { javaClassInstance = javaClass.CallStatic<AndroidJavaObject>("getInstance"); } } _toast.onClick.AddListener(OnClickToast); _main.onClick.AddListener(OnClickChangeAppIcon_Main); _appIcon01.onClick.AddListener(OnClickChangeAppIcon_1); _appIcon02.onClick.AddListener(OnClickChangeAppIcon_2); _appIcon03.onClick.AddListener(OnClickChangeAppIcon_3); } private void OnClickToast() { javaClassInstance.Call("ShowToast", activityContext, "测试Toast消息输出 ^^"); } private void OnClickChangeAppIcon_Main() { javaClassInstance.Call("ChangeIcon", activityContext, IconTypeArr, "DefaultLauncherAlias"); javaClassInstance.Call("ShowToast", activityContext, "切换为默认图标"); } private void OnClickChangeAppIcon_1() { javaClassInstance.Call("ChangeIcon", activityContext, IconTypeArr, "OneLauncherAlias"); javaClassInstance.Call("ShowToast", activityContext, "切换为自定义图标1"); } private void OnClickChangeAppIcon_2() { javaClassInstance.Call("ChangeIcon", activityContext, IconTypeArr, "TwoLauncherAlias"); javaClassInstance.Call("ShowToast", activityContext, "切换为自定义图标2"); } private void OnClickChangeAppIcon_3() { javaClassInstance.Call("ChangeIcon", activityContext, IconTypeArr, "ThreeLauncherAlias"); javaClassInstance.Call("ShowToast", activityContext, "切换为自定义图标3"); } }
验证步骤
- 卸载旧版本应用,重新安装修改后的包(避免缓存残留);
- 测试切换各个图标,检查桌面是否仅显示一个图标;
- 若仍有问题,进入应用信息页面,清理缓存和数据后重启设备再测试。
内容的提问来源于stack exchange,提问作者TOMOU
相关产品推荐
相关产品推荐

