Have you ever noticed apps changing their launcher icons during holidays, special events, or promotional campaigns? A shopping application might switch to a festive holiday icon during Christmas, a sports app might brand itself for the World Cup, or a finance tool might offer an exclusive sleek icon for premium subscribers. The most impressive aspect of this mechanism is that users do not need to download an app update from the App Store or Google Play Store. The app simply toggles its active icon to another asset already bundled within the installation package.
In this comprehensive guide, we will explore what dynamic app icons are, why they are beneficial for user engagement, how native platforms support them, and a complete step-by-step technical implementation in React Native using the react-native-change-icon library.
What Are Dynamic App Icons?
Dynamic app icons allow an application to switch between multiple app icons that are already pre-bundled within the compiled build. Instead of releasing a full software update every time you want to refresh your branding, you programmatically instruct the host operating system (iOS or Android) to enable a different predefined icon asset.
THE WARDROBE ANALOGY
Think of dynamic icons like having several shirts in your wardrobe. You don't buy a brand-new shirt every single morning—you simply choose a different one from your existing collection depending on the occasion. Dynamic app icons operate on the exact same principle.
Why Use Dynamic App Icons?
- Seasonal Themes: Refresh your app's look for holidays such as Christmas, Halloween, New Year, Diwali, or Black Friday to keep the app feeling timely and active.
- Promotions & Campaigns: Promote limited-time events, flash sales, or badge discounts (e.g., "50% OFF") directly on the home screen without demanding an update.
- Premium Personalization: Provide paid subscribers or VIP users with exclusive, high-end app icons as a reward, enhancing perceived product value.
- Special Brand Events: Align icon visuals with real-time milestones like product launches, major sports tournaments, or company anniversaries.
How Does It Work Under the Hood?
While React Native does not natively expose dynamic icon APIs directly out of the box, both Android and iOS offer native OS-level capabilities to handle icon swapping:
-
iOS (
CFBundleAlternateIcons): iOS allows developers to define primary and alternate icons in theInfo.plistfile. The system usesUIApplication.shared.setAlternateIconName()to switch icons dynamically at runtime. -
Android (
Activity Aliases): Android achieves icon changing through<activity-alias>declarations inAndroidManifest.xml. Each alias points to the mainMainActivitybut specifies a differentandroid:iconasset. The native module enables one alias while disabling the others usingPackageManager.setComponentEnabledSetting().
Step-by-Step Implementation in React Native
We will use the popular react-native-change-icon library, which provides a clean JavaScript bridge over native iOS and Android icon APIs.
Step 1: Install the Library
Add the library to your React Native project using your preferred package manager:
# Using npm
npm install react-native-change-icon
# Or using Yarn
yarn add react-native-change-icon
# For iOS CocoaPods
cd ios && pod install && cd ..
Step 2: Prepare Your App Icon Assets
Because dynamic icons cannot be downloaded over the network at runtime, all icon variants must be created and bundled before compiling the app. Create all necessary dimensions for iOS (AppIcon sets) and Android (mipmap folders) for each variant:
- Default Icon: Standard primary app icon
- Christmas Icon: Holiday variant
- Dark Icon: Dark mode / AMOLED theme icon
- Premium Icon: Exclusive icon for paid members
- Sale Icon: Promotional variant
Step 3: Configure iOS (Info.plist)
Declare all alternate icons in your iOS project's Info.plist file under the CFBundleAlternateIcons dictionary key. Ensure the string names match the asset file names in Xcode:
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Christmas</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>ChristmasIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>Dark</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>DarkIcon</string>
</array>
</dict>
</dict>
</dict>
Step 4: Configure Android (AndroidManifest.xml)
In android/app/src/main/AndroidManifest.xml, define an <activity-alias> for each alternate icon. Each alias targets MainActivity:
<!-- Main Launcher Activity -->
<activity
android:name=".MainActivity"
android:exported="true">
</activity>
<!-- Alternate Icon Alias: Christmas -->
<activity-alias
android:name=".ChristmasAlias"
android:enabled="false"
android:icon="@mipmap/ic_launcher_christmas"
android:targetActivity=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
Step 5 & 6: Import & Change Icons Programmatically
Import the module into your JavaScript / TypeScript code and invoke the changeIcon method:
import ChangeIcon from "react-native-change-icon";
// Switch to Christmas icon
const enableChristmasIcon = async () => {
try {
const response = await ChangeIcon.changeIcon("Christmas");
console.log("Icon changed successfully:", response);
} catch (error) {
console.error("Failed to change icon:", error);
}
};
// Revert back to Default Icon
const resetToDefaultIcon = async () => {
await ChangeIcon.changeIcon(); // Passing empty parameter resets to default
};
Step 7: Tying Icon Swapping to Application Logic
Dynamically triggering icon updates based on state, context, or runtime properties gives this feature its power:
// Dynamic logic switch example
const updateAppIcon = async (user, theme, isHoliday) => {
if (isHoliday) {
await ChangeIcon.changeIcon("Christmas");
} else if (user.isPremium) {
await ChangeIcon.changeIcon("Premium");
} else if (theme === "dark") {
await ChangeIcon.changeIcon("Dark");
} else {
await ChangeIcon.changeIcon(); // Default
}
};
Step 8: Remote Management via Firebase Remote Config
Combining dynamic app icons with Firebase Remote Config (or any remote feature flagging service) allows total over-the-air branding control:
import remoteConfig from "@react-native-firebase/remote-config";
import ChangeIcon from "react-native-change-icon";
const syncRemoteIcon = async () => {
await remoteConfig().fetchAndActivate();
const remoteIconName = remoteConfig().getString("app_icon_key");
// Get current active icon to prevent unnecessary re-swaps
const currentIcon = await ChangeIcon.getIcon();
if (remoteIconName && remoteIconName !== currentIcon) {
await ChangeIcon.changeIcon(remoteIconName);
}
};
KEY ADVANTAGE
Updating theapp_icon_keyparameter in the Firebase console instantaneously shifts the app icon for all targeted users the next time their app fetches configuration—zero store reviews or updates required!
Important Caveats & Best Practices
- Pre-bundled Requirement: Dynamic icon updates are limited strictly to assets compiled into the app binary. You cannot download image URLs at runtime and set them as icons.
- Avoid Rapid Swapping: Changing app icons too frequently can confuse users who are searching for your app on their home screen. Reserve icon changes for meaningful events, holidays, or explicit user settings.
- Platform Differences & OS Alerts: iOS often displays a native system prompt informing the user that the app icon has changed. Android may briefly close or refresh the launcher task when an activity-alias is toggled.
- Brand Consistency: Maintain key brand elements (like logo silhouettes or core colors) across all custom icons so users can still identify your app instantly.
- Thorough Testing: Test every alternate icon configuration across both platforms on physical devices. Verify persistence after app restarts and phone reboots.
Conclusion
Dynamic app icons offer a refined, impactful way to keep your React Native app fresh, engaging, and context-aware. By combining pre-bundled native icon assets with react-native-change-icon and remote configuration services, you gain full control over your app's home screen presence—delivering timely visual experiences without forcing users through app store update cycles.
Top comments (0)