Most Android developers assume the app icon is a static asset defined at build time. However, providing users with the ability to change the app icon—whether for a 'Pro' theme, a seasonal event like Halloween, or personal preference—adds a layer of polish that sets high-quality apps apart. This isn't done by swapping a file; it is achieved by toggling the enabled state of an activity-alias.
Understanding the activity-alias
The activity-alias is a manifest element that points to an existing <activity>. By defining multiple aliases, each with its own android:icon and android:label, you can effectively present different 'entry points' to your application. Only one should be enabled at a time.
Step 1: Configure the Android Manifest
First, you need to define your main activity and then create aliases for it. Crucially, the main activity itself should usually have its intent-filter removed or be disabled by default if you rely entirely on aliases.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<!-- The actual Activity -->
<activity android:name=".MainActivity" android:exported="true" />
<!-- Default Icon Alias -->
<activity-alias
android:name=".MainActivityDefault"
android:enabled="true"
android:icon="@mipmap/ic_launcher_default"
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>
<!-- Premium Icon Alias -->
<activity-alias
android:name=".MainActivityPremium"
android:enabled="false"
android:icon="@mipmap/ic_launcher_premium"
android:label="Pro App"
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>
Step 2: Switching Icons Programmatically
To change the icon, you use the PackageManager to disable the current alias and enable the new one. This triggers the Android launcher to refresh the icon associated with your package.
fun changeAppIcon(context: Context, usePremium: Boolean) {
val pm = context.packageManager
val defaultAlias = ComponentName(context, "com.example.myapp.MainActivityDefault")
val premiumAlias = ComponentName(context, "com.example.myapp.MainActivityPremium")
if (usePremium) {
// Enable Premium, Disable Default
pm.setComponentEnabledSetting(premiumAlias, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
pm.setComponentEnabledSetting(defaultAlias, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
} else {
// Enable Default, Disable Premium
pm.setComponentEnabledSetting(defaultAlias, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
pm.setComponentEnabledSetting(premiumAlias, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
}
}
The Trade-offs
While powerful, this technique has a few side effects. When you call setComponentEnabledSetting, the Android system typically kills the app process to update the launcher. Even if you use the DONT_KILL_APP flag, the launcher itself may restart or close the app to reflect the UI change. It is best to perform this action during a settings change or a specific 'Success' screen rather than during active navigation.
Best Practices
Always ensure at least one alias is enabled, or your app will disappear from the user's app drawer entirely. Furthermore, avoid changing the icon too frequently, as constant launcher refreshes can frustrate users. Use this feature sparingly for meaningful customization like seasonal themes or achievement-based rewards.




