Exploring Flutter Flavors: Customize Your App for Different Environments
In the dynamic world of app development, creating versatile applications that cater to various environments is paramount. Whether you're developing for production, testing, or staging, ensuring consistency while accommodating specific requirements is crucial. Flutter, Google's open-source UI toolkit, offers a powerful solution to this challenge with its "flavors" feature.
Understanding Flutter Flavors
Flutter flavors allow developers to build multiple versions of an app from a single codebase, each tailored to a specific environment or configuration. These flavors, also known as build variants or product flavors in other frameworks, enable you to create distinct versions of your app with differences in branding, configuration, or functionality.
Why Use Flavors?
Flavors are typically used to build your app for different environments such as dev and prod. For eg. - your development version of the app might want to point to an API host at dev.api.myapp.com - and your production version of the app might want to point to api.myapp.com.
Instead of hardcoding these values into variables and building an app for every environment manually, the right approach is to use flavors, and supply these values as build time configurations.
Funnily, this article does not tackle the use-case of how to handle different API hosts. I feel another article does this well, and I did not want to repeat that information.
I feel almost everyone launching an app should be using flavors, but I see that most people avoid using them until much longer. Usually the initial setup inertia is enough to leave it for later, and in the end developers end up wasting a lot of time unintentionally. Unfortunately, in the case of Flutter, they are still not that straightforward to setup, hope this article helps with that.
1. Environment-specific Configuration: Flavors facilitate the customization of app configurations such as API endpoints, feature flags, and authentication keys for different environments like development, staging, and production.
2. Branding and Theming: Tailoring the app's branding elements such as colors, fonts, and logos to match different environments or client requirements becomes seamless with flavors.
3. Feature Experimentation: Flavors empower developers to experiment with new features by creating separate builds with those features enabled or disabled, allowing for controlled testing and feedback.
4. Client-specific Builds: For applications deployed to multiple clients, flavors provide an efficient way to generate distinct builds that meet each client's unique specifications without duplicating code or maintaining separate repositories.
Environment set up (From the official Documentation)
Prerequisites:
To set up flavors in iOS and macOS, you'll define build configurations in Xcode.
Creating flavors in iOS and macOS
Your configurations should be based on your Debug.xconfig or Release.xcconfig file, not the Pods-Runner.xcconfigs. You can check this by expanding the configuration names.
4. To match the free flavor, add -free at the end of each new configuration name.
5. Change the free scheme to match the build configurations already created.
Using flavors in iOS and macOS
Now that you've set up your free flavor, you can, for example, add different product bundle identifiers per flavor. A bundle identifier uniquely identifies your application. In this example, we set the Debug-free value to equal com.flavor-test.free.
2. In the Build Settings, set the Product Name value to match each flavor. For example, add Debug Free.
Recommended by LinkedIn
3. Add the display name to Info.plist. Update the Bundle Display Name value to $(PRODUCT_NAME).
Now you have set up your flavor by making a free scheme in Xcode and setting the build configurations for that scheme.
Plugin configurations
If your app uses a Flutter plugin, you need to update ios/Podfile (if developing for iOS) and macos/Podfile (if developing for macOS).
project 'Runner', {
'Debug-free' => :debug,
'Profile-free' => :release,
'Release-free' => :release,
}
Using flavors in Android
Setting up flavors in Android can be done in your project's build.gradle file.
flavorDimensions "default"
productFlavors {
free {
dimension "default"
resValue "string", "app_name", "free flavor example"
applicationIdSuffix ".free"
}
}
Setting up launch configurations
Next, add a launch.json file; this allows you to run the command flutter run --flavor [environment name].
In VSCode, set up the launch configurations as follows:
{
"version": "0.2.0",
"configurations": [
{
"name": "free",
"request": "launch",
"type": "dart",
"program": "lib/main_development.dart",
"args": ["--flavor", "free", "--target", "lib/main_free.dart" ]
}
],
"compounds": []
}
You can now run the terminal command flutter run --flavor free or you can set up a run configuration in your IDE.
Launching your app flavors
For examples of build flavors for iOS, macOS, and Android, check out the integration test samples in the Flutter repo.
Retrieving your app's flavor at runtime
From your Dart code, you can use the appFlavor API to determine what flavor your app was built with.
Conditionally bundling assets based on flavor
If you aren't familiar with how to add assets to your app, see Adding assets and images.
If you have assets that are only used in a specific flavor in your app, you can configure them to only be bundled into your app when building for that flavor. This prevents your app bundle size from being bloated by unused assets.
Here is an example:
flutter:
assets:
- assets/common/
- path: assets/free/
flavors:
- free
- path: assets/premium/
flavors:
- premium