@praneeth26/expo-dynamic-app-identity
v1.1.1
Published
Comprehensive Expo plugin for dynamic app icon and label switching. Features: DEFAULT alias support, deep link migration, app label switching, immediate switch, toast feedback, and adaptive icon support.
Maintainers
Readme
@praneeth26/expo-dynamic-app-identity
A comprehensive Expo plugin for dynamic app icon and label switching with production-ready features and fixes.
🎯 Why This Plugin?
This plugin provides a production-ready solution for dynamic app icon and label switching with comprehensive fixes:
| # | Feature | Status |
|---|---------|--------|
| 1 | DEFAULT alias support | ✅ Creates MainActivityDEFAULT alias to prevent crashes |
| 2 | Deep link migration | ✅ Automatically migrates all intent filters to aliases |
| 3 | App label switching | ✅ Supports label property per icon (Android) |
| 4 | Immediate switch | ✅ Supports immediate switching (no forced delay) |
| 5 | Toast feedback | ✅ Native toast notifications (Android) |
| 6 | Adaptive icons | ✅ Full support for Android adaptive icons |
| 7 | iOS dark mode | ✅ Support for light/dark/tinted icon variants (iOS 18+) |
| 8 | Label-only mode | ✅ Change app name without changing icon |
| 9 | Safe switching | ✅ Enable-first, disable-second ordering prevents crashes |
📦 Installation
npm install @praneeth26/expo-dynamic-app-identity
# or
yarn add @praneeth26/expo-dynamic-app-identityAfter installation, configure the plugin in your app.json (see Configuration section below), then run:
npx expo prebuild --cleanThis generates the native code with the dynamic icon configuration.
⚙️ Configuration
Add the plugin to your app.json or app.config.js:
Standard Format (with icons wrapper)
{
"expo": {
"plugins": [
[
"@praneeth26/expo-dynamic-app-identity",
{
"icons": {
"premium": {
"image": "./assets/icons/premium.png",
"label": "MyApp Premium"
},
"dark": {
"image": "./assets/icons/dark.png",
"label": "MyApp Dark"
},
"holiday": {
"image": "./assets/icons/holiday.png"
}
}
}
]
]
}
}Simplified Format (without icons wrapper)
The plugin also supports a simplified format where icon definitions are at the root level:
{
"expo": {
"plugins": [
[
"@praneeth26/expo-dynamic-app-identity",
{
"icon1": {
"android": "./assets/resources/assets/icon.png",
"ios": "./assets/resources/assets/icon.png",
"prerendered": true
},
"icon2": {
"android": "./assets/resources/assets/splash-icon.png",
"ios": "./assets/resources/assets/splash-icon.png",
"prerendered": true
},
"icon3": {
"android": "./assets/resources/assets/icon4.png",
"ios": "./assets/resources/assets/icon4.png",
"prerendered": true
}
}
]
]
}
}Both formats are fully supported and will be automatically normalized by the plugin.
Label-Only Mode (Android)
If you only want to change the app name without changing the icon:
{
"icons": {
"enterprise": {
"label": "MyApp Enterprise"
}
}
}Note: When no image is provided, the default app icon is used.
iOS Dark Mode Icons (iOS 18+)
Support for light/dark/tinted icon variants:
{
"icons": {
"themed": {
"ios": {
"light": "./assets/icons/light.png",
"dark": "./assets/icons/dark.png",
"tinted": "./assets/icons/tinted.png"
},
"android": "./assets/icons/android.png",
"label": "MyApp Themed"
}
}
}Android Adaptive Icons
Full support for Android adaptive icons:
{
"icons": {
"adaptive": {
"android": {
"foregroundImage": "./assets/icons/foreground.png",
"backgroundColor": "#FF5722"
},
"ios": "./assets/icons/ios.png",
"label": "MyApp Adaptive"
}
}
}Platform-Specific Icons (Advanced)
Multiple formats are supported:
{
"icons": {
"dark": {
"image": "./assets/icons/dark.png",
"androidImage": "./assets/icons/dark-android.png",
"iosImage": "./assets/icons/dark-ios.png"
}
}
}Configuration Options
Icon Configuration
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| image | string | ❌ | Path to icon image (used for both platforms) |
| ios | string | object | ❌ | iOS icon - string or { light, dark, tinted } |
| android | string | object | ❌ | Android icon - string or { foregroundImage, backgroundColor } |
| iosImage | string | ❌ | iOS-specific icon path (alternative to ios) |
| androidImage | string | ❌ | Android-specific icon path (alternative to android) |
| label | string | ❌ | App name to display (Android only) |
| prerendered | boolean | ❌ | iOS prerendered icon (default: true) |
Format Compatibility
This plugin supports multiple configuration formats for flexibility:
// Simple format
{ "image": "./icon.png", "label": "MyApp" }
// Platform-specific
{ "iosImage": "./ios.png", "androidImage": "./android.png" }
// Full format
{ "ios": "./icon.png", "android": "./icon.png" }
{ "ios": { "light": "...", "dark": "...", "tinted": "..." } }
{ "android": { "foregroundImage": "...", "backgroundColor": "#fff" } }Runtime Options
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| showToast | boolean | true | Show toast after switching (Android only) |
| immediate | boolean | true | Switch immediately (false = wait for background on Android) |
| delay | number | 5000 | Delay in milliseconds before switching when immediate=false (Android only) |
🚀 Usage
Basic Usage
import { setAppIdentity, getAppIdentity } from '@praneeth26/expo-dynamic-app-identity';
// Switch to a named icon
await setAppIdentity('premium');
// Switch back to default
await setAppIdentity(null);
// or
await setAppIdentity('DEFAULT');
// Get current icon
const currentIcon = getAppIdentity();
console.log(currentIcon); // 'premium' or 'DEFAULT'Advanced Usage
import {
setAppIdentity,
getAppIdentity,
getAvailableIcons
} from '@praneeth26/expo-dynamic-app-identity';
// Switch without toast notification
await setAppIdentity('premium', { showToast: false });
// Switch when app goes to background (legacy behavior)
await setAppIdentity('premium', { immediate: false });
// Switch with custom delay (3 seconds instead of default 5)
await setAppIdentity('premium', { immediate: false, delay: 3000 });
// Get all available icons
const icons = getAvailableIcons();
console.log(icons); // ['DEFAULT', 'premium', 'dark', 'holiday']Backward Compatibility
Aliases are provided for convenience:
import { setAppIcon, getAppIcon } from '@praneeth26/expo-dynamic-app-identity';
// These work the same as setAppIdentity/getAppIdentity
await setAppIcon('premium');
const current = getAppIcon();📱 Platform Support
| Feature | Android | iOS | |---------|---------|-----| | Icon switching | ✅ | ✅ | | Label switching | ✅ | ❌ (iOS limitation) | | Immediate switch | ✅ | ✅ | | Toast feedback | ✅ | ❌ (uses system alert) | | Deep link migration | ✅ | N/A |
🔧 How It Works
Android
Config Plugin modifies
AndroidManifest.xml:- Removes intent filters from base
MainActivity - Creates
MainActivityDEFAULTalias with all intent filters - Creates aliases for each custom icon with
android:labeland intent filters
- Removes intent filters from base
Resource Generation copies icons to
mipmap-*folders:- Generates all density variants (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi)
- Creates round icon variants
Runtime Module uses
PackageManager.setComponentEnabledSetting():- Disables all aliases except the target
- Shows toast notification (optional)
- Supports immediate switching (no delay)
iOS
Config Plugin modifies
Info.plist:- Adds
CFBundleAlternateIconsconfiguration
- Adds
Resource Copying adds icons to iOS project
Runtime Module uses
UIApplication.setAlternateIconName():- iOS handles icon switching natively
- System alert is shown by default
🐛 Troubleshooting
Icon not changing on Android
- Make sure you ran
npx expo prebuildafter adding the plugin - Check that icon files exist at the specified paths
- Verify the icon names in
app.jsonmatch your code
App crashes when switching back to default
This plugin creates a MainActivityDEFAULT alias to prevent crashes. If you still have issues, ensure you're using setAppIdentity(null) or setAppIdentity('DEFAULT').
Deep links not working
This plugin automatically migrates all intent filters to aliases. If you still have issues:
- Run
npx expo prebuild --clean - Check that deep links are configured in
app.json
iOS icon not changing
- iOS requires icons to be added to the Xcode project
- Run
npx expo prebuildto copy icons - iOS always shows a system alert when changing icons
📄 License
MIT
🙏 Credits
Inspired by and improvements upon:
- [@sefatunckanat/expo-dynamic-app-icon]
