Creating flavors of a Flutter app (Flutter & Android setup)

It’s quite common for a native Android app to use productFlavors to set up several apps from the same source code. So, how easy is this to implement in Flutter?

In this code tutorial, we will set up a project with 2 app flavors. Each app will display the app name (specific per flavor), the current date (shared functionality, which includes a string), a short description (specific per flavor), and two images (one specific per flavor, one shared).

Note: The code tutorial only involves the Flutter and  Android set up, not the iOS set up, because I am not proficient in building and publishing iOS apps.


Code tutorial index

Setting up the app as a single app
Adding flavors (Android setup)
Adding flavors (Flutter setup)
Customising some string resources based on flavor
Customising some assets based on flavor

Setting up the app as a single app

To follow the code tutorial, create a new app as follows.

If you’re unsure how to set up a Flutter app, check out Getting started with Flutter official tutorial.

Firstly, we create a Material app in main.dart, which will launch the HomePage widget.

 

Secondly, we create home_page.dart. It displays the app name, the current date, a short description, and two images.

 

Thirdly, we create a resource folder, and a new file display_strings.dart in in.

 

Fourthly, we add the intl package (used for date formatting) to pubspec.yaml as below, then do flutter packages get .

 

Lastly, we set up the images. Create a folder assets (on same level as lib), then add images dancing.png and 1.png (right click on files then save), and amend the pubspec.yaml as below.

Back to code tutorial index

Adding flavors (Android setup)

Now, we will create 2 flavors of our app, called app1 and app2. To do this, we amend android/app/build.gradle file as below.

 

We also amend the AndroidManifest.xml (in android/app/src/main folder) to use an app name specified in an Android string resource.

 

Then, we provide the app name string for each app. In android/app/src/main/res/values, we create strings.xml as below.

 

Finally, we create folders app1 and app2 under android/app/src. In each new folder, we create a folder res then a folder values. Inside each new values folder, we create strings.xml as below.

 

Flutter run and build commands come with a –flavor flag. So, from the command line, you can simply type flutter run --flavor app1  and flutter fun --flavor app2 .

Gotcha 1: As of writing and on my system, you need to do flutter clean  in between running different flavors.

Gotcha 2: –flavor flag currently fails if the Android flavor name has an uppercase character in it, so make sure your Android flavor names are all lowercase! 

If you prefer using an IDE, you can edit your configurations and pass in the flavor in it. So let’s create 2 configurations in the IDE, as per screenshots below.

Select Edit Configurations
Select Edit Configurations
Rename to App1
Rename to App1
Add build flavor
Add build flavor
Select Add new configuration
Select Add new configuration
Select Flutter
Select Flutter
Name App2
Name App2
Add Dart entrypoint
Add Dart entrypoint
Add build flavor
Add build flavor
Select Share
Select Share

 

At this point, when you run each app, you will see the same thing on screen. However, you should see the correct app name when you view the list of apps on your device (ie “App 1” and “App 2”).

 

 

Back to code tutorial index

Adding flavors (Flutter setup)

Following the advice from Separating build environments in Flutter apps, part #1 – environment-specific configuration in Dart side, we will create an app_config.dart file, which is an Inherited Widget. Such a Widget allows for the app config data to be accessed from any widgets in the app.

 

Then, we rename main.dart to main_common.dart, amend it slightly, and create main_app1.dart and main_app2.dart files.

 

Then, we edit home_page.dart to show the app name. We also remove APP_TITLE string from display_strings.dart.

 

Finally, to launch each config from the command line, you can simply type flutter run --flavor app1 -t lib/main_app1.dart  and flutter run --flavor app2 -t lib/main_app2.dart

Or, from the IDE, you can edit each configuration as per screenshots below.

Amend Dart entrypoint for App2
Amend Dart entrypoint for App2
Amend Dart entrypoint for App1
Amend Dart entrypoint for App1

 

Note: renaming main.dart to main_common.dart means that we have to pass in a main file name when launching the app (as the default doesn’t exist), so we never accidentally launch the non configured app.

Gotcha 3: when launching from the IDE, I sometimes need to relaunch because even though I am launching “App2”, “App1” is being launched. But a hot restart usually fixes this. On a few rare occasions, I need to do  flutter clean .

At this point, when you run each app, you will see the correct app title, but all the other strings and images are the same.

 

Back to code tutorial index

Customising some string resources based on flavor

In Android, we are used to overloading the xml resources so we can specify a different one for a different flavor. By this, I mean what we did above for the Android app_title string resource – we keep the name, we just give it a different value.

As everything in Flutter is Dart code, we need to use a Dart construct, that is an abstract class.

Let’s look at how it works in practice, by making the string APP_DESCRIPTION customizable per flavor.

We amend app_config.dart to add the abstract string class.

 

We remove APP_DESCRIPTION string from display_strings.dart and create 2 new files, in /lib/resource, named display_strings_app1.dart and display_strings_app2.dart, as below.

 

Note: by using an abstract class, we cannot forget to implement a string for a given flavor.

Then, we need to amend main_app1.dart and main_app2.dart to specify which string resource to use.

 

And we need to amend home_page.dart so it uses the string from the StringResource.

Back to code tutorial index

Customising some assets based on flavor

As assets are specified in a folder, we can use a file structure to specify which asset to use, and then we can use the appInternalId (specified in AppConfig) to retrieve the correct one.

Firstly, we create folders 1 and 2 under assets. We  then rename 1.png to icon.png and move it to the 1 folder. We then download and save 2.png in the 2 folder, and rename it to icon.png.

Secondly, we amend the home_page.dart to specify the correct icon based on the appInternalId.

 

Finally, we amend pubspec.yaml.

Back to code tutorial index

Voila!

App 1
App 1
App 2
App 2

 

Enjoying this code tutorial? Support the blog!

Options
 

What next?

So, you’ve learned a way to use flavors in Flutter. There are a few different ways, so for a full understanding of your options, I recommend you checkout Flavoring Flutter

 

 

Subscribe to my mailing list

Receive a monthly email with a curated list of the best 5 articles on software development I have come across during the month, as well as relevant blog updates such as new posts. The email is sent near the start of each month.
* indicates required

Android app developer with 8 years experience, ranging from start ups to large tech (Google) and non tech (British Airways) companies. Currently freelancing and learning Flutter. LinkedIn natalie ( at ) cogitas (dot) net

Author: Natalie Masse Hooper

Android app developer with 8 years experience, ranging from start ups to large tech (Google) and non tech (British Airways) companies. Currently freelancing and learning Flutter. LinkedIn natalie ( at ) cogitas (dot) net

Leave a Reply

Your email address will not be published. Required fields are marked *