Creating Flavors for Flutter app (VS Code & Android Studio)

This article will teach you how to setup separate targets for Dev, Staging and Production Environments in Flutter and add these configurations to IDEs (VS Code and Android Studio) to toggle between these targets with EASE.

Dinesh Kachhot
Flutter Community
8 min readApr 4, 2019

--

The 80-20 Principle Photo by Austin Distel on Unsplash

Do you think only smart OR hard work pays off?

I think the hard and smart work balance will drive you to the success possibly!!

I am working on my self these days, trying to improve lifestyle by improving my daily habits. Let me share some of my experiments.

Do you know Pomodoro Technique?

The Pomodoro Technique is a time management method developed by Francesco Cirillo in the late 1980s. The techniqueuses a timer to break down work into intervals, traditionally 25 minutes in length, separated by short breaks.

I am trying to follow Pomodoro at my work place, it’s hard to follow while you start, because every break time you are in between a task of finished task early than break time, but the result is way more productive. While you know you will have to take a break, your focus more on your work, and in a break you will have enough time to think the problems and road map to finish it.

For example: While learning to drive, you may notice if you take a short break then try again, your driving is improved. This is how Pomodoro Technique work.

It’s comparatively easy to get rank in top 10 than be a topper in class!

Yes that’s true and everyone know if you are not a last bencher and late night reader like me 😉. That’s why back in 1895 Vilfredo Pareto introduce 80-20 rule.

Roughly 80% of the effects come from 20% of the causes.

Let’s see how it applies to Software and Sports as these are of my interest fields.

In Software:- Microsoft noted that by fixing the top 20% of the most-reported bugs, 80% of the related errors and crashes in a given system would be eliminated.

In Sports:- Roughly 20% of the exercises and habits have 80% of the impact and the trainee should not focus so much on a varied training.

Enough motivation, but this is directly relate to topic only. lets dig in to the topic!

Overview

Why we need multiple targets? How to make it?

As a developer, we have to deal with multiple environments like those required to separate testing and production configurations. We need to have separate configurations like base url, configuration keys, app names, app icons, databases, etc. Most of products follow two environments, “development” and “production”. In some cases, staging and QA are used between development and production to ensure the expected outcome.

So common used environments are Development, {Staging, QA}, Production.

When starting with Flutter, one of the questions I asked myself was “how can I manage environment variable in Flutter like I am using in iOS”.

As luck would have it, I found this stakoverflow answer by Seth Ladd, a Product Manager at Google, formerly of the Flutter team, now working on Fuchsia. I also found this blog which is only for Android Studio/InteliJ.

Since Vs Code is my editor of choice, I decided to write a similar article for VS.

My favorite Flutter IDE is VS Code and the following are my personal preferences:
- I am full-time iOS Developer 😎😉, so I don’t mind to fresh start with VS Code
- VS Code is fast and lightweight (smooth operator), less memory usage and battery life
- I love the blue Theme of VS Code, later I customized my Xcode them to Blue, same like VS Code
- It let me focus, more responsive and not sluggish

Android Studio Flutter ready Setup

There might be times while using VsCode where you need to change something Android specific. In Vs Code, you can right click the Android folder and choose “Open in Android Studio”.

Once opened, you might be faced with the following error:

Dart SDK Not Found? Don’t panic!

The solution for this is pretty easy, you need to add the Flutter SDK path.

Click on Android Studio on top left → Select Preferences… → Unfold Langues & Frameworks → Select Flutter → Select Flutter SDK Path → Click on Apply Button.

Set Flutter SDK Path

Prerequisite

Create a new app and do following minor changes.

main.dart is almost same as default tamplate
my_app.dart

TODO

Currently app support single environment, there is no way to set a different configurations for different environments(Except commenting/un-commenting code🤨). We will set three different environments Development, Staging and Production.

We will configure following things to separate each build from other,
1. Set app bar title with text App name — <Environment>
2. Set first label with description of the target
3. Set second label text with base url used for selected target
4. Set separate ThemeData for each target

Create App Configuration

Lets create app_config.dart which will contains all environment related configurations.

AppConfig extends with InheritedWidget, so the single reference can be used throughout the app.

AppConfig

Create main file for each environment

In flutter main.dart is entry point of app, so we can set app configuration in main.dart file. We want to create three different environments so will have to create three variant of main file , main_dev.dart, main_stage.dart, main.dart.

In each main file, we’ll set configurations in AppConfig class with the appropriate configuration data before runApp called. From then AppConfig can be used in entire app with access of shared instance.

Likewise we have to set different configuration for different main file according to environment.

We just set configuration of shared AppConfig instance in main class. Instead of direct call runApp we derive function body and set configuration. Set title of MyApp and MyHomePage widget and set theme data as per AppConfig.

As we are using shared instance access of AppConfig properties will be same throughout the app as the reference is shared.

Run/Build using terminal

We can run the different variants by running flutter run with the --target or -t argument for short.

Run flutter help run in terminal to know about run parameters.

So, in our case:

  • to run the development build, we call flutter run -t lib/main_dev.dart
  • to run the staging build, we call flutter run -t lib/main_stage.dart
  • to run the production build, we call flutter run -t lib/main_prod.dart

To create a release build on iOS, we can run flutter build ios -t lib/main_<environment>.dart and we will get the correct IPA for our environment. To do a release build on Android, just replace ios with apk.

So far so good. But how handy it is to run command in terminal every-time? It’s very easy if we have an option to switch between environments in our respective IDEs.

Using VS Code

Follow these steps below to setup targets in VS Code

1. Press ⌘⇧D if you are not in debug tab yet.
2. Click on configuration beside play button.
3. Select add configuration… from dropdown
4. It will open a drop down in launch.json file
5. Search Flutter and select {}Flutter: Launch

launch.json

6. Add "program": "lib/main.dart" for if it’s not already exist there (default is main.dart if you don’t write program field)
7. Rename “name” with your app name
8. Copy that configuration and past two times for Dev and Staging
9. Change name and program for just pasted configurations as per follow

Now toggle the targets from drop-down beside play button and test your configurations for Development, Staging and Production.

Run it using fn + F5 or F5, hot reload will not push the change because we did change in launch.json and main.dart file.

Using Android Studio

  1. Open app folder in Android Studio (not just the android folder)
  2. Click on main.dart button left side of play button, will open a dropdown
  3. Click on Edit Configurations…
  4. Rename main.dart target to your app-name
  5. Click on + on top left corner to add new configuration
  6. Select Flutter from dropdown
  7. Edit name to <app-name>-dev
  8. Check share checkbox
  9. Select Dart Entry point to main_dev.dart from lib folder
  10. Repeat steps 5–9 to add stage configuration

Now you can toggle between targets in Android Studio too. Toggle between targets and play with it.

Flutter multiple target demo source code is here.

Android Configuration

Let’s setup flavors in Android as well to separate platform specific configurations.

  • Open build.gradle in android>app folder.
  • Write following code as per your environments below buildTypes
flavorDimensions "default"
productFlavors {
dev {
dimension "default"
applicationIdSuffix ".dev"
}
stag {
dimension "default"
}
prod {
dimension "default"
}
}
  • Run your flavor using following command
    flutter run -t lib/main_dev.dart — flavor dev

iOS Configuration

Add different schemes to iOS project, open iOS workspace in Xcode and follow the steps,

  • Product> Schemes> Manage Schemes…
  • Select Runner Scheme click on setting icon and duplicate option
Create new scheme using Runner duplicate.
  • Name scheme name dev and select shared and close the window
  • Repeat above steps for all the flavors of flutter

Set project configurations as follows

  • Select root project Runner and Select Runner in Project section(Select info tab if it is not selected already)
  • We have to duplicate Debug and Release configuration for each Flavors
  • Select debug and click on + icon below, select Duplicate “Debug” Configuration, rename it to Debug-dev
  • Repeat duplicate and rename for all Debug flavors
  • Repeat duplicate and rename for all Release flavors
Final configurations looks like this

It’s time to assign proper configurations to our schemas,

  • Go to Product> Schemes> Manage Schemes…
  • Select dev and click on Edit
  • Select run scheme and select Debug-dev option in Build Configuration
  • Select Archive scheme and select Release-dev option in Build configuration

Repeat above steps for all the pending flavors in the app.

Run your flavor using following command
flutter run -t lib/main_dev.dart — flavor dev

My articles are free, but you know you can press the clap👏 button 50 times? The higher you go, the more it motivates me to write more stuff for you guys!

Feeling super generous?

I am Dinesh Kachhot. A creative developer and a logical designer. You can find me on Linkedin or stalk me on GitHub or maybe follow me on Twitter? If that’s too social for you, just drop a mail to dinesh.kachhot@gmail.com if you wish to talk tech with me.

--

--

Dinesh Kachhot
Flutter Community

iOS Developer 👨🏻‍💻 Flutter and React Native 💙