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
- In Xcode, select your project → Build Settings
- Search for
PRODUCT_NAMEorINFOPLIST_KEY_CFBundleDisplayName - Click the
+next to the setting to add per-configuration values:Debug-dev: MyApp DevDebug-staging: MyApp StagingRelease-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
- In Xcode, open
Assets.xcassets - Add icon sets:
AppIcon-dev,AppIcon-staging,AppIcon(production) - In Build Settings, search for
ASSETCATALOG_COMPILER_APPICON_NAME - Set per configuration:
- Debug-dev:
AppIcon-dev - Debug-staging:
AppIcon-staging - Release-production:
AppIcon
- Debug-dev:
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.