Change App Icon Dynamically in Android App
Overview
Have you ever noticed how apps like VLC, Zomato, Blinkit, or Zepto suddenly change their app icons during festive seasons like Diwali, Holi, or Christmas? It’s a small but powerful detail that instantly grabs attention. This kind of visual transformation not only enhances user engagement but also adds a sense of freshness and relevance to the app experience.
As developers, it naturally sparks our curiosity: “How are they changing the app icon without updating the app?” The ability to dynamically switch your app icon allows you to celebrate festivals, highlight campaigns, or reflect a user’s personal choice - all without pushing an app update.
In this article, we’ll explore how to implement dynamic icon switching in Android using native tools like activity-alias
, giving your app a festive flair - like a Christmas VLC icon - and keeping your users intrigued every time they unlock their phones.
πΉ What is activity-alias?
activity-alias
is a special Android manifest component that acts as an alternate name and icon for an existing activity (usually your launcher activity). You can define multiple aliases pointing to the same activity but with different icons or labels.
πΉ How It Helps with Icon Switching
By defining multiple activity-alias
entries (each with a unique icon), you can enable one and disable the others at runtime using PackageManager
. Only the enabled alias appears in the launcher as your app's icon.
- π Change the app icon based on festivals or seasons (e.g., Diwali, Christmas).
- π€ Offer personalized icon themes (e.g., Light vs. Dark).
- π£ Promote limited-time campaigns without needing a Play Store update.
Key Features Table
Feature | Description |
---|---|
π Festive Icon Switching | Change app icon to a Christmas VLC theme using activity-alias . |
π Scheduled Holiday Updates | Use AlarmManager to switch icons on Christmas Day. |
π€ User-Driven Themes | Allow users to toggle between normal and Christmas VLC icons. |
Implementation Steps
In this code, we’ve created a simple UI with normal and Christmas VLC icon previews and a switch to toggle between them - just like how Zomato and Zepto change icons for events.
If you want your app to automatically switch its launcher icon during festivals like Diwali, Holi, or Christmas, you can achieve this cleanly using Android’s AlarmManager
. AlarmManager
allows you to schedule a task to be executed at a specific date and time, even if your app is not actively running.
This makes it perfect for triggering an icon change exactly on a festival day - without requiring user interaction.
Step 1: Define activity-alias in AndroidManifest.xml
Create alternate launcher entries for normal and Christmas VLC icons.
<!-- Normal VLC Icon (Enabled by Default) -->
<activity-alias
android:name=".DefaultVLC"
android:enabled="true"
android:exported="true"
android:icon="@mipmap/ic_vlc_launcher"
android:roundIcon="@mipmap/ic_vlc_launcher_round"
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>
<!-- Christmas VLC Icon (Initially Disabled) -->
<activity-alias
android:name=".ChristmasVLC"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_vlc_christmas_launcher"
android:roundIcon="@mipmap/ic_vlc_christmas_launcher_round"
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>
Step 2: Set Up Main Activity
Create the main activity to host the Jetpack Compose UI for icon switching.
package com.boltuix.iconchanger
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import com.boltuix.iconchanger.ui.theme.IconChangerTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
IconChangerTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
HomeScreen()
}
}
}
}
}
Step 3: Create Festive UI with Jetpack Compose
Build a UI with normal and Christmas VLC icon previews and a toggle switch.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen() {
val context = LocalContext.current
var isDefaultSelected by remember { mutableStateOf(true) }
Scaffold(
topBar = {
TopAppBar(
title = {
Text(
"VLC Icon Switcher",
style = TextStyle(textAlign = TextAlign.Center),
modifier = Modifier.fillMaxWidth()
)
}
)
}
) { paddingValues ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
// Normal VLC Icon Preview
Image(
painter = painterResource(id = R.drawable.vlc_default),
contentDescription = "Normal VLC Icon",
modifier = Modifier
.align(Alignment.CenterStart)
.size(100.dp)
)
// Christmas VLC Icon Preview
Image(
painter = painterResource(id = R.drawable.vlc_christmas),
contentDescription = "Christmas VLC Icon",
modifier = Modifier
.align(Alignment.CenterEnd)
.size(100.dp)
)
// Switch Toggle
Column(
modifier = Modifier.align(Alignment.Center),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = if (isDefaultSelected) "Normal VLC Icon" else "Christmas VLC Icon"
)
Switch(
checked = isDefaultSelected,
onCheckedChange = {
isDefaultSelected = it
if (isDefaultSelected) {
// Enable default, disable special
switchIcon("DefaultVLC", "ChristmasVLC", context)
} else {
// Enable special, disable default
switchIcon("ChristmasVLC", "DefaultVLC", context)
}
}
)
}
}
}
}
Step 4: Switch Icons with PackageManager
Enable the desired activity-alias
to update the launcher icon.
private fun switchIcon(enableAlias: String, disableAlias: String, context: Context) {
val pm = context.packageManager
val enableComponent = ComponentName(context, "com.boltuix.iconchanger.$enableAlias")
val disableComponent = ComponentName(context, "com.boltuix.iconchanger.$disableAlias")
pm.setComponentEnabledSetting(
enableComponent,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
disableComponent,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
Step 5: Schedule π Christmas Icon Change (Optional)
Use AlarmManager
to automatically switch to the Christmas VLC icon on December 25th.
Schedule tasks to trigger icon changes without user interaction, ensuring timely festive updates.
π Full Source Code
Below is the complete source code for the dynamic icon switching app, combining all steps into a single implementation.
AndroidManifest.xml
<?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:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_vlc_launcher"
android:roundIcon="@mipmap/ic_vlc_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.IconChanger"
tools:targetApi="31">
<!-- Base MainActivity (used by all aliases) -->
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.IconChanger" />
<!-- Normal VLC Icon (Enabled by Default) -->
<activity-alias
android:name=".DefaultVLC"
android:enabled="true"
android:exported="true"
android:icon="@mipmap/ic_vlc_launcher"
android:roundIcon="@mipmap/ic_vlc_launcher_round"
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>
<!-- Christmas VLC Icon (Initially Disabled) -->
<activity-alias
android:name=".ChristmasVLC"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_vlc_christmas_launcher"
android:roundIcon="@mipmap/ic_vlc_christmas_launcher_round"
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>
MainActivity.kt
package com.boltuix.iconchanger
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.boltuix.iconchanger.ui.theme.IconChangerTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
IconChangerTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
HomeScreen()
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen() {
val context = LocalContext.current
var isDefaultSelected by remember { mutableStateOf(true) }
Scaffold(
topBar = {
TopAppBar(
title = {
Text(
"VLC Icon Switcher",
style = TextStyle(textAlign = TextAlign.Center),
modifier = Modifier.fillMaxWidth()
)
}
)
}
) { paddingValues ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
// Normal VLC Icon Preview
Image(
painter = painterResource(id = R.drawable.vlc_default),
contentDescription = "Normal VLC Icon",
modifier = Modifier
.align(Alignment.CenterStart)
.size(100.dp)
)
// Christmas VLC Icon Preview
Image(
painter = painterResource(id = R.drawable.vlc_christmas),
contentDescription = "Christmas VLC Icon",
modifier = Modifier
.align(Alignment.CenterEnd)
.size(100.dp)
)
// Switch Toggle
Column(
modifier = Modifier.align(Alignment.Center),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = if (isDefaultSelected) "Normal VLC Icon" else "Christmas VLC Icon"
)
Switch(
checked = isDefaultSelected,
onCheckedChange = {
isDefaultSelected = it
if (isDefaultSelected) {
// Enable default, disable special
switchIcon("DefaultVLC", "ChristmasVLC", context)
} else {
// Enable special, disable default
switchIcon("ChristmasVLC", "DefaultVLC", context)
}
}
)
}
}
}
}
/**
* This function enables one icon alias and disables the other.
* The launcher icon gets switched without killing the app.
*
* @param enableAlias The component name to enable (e.g., "DefaultVLC")
* @param disableAlias The component name to disable (e.g., "ChristmasVLC")
* @param context The application context
*/
private fun switchIcon(enableAlias: String, disableAlias: String, context: Context) {
val pm = context.packageManager
val enableComponent = ComponentName(context, "com.boltuix.iconchanger.$enableAlias")
val disableComponent = ComponentName(context, "com.boltuix.iconchanger.$disableAlias")
pm.setComponentEnabledSetting(
enableComponent,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
disableComponent,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
FAQ
π Which Android versions support dynamic icon switching?
activity-alias
is supported on Android 4.4 (API 19) and above, covering nearly all modern devices.
π Does AlarmManager require special permissions for scheduling?
No, basic AlarmManager
usage for icon switching needs no additional permissions, but ensure exact timing for reliability.
π€ Will the icon change reflect instantly for users?
Yes, the change is immediate, but some launchers may require a restart or refresh to display the new icon.
π£ Can I support multiple festive icons?
Yes, add more activity-alias
entries for festivals like Diwali or Holi and toggle them as needed.
Community Feedback
Have you implemented dynamic icon switching for holidays or campaigns? Share your tips, fixes, or alternative approaches in the comments to help the Android community. We’ll update this guide with your feedback!
Join Reddit to get more updates like this.