← Articles

Different app icons and names per flavor in Flutter

By Ann Tech · 19 September 2024

When you run multiple Flutter flavors (dev, staging, production), each flavor should have its own app icon and display name so users and testers can instantly tell which version is installed.

The goal

  • Dev: app named "MyApp Dev" with a distinct icon (e.g., orange tint)
  • Staging: app named "MyApp Staging" with a different icon (e.g., yellow tint)
  • Production: app named "MyApp" with the standard icon

Android: app names per flavor

android/app/build.gradle.kts:

android {
  flavorDimensions += "environment"

  productFlavors {
    create("dev") {
      dimension = "environment"
      applicationId = "com.example.myapp.dev"
      resValue("string", "app_name", "MyApp Dev")
    }
    create("staging") {
      dimension = "environment"
      applicationId = "com.example.myapp.staging"
      resValue("string", "app_name", "MyApp Staging")
    }
    create("production") {
      dimension = "environment"
      applicationId = "com.example.myapp"
      resValue("string", "app_name", "MyApp")
    }
  }
}

android/app/src/main/AndroidManifest.xml — use the resource variable:

<application
  android:label="@string/app_name"
  ...>

Android: icons per flavor

Place flavor-specific icon files under the flavor source set:

android/app/src/dev/res/
  mipmap-mdpi/ic_launcher.png         (48x48)
  mipmap-hdpi/ic_launcher.png         (72x72)
  mipmap-xhdpi/ic_launcher.png        (96x96)
  mipmap-xxhdpi/ic_launcher.png       (144x144)
  mipmap-xxxhdpi/ic_launcher.png      (192x192)
  mipmap-anydpi-v26/ic_launcher.xml   (adaptive icon)

android/app/src/staging/res/
  mipmap-*/ic_launcher.png

android/app/src/main/res/
  mipmap-*/ic_launcher.png  ← Production (default)

During a dev build, Android merges src/main/res with src/dev/res, with src/dev/res taking priority.

iOS: app names per scheme

  1. In Xcode, select your project → Build Settings
  2. Search for PRODUCT_NAME or INFOPLIST_KEY_CFBundleDisplayName
  3. Click the + next to the setting to add per-configuration values:
    • Debug-dev: MyApp Dev
    • Debug-staging: MyApp Staging
    • Release-production: MyApp

Or set it in Info.plist using a build setting variable:

<key>CFBundleDisplayName</key>
<string>$(APP_DISPLAY_NAME)</string>

Then define APP_DISPLAY_NAME per configuration in Build Settings.

iOS: icons per scheme

  1. In Xcode, open Assets.xcassets
  2. Add icon sets: AppIcon-dev, AppIcon-staging, AppIcon (production)
  3. In Build Settings, search for ASSETCATALOG_COMPILER_APPICON_NAME
  4. Set per configuration:
    • Debug-dev: AppIcon-dev
    • Debug-staging: AppIcon-staging
    • Release-production: AppIcon

Using flutter_launcher_icons

Automate icon generation for all resolutions:

# pubspec.yaml
dev_dependencies:
  flutter_launcher_icons: ^0.13.1

flutter_launcher_icons:
  android: true
  ios: true
  image_path: 'assets/icons/icon_production.png'
  flavors:
    dev:
      android: true
      ios: true
      image_path: 'assets/icons/icon_dev.png'
    staging:
      android: true
      ios: true
      image_path: 'assets/icons/icon_staging.png'
    production:
      android: true
      ios: true
      image_path: 'assets/icons/icon_production.png'
flutter pub run flutter_launcher_icons

This generates all the correctly-sized images in the right directories automatically.

Quick way to create flavor icons

If you don't have a designer, generate tinted versions of your production icon:

# Tint dev icon orange using ImageMagick
convert icon_production.png -fill orange -colorize 40 icon_dev.png

# Tint staging yellow
convert icon_production.png -fill yellow -colorize 40 icon_staging.png

Or add a colored banner overlay:

convert icon_production.png \
  -gravity South \
  -fill '#FF6600' -draw 'rectangle 0,180,192,192' \
  -fill white -pointsize 24 -annotate +0+2 'DEV' \
  icon_dev.png

Using flutter_flavorizr

flutter_flavorizr automates all of this (icons, names, bundle IDs, schemes):

flavorizr:
  app:
    android:
      flavorDimensions: "environment"
  flavors:
    dev:
      app:
        name: "MyApp Dev"
      android:
        applicationId: "com.example.myapp.dev"
        icon: "assets/icons/icon_dev.png"
      ios:
        bundleId: "com.example.myapp.dev"
        icon: "assets/icons/icon_dev.png"
    production:
      app:
        name: "MyApp"
      android:
        applicationId: "com.example.myapp"
        icon: "assets/icons/icon_production.png"
      ios:
        bundleId: "com.example.myapp"
        icon: "assets/icons/icon_production.png"
flutter pub run flutter_flavorizr

Common pitfalls

Not clearing Xcode's derived data after icon changes. iOS sometimes shows the old icon even after changes due to simulator caching. In Xcode: Product → Clean Build Folder, then delete the app from the simulator before reinstalling.

Wrong android:label in AndroidManifest. If android:label is a hardcoded string instead of @string/app_name, the flavor-specific name from build.gradle.kts won't take effect. Make sure the manifest references the resource.

All flavors having the same bundle ID / application ID. If dev and production share the same ID, you can't install both simultaneously. The whole point of separate flavor IDs is separate installations — double-check each flavor has a unique identifier.

Sign in to like, dislike, or report.

Different app icons and names per flavor in Flutter — ANN Tech