dynamic_app_icon_flutter_plus 0.0.8 copy "dynamic_app_icon_flutter_plus: ^0.0.8" to clipboard
dynamic_app_icon_flutter_plus: ^0.0.8 copied to clipboard

Dynamic App Icon for Flutter enables Flutter apps to change their launcher icon at runtime, ideal for branding updates, seasonal themes, and feature-based icon switching.

dynamic_app_icon_flutter_plus #

A Flutter plugin for dynamically changing app icons on Android and iOS.

Android Demo
Android
iOS Demo
iOS

Features 🌟 #

  • 🎨 Android Support: Change app icons using activity aliases
  • 🍎 iOS Support: Use alternate app icons (iOS 10.3+)
  • πŸ” Auto-Discovery: Automatically finds all available icons from configuration
  • πŸš€ No Hardcoding: Fully dynamic, client-driven configuration
  • πŸ“± Cross-Platform: Works seamlessly on both Android and iOS

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  dynamic_app_icon_flutter_plus: ^0.0.1

Then run:

flutter pub get

Quick Start πŸš€ #

Let's get you started with dynamic app icons in no time!

import 'package:dynamic_app_icon_flutter_plus/dynamic_app_icon_flutter_plus.dart';

// Check if dynamic icons are supported on this platform
bool supported = await DynamicAppIconFlutterPlus.supportsAlternateIcons;

// Get all available icons
List<String> icons = await DynamicAppIconFlutterPlus.getAvailableIcons();

// Get the currently active icon
String? currentIcon = await DynamicAppIconFlutterPlus.getAlternateIconName();

// Change to a different icon
await DynamicAppIconFlutterPlus.setAlternateIconName('dark');

// Restore default icon
await DynamicAppIconFlutterPlus.setAlternateIconName(null);

That's it! You're ready to change app icons dynamically. πŸŽ‰

API Reference πŸ“š #

supportsAlternateIcons #

Check if the current platform supports dynamic app icons.

Returns: Future<bool> - true if supported, false otherwise

Example:

bool supported = await DynamicAppIconFlutterPlus.supportsAlternateIcons;
if (supported) {
  print('Dynamic icons are supported!');
} else {
  print('Dynamic icons not supported on this platform');
}

Platform Support:

  • βœ… Android: Always returns true
  • βœ… iOS: Returns true on iOS 10.3+, false otherwise

getAlternateIconName() #

Get the name of the currently active alternate icon.

Returns: Future<String?> - The icon name if an alternate icon is active, null if using the default icon

Example:

String? currentIcon = await DynamicAppIconFlutterPlus.getAlternateIconName();
if (currentIcon == null) {
  print('Using default icon');
} else {
  print('Current icon: $currentIcon');
}

Note: Returns null when the default app icon is active.


getAvailableIcons() #

Get a list of all available alternate icon names that can be used.

Returns: Future<List<String>> - List of available icon names

Example:

List<String> availableIcons = await DynamicAppIconFlutterPlus.getAvailableIcons();
print('Available icons: $availableIcons');
// Output: Available icons: [dark, light]

Platform Behavior:

  • Android: Dynamically discovers all activity aliases from AndroidManifest.xml that follow the pattern package.MainActivity.iconName
  • iOS: Reads icon names from Info.plist under CFBundleAlternateIcons

Note: The "default" alias is automatically excluded from this list on Android.


setAlternateIconName(iconName, {showAlert}) #

Set the app icon to the specified alternate icon, or restore the default icon.

Parameters:

  • iconName (String?): The name of the icon to set, or null to restore the default icon
  • showAlert (bool, optional): iOS only - Whether to show the system alert when changing icons. Defaults to true.

Returns: Future<void>

Throws: PlatformException if the icon name doesn't exist or there's an error

Example:

// Set an alternate icon
await DynamicAppIconFlutterPlus.setAlternateIconName('dark');

// Set icon without alert on iOS (use at your own risk)
await DynamicAppIconFlutterPlus.setAlternateIconName('light', showAlert: false);

// Restore default icon
await DynamicAppIconFlutterPlus.setAlternateIconName(null);

Platform Behavior:

  • Android: Enables the corresponding activity alias and disables others
  • iOS: Changes the app icon using UIApplication.setAlternateIconName()

iOS Alert Suppression: The showAlert parameter uses a private API on iOS to suppress the system alert. Use this at your own risk as it may break in future iOS versions.


Platform Setup πŸ”§ #

Android Setup #

1. Configure AndroidManifest.xml

Add activity aliases for each alternate icon. The plugin automatically discovers all aliases following the pattern: package.MainActivity.iconName

Important: The main activity must have exported="true" and a launcher intent-filter to serve as the default icon.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:label="Your App Name"
        android:icon="@mipmap/ic_launcher">
        
        <!-- Main Activity - Used as default icon launcher -->
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        
        <!-- Alternate icon 1 -->
        <activity-alias
            android:name="com.example.yourapp.MainActivity.dark"
            android:targetActivity=".MainActivity"
            android:exported="true"
            android:icon="@mipmap/ic_launcher_dark"
            android:label="@string/app_name"
            android:enabled="false">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity-alias>
        
        <!-- Alternate icon 2 - Add as many as you need -->
        <activity-alias
            android:name="com.example.yourapp.MainActivity.light"
            android:targetActivity=".MainActivity"
            android:exported="true"
            android:icon="@mipmap/ic_launcher_light"
            android:label="@string/app_name"
            android:enabled="false">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity-alias>
    </application>
</manifest>

2. Create Icon Resources

For each alternate icon, create icon files in all density folders. You must provide icons for all density variants:

Android Icon Folder Structure

  1. Navigate to your Android app's res directory (e.g., android/app/src/main/res/)

  2. For each alternate icon, create icon files in all density folders:

    • mipmap-mdpi/ic_launcher_{iconName}.png
    • mipmap-hdpi/ic_launcher_{iconName}.png
    • mipmap-xhdpi/ic_launcher_{iconName}.png
    • mipmap-xxhdpi/ic_launcher_{iconName}.png
    • mipmap-xxxhdpi/ic_launcher_{iconName}.png
  3. Example structure for multiple icons:

    res/
      mipmap-mdpi/
        ic_launcher.png          (default icon - required)
        ic_launcher_dark.png     (alternate icon)
        ic_launcher_light.png    (alternate icon)
      mipmap-hdpi/
        ic_launcher.png
        ic_launcher_dark.png
        ic_launcher_light.png
      mipmap-xhdpi/
        ic_launcher.png
        ic_launcher_dark.png
        ic_launcher_light.png
      mipmap-xxhdpi/
        ic_launcher.png
        ic_launcher_dark.png
        ic_launcher_light.png
      mipmap-xxxhdpi/
        ic_launcher.png
        ic_launcher_dark.png
        ic_launcher_light.png
    

Important:

  • Replace {iconName} with your actual icon name (e.g., dark, light)
  • The icon name in the filename must match the name used in the activity-alias in AndroidManifest.xml
  • Ensure all density variants are provided for each icon
  • The default icon (ic_launcher.png) is required and should be present in all density folders

iOS Setup #

Configure Info.plist

Add alternate icons configuration to your Info.plist. Important: You must include both the alternate icons (CFBundleAlternateIcons) and the default/primary icon (CFBundlePrimaryIcon) configuration:

	<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
  <key>dark</key>
  <dict>
    <key>CFBundleIconFiles</key>
    <array>
      <string>dark</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
  </dict>
  <key>light</key>
  <dict>
    <key>CFBundleIconFiles</key>
    <array>
      <string>light</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
  </dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
  <key>CFBundleIconFiles</key>
  <array>
    <string>default</string>
  </array>
  <key>UIPrerenderedIcon</key>
  <false/>
</dict>
</dict>
<key>CFBundleIcons~ipad</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
  <key>dark</key>
  <dict>
    <key>CFBundleIconFiles</key>
    <array>
      <string>dark</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
  </dict>
  <key>light</key>
  <dict>
    <key>CFBundleIconFiles</key>
    <array>
      <string>light</string>
    </array>
    <key>UIPrerenderedIcon</key>
    <false/>
  </dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
  <key>CFBundleIconFiles</key>
  <array>
    <string>default</string>
  </array>
  <key>UIPrerenderedIcon</key>
  <false/>
</dict>
</dict>

Note: The CFBundlePrimaryIcon configuration for the default icon is required. Make sure to include it in both CFBundleIcons (for iPhone) and CFBundleIcons~ipad (for iPad) sections. The default icon name should match the icon files you place in the App Icon folder (e.g., default@2x.png and default@3x.png).

Add Icon Assets

iOS App Icon Folder Structure

  1. Open your project in Xcode

  2. Create an App Icon folder in your Runner directory (e.g., ios/Runner/App Icon/)

  3. Add icon image files for each icon (including the required default icon) with the following naming convention:

    • For each icon name (e.g., dark, light, default), add:
      • {iconName}@2x.png (120x120 pixels for iPhone)
      • {iconName}@3x.png (180x180 pixels for iPhone)

    Important: You must include the default icon files. Example files:

    • default@2x.png (required - for default/primary icon)
    • default@3x.png (required - for default/primary icon)
    • dark@2x.png (for alternate icon)
    • dark@3x.png (for alternate icon)
    • light@2x.png (for alternate icon)
    • light@3x.png (for alternate icon)
  4. Ensure the icon names in your files match the keys used in Info.plist (e.g., if you use "dark" in Info.plist, name your files dark@2x.png and dark@3x.png)

  5. Open Runner.xcworkspace in Xcode (not Runner.xcodeproj)

  6. Right-click on Runner in the project navigator and select "Add Files to 'Runner'"

    Add Files to Runner

  7. Select the App Icon folder you created in step 2

    Select App Icon Folder

  8. In the dialog that appears, select "Create folder references" (not "Create groups") and click "Add"

    Create Folder References

Requirements:

  • iOS 10.3 or later
  • Icon files must be placed in the App Icon folder within your Runner directory
  • Provide both @2x and @3x versions for each alternate icon

Complete Example πŸ’‘ #

Here's a complete example showing how to build an icon selector:

import 'package:flutter/material.dart';
import 'package:dynamic_app_icon_flutter_plus/dynamic_app_icon_flutter_plus.dart';

class IconSelector extends StatefulWidget {
  @override
  _IconSelectorState createState() => _IconSelectorState();
}

class _IconSelectorState extends State<IconSelector> {
  List<String> availableIcons = [];
  String? currentIcon;
  bool isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadIcons();
  }

  Future<void> _loadIcons() async {
    final icons = await DynamicAppIconFlutterPlus.getAvailableIcons();
    final current = await DynamicAppIconFlutterPlus.getAlternateIconName();
    setState(() {
      availableIcons = icons;
      currentIcon = current;
      isLoading = false;
    });
  }

  Future<void> _setIcon(String? iconName) async {
    try {
      await DynamicAppIconFlutterPlus.setAlternateIconName(iconName);
      await _loadIcons();
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Icon changed successfully!')),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return Center(child: CircularProgressIndicator());
    }

    return ListView(
      children: [
        // Default icon option
        ListTile(
          title: Text('Default'),
          trailing: currentIcon == null ? Icon(Icons.check) : null,
          onTap: () => _setIcon(null),
        ),
        // Alternate icons
        ...availableIcons.map((iconName) => ListTile(
          title: Text(iconName),
          trailing: currentIcon == iconName ? Icon(Icons.check) : null,
          onTap: () => _setIcon(iconName),
        )),
      ],
    );
  }
}

For a complete example with a beautiful UI, check out the example directory.


How It Works πŸ” #

Android #

The plugin uses Android's activity aliases feature:

  1. Each alternate icon is configured as an activity-alias targeting the main activity
  2. The plugin dynamically discovers all aliases from AndroidManifest.xml
  3. When changing icons, it enables the target alias and disables others
  4. The main activity serves as the default icon launcher

iOS #

The plugin uses iOS's alternate app icons feature:

  1. Alternate icons are configured in Info.plist under CFBundleAlternateIcons
  2. The plugin reads available icons from the Info.plist
  3. Uses UIApplication.setAlternateIconName() to change icons
  4. Returns null when the default icon is active

Notes ⚠️ #

  • Android: After changing the icon, users may need to go to the home screen to see the change
  • Android: The icon change happens immediately
  • iOS: Changing icons may show a system alert (can be suppressed with showAlert: false)
  • iOS: Requires iOS 10.3 or later
  • All activity aliases (Android) must target the same MainActivity
  • Only one icon can be active at a time

License #

MIT License - see LICENSE file for details.

1
likes
160
points
25
downloads

Publisher

unverified uploader

Weekly Downloads

Dynamic App Icon for Flutter enables Flutter apps to change their launcher icon at runtime, ideal for branding updates, seasonal themes, and feature-based icon switching.

Repository (GitHub)
View/report issues

Topics

#dynamic #icon #app

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on dynamic_app_icon_flutter_plus

Packages that implement dynamic_app_icon_flutter_plus