
本文介绍如何利用 Android 的 机制,在运行时动态切换应用启动图标与名称,无需重启应用或重新安装,适用于多品牌、多主题或用户个性化场景。
本文介绍如何利用 android 的 `
在 Android 中,应用的启动图标和名称由 AndroidManifest.xml 中声明的 LAUNCHER Activity 决定。由于系统仅允许一个默认启动入口,若需实现「运行时动态切换图标」,不能直接修改 android:icon 或 android:label 属性(这些属性在编译期固化),而应采用 Activity Alias + PackageManager 启用/禁用控制 的标准方案。
✅ 核心原理
为同一目标 Activity(如 .SplashActivity 或 .MainActivity)定义多个 <activity-alias></activity-alias>,每个 alias 拥有独立的 android:icon、android:label、android:roundIcon 和唯一 android:name;再通过 PackageManager.setComponentEnabledSetting() 动态启用目标 alias,同时禁用其他 alias —— 系统 Launcher 将自动刷新显示对应图标。
? 正确的 Manifest 配置示例
在 AndroidManifest.xml 中,为同一个主 Activity 声明多个 alias(注意:android:enabled="false" 初始禁用,避免冲突):
<activity
android:name=".SplashActivity"
android:exported="true"
android:theme="@style/Theme.App.Starting">
<!-- 主 Activity 不带 intent-filter,不作为 Launcher -->
</activity>
<!-- Icon 1 alias -->
<activity-alias
android:name=".SplashActivityAlias1"
android:targetActivity=".SplashActivity"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher_1"
android:roundIcon="@mipmap/ic_launcher_1_round"
android:label="App Name Variant A">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<!-- Icon 2 alias -->
<activity-alias
android:name=".SplashActivityAlias2"
android:targetActivity=".SplashActivity"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher_2"
android:roundIcon="@mipmap/ic_launcher_2_round"
android:label="App Name Variant B">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>⚠️ 注意事项:
Android Adb Skill下载Android 开发调试技能,通过系统 ADB 工具操作 Android 设备。以下场景必须触发此技能:(1) 直接 ADB 操作——安装 APK、查看设备列表、抓取 logcat 日志、查看已安装应用、清除应用数据、截图、重启设备、拉取/推送文件、查看 CPU/内存/电池信息、adb shell 操作;(2)...
- 所有 alias 必须设置
android:exported="true"(Android 12+ 强制要求);android:targetActivity必须是已声明且exported="true"的 Activity;- 图标资源(
@mipmap/...)需提前放入res/mipmap-*目录;- 初始状态建议全部设为
android:enabled="false",首次启动时由代码显式启用一个。
? 运行时切换逻辑(Kotlin 示例)
在按钮点击事件中,调用 PackageManager 控制组件状态:
private fun switchToIcon1() {
val pm = packageManager
val packageName = packageName
// 启用目标 alias,禁用其余
pm.setComponentEnabledSetting(
ComponentName(packageName, "$packageName.SplashActivityAlias1"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
ComponentName(packageName, "$packageName.SplashActivityAlias2"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
private fun switchToIcon2() {
val pm = packageManager
val packageName = packageName
pm.setComponentEnabledSetting(
ComponentName(packageName, "$packageName.SplashActivityAlias1"),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
ComponentName(packageName, "$packageName.SplashActivityAlias2"),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
}✅ 切换后,用户需手动下拉并刷新桌面(部分 Launcher 如 Nova、Microsoft Launcher 支持即时更新;原生 Pixel Launcher 可能需长按图标 → “App info” → 返回后生效),但无需重启 App 或设备。
? 总结
该方案完全符合 Android 官方设计规范,安全、稳定、无反射风险。它不依赖任何第三方库,兼容 Android 5.0(API 21)及以上版本。关键在于:所有图标变体均预置在 APK 中,仅通过 PackageManager 动态开关其可见性,既满足动态需求,又规避了权限与签名限制。实际项目中,可结合 SharedPreferences 持久化用户选择,确保下次冷启动时恢复上次图标配置。


















