npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

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-identity

After installation, configure the plugin in your app.json (see Configuration section below), then run:

npx expo prebuild --clean

This 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

  1. Config Plugin modifies AndroidManifest.xml:

    • Removes intent filters from base MainActivity
    • Creates MainActivityDEFAULT alias with all intent filters
    • Creates aliases for each custom icon with android:label and intent filters
  2. Resource Generation copies icons to mipmap-* folders:

    • Generates all density variants (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi)
    • Creates round icon variants
  3. Runtime Module uses PackageManager.setComponentEnabledSetting():

    • Disables all aliases except the target
    • Shows toast notification (optional)
    • Supports immediate switching (no delay)

iOS

  1. Config Plugin modifies Info.plist:

    • Adds CFBundleAlternateIcons configuration
  2. Resource Copying adds icons to iOS project

  3. Runtime Module uses UIApplication.setAlternateIconName():

    • iOS handles icon switching natively
    • System alert is shown by default

🐛 Troubleshooting

Icon not changing on Android

  1. Make sure you ran npx expo prebuild after adding the plugin
  2. Check that icon files exist at the specified paths
  3. Verify the icon names in app.json match 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:

  1. Run npx expo prebuild --clean
  2. Check that deep links are configured in app.json

iOS icon not changing

  1. iOS requires icons to be added to the Xcode project
  2. Run npx expo prebuild to copy icons
  3. iOS always shows a system alert when changing icons

📄 License

MIT

🙏 Credits

Inspired by and improvements upon:

  • [@sefatunckanat/expo-dynamic-app-icon]