Customizing Flutter App for Different Environments with Flavors

Customize your Flutter app with flavors to target multiple environments like staging and production.Establishing various environments, including Development (dev), Demo (staging), and Production (prod), is a fundamental practice in Flutter app development for mobile applications. Each environment has a distinct role, enabling teams to effectively manage and deliver applications while ensuring high standards of quality.

Benefits of Creating Multiple Flavors

1. Enhanced Collaboration and Workflow

  • Independent Development: Developers can operate within their own development environment without disrupting others.
  • Isolated Testing: QA teams and stakeholders can perform tests in a demo or flutter app for staging environment, free from interference from ongoing development activities.
  • Stable Production: The production environment remains stable and insulated from potential issues arising during development.

2. Tailored Configuration

  • Different configurations (e.g., API endpoints, database connections, analytics tools) can be applied to each environment.
  • Feature flags can be tested in staging without enabling them in production.

3. Faster Troubleshooting

  • Developers can reproduce and debug issues in the flutter app  development or staging environment without impacting production.
  • Logs and metrics from different environments provide clearer insights into problems.

4. Efficient Deployment Process

  • Automated Pipelines: Flutter app builds can be deployed to designated environments through automated pipelines, ensuring consistent and repeatable releases.
  • CI/CD Advantages: Continuous Integration and Continuous Deployment (CI/CD) practices thrive with clearly defined environments.

In this tutorial, I’ll guide you step-by-step through the process of adding Multiple Flutter  Flavors in the Flutter application using flutter_flavorizr Package. Let’s dive in!

Smooth Deployment Across Flutter Environments

Prerequisites:

Before running Flutter Flavorizr, you must install the following software:

These prerequisites are needed to manipulate Flutter flavor for  the iOS and macOS projects and schemes. If you are interested in flavorizing Android only, you can skip this step.

Steps 1 -: Installation 

Add the flutter_flavorizr: ^2.2.3 package to the dev_dependencies section of your project’s pubspec.yaml file, and then run the flutter pub get command to install the dependency, as demonstrated below:

Installing Flutter Environment Configuration for Multi-Environment Setup

Step 2 -: Create flavors 

After installing all the necessary prerequisites and adding flutter_flavorizr as a development dependency, you will need to modify your pubspec.yaml file to define the flavors like below.

flavorizr:

  flavors:

    dev:

      app:

        name: "FlavorSample"

      android:

        applicationId: "com.mobisoft.flavorsampleapp"

      ios:

        bundleId: "com.mobisoft.flavorsampleapp"

    demo:

      app:

        name: "FlavorSample"

      android:

        applicationId: "com.mobisoft.flavorsampleapp"

      ios:

        bundleId: "com.mobisoft.flavorsampleapp"

    prod:

      app:

        name: "FlavorSample"

      android:

        applicationId: "com.mobisoft.flavorsampleappprod"

      ios:

        bundleId: "com.mobisoft.flavorsampleappprod"Code language: CSS (css)

Once the flavor is defined, it will appear as follows.

Create Flutter Flavors for Multi-Environment Setup

You can assign a unique bundle ID or package name to each flavor, as I did for the production environment by using a distinct bundle ID.

Step 3-: Executing the Flavorizr Script with flutter pub run

 Having defined the Flavorizr configuration, we can now move forward by running the script with the command flutter pub run flutter_flavorizr

Upon executing the command, you will notice that the following files have been generated in the lib folder: flavors.dart, app.dart, main_dev.dart, main_demo.dart, and main_prod.dart. Additionally, a pages folder will be created, containing the my_home_page.dart file.

The script will remove the default generated code from the main.dart file, which may result in an error in the widget_test.dart file located in the test folder. To fix this, simply replace the error code with await tester.pumpWidget(const App());

Step 3 - Complete Flutter App Environment Configuration

Typically, we prefer to create our own screens. Therefore, I am deleting the script-generated my_home_page.dart and app.dart files. However, if you wish, you can choose to use them and continue with this setup

Step 4 -: Organizing and Configuring Flavor Files for Setup and Initialization

 To keep all flavor-related files organized in one location, create a folder named flavors and then create a file called build_flavor.dart inside it. Add the following code to this file. This section enables you to perform additional setups, such as configuring Firebase or initializing the database, before calling runApp(MyApp()). Additionally, move the flavors.dart file into the flavors folder to maintain organization. 

void buildFlavor(Flavor flavor) {

  F.appFlavor = flavor;

  runApp(const App());

}Code language: JavaScript (javascript)

Invoke the buildFlavor() function in the main_dev, main_demo, and main_prod files, utilizing the correct flavor parameter. The code in your main files should look like this

main_dev.dart -:

Future<void> main() async {

  buildFlavor(Flavor.dev);

}Code language: JavaScript (javascript)

main_demo.dart -:

Future<void> main() async {

  buildFlavor(Flavor.demo);

}Code language: JavaScript (javascript)

main_prod.dart -:

Future<void> main() async {

  buildFlavor(Flavor.prod);

}Code language: JavaScript (javascript)

Step 5-: Setting Up Your Flavors

Now, let’s move on to the next step, where we configure the setup using the main files generated by flutter_flavorizr.

1) Open the Run/debug configuration dialog and choose the Edit Configuration option 

Edit Flutter App Configuration for Different Environments

2) Click the Add New Configuration button (or use ⌘ + N) located at the top-right corner of the window, and select Flutter. Refer to the image below for guidance.

Add New Configuration for Flutter App Build Variants

3) Dev Configuration: Rename the flutter build configuration to dev and specify the path to the main_dev.dart file in the Dart Entrypoint field. Include –flavor dev in the Additional Run Args field. After filling in all the necessary fields, click the OK button.

Note: The argument name should match your flavor name. 

Fields and their descriptions:

  • Name: Specifies the name of the flavor.
  • Dart entrypoint: Defines the path to the respective main file for the flavor.
  • Additional run args: Allows you to add extra command-line arguments to be passed to the Flutter application during execution.
  • Store as project file: When checked, saves the configuration directly in the project files, making it easier to share and manage run settings across teams or different environments
 Flutter Development Configuration for Multi-Environment Setup

If you’re having trouble adding the path of your main file, you can click the browse button at the end of the field to choose the correct main file. Please see the image below for reference

Flutter App Development Configuration - Dev Environmen

4) Demo Configuration: Add a new configuration, rename it to demo, and specify the path to the main_demo.dart file in the Dart Entrypoint field. Include --flavor demo in the Additional Run Args field.

Demo Configuration for Flutter App Deployment

5) Prod Configuration: Add another new configuration, rename it to prod, and specify the path to the main_prod.dart file in the Dart Entrypoint field. Additionally, include --flavor prod in the Additional Run Args field.

Flutter Production Configuration for App Deployment

After completing all configurations, you can remove the main target flavor. Once the setup is finished, your configurations should look like this

Advanced Flutter Production Configuration for App Deployment

Step 6 -: Creating a Flavor-Based Text Display Screen

We have completed all the setup. Now, let’s proceed to the example where we create a screen that displays text with colors corresponding to each flavor.

  1. Create a folder for the screens and add a file named welcome_screen.dart inside it. In this file, we will create a text label and assign its title property, which is automatically generated in flavors.dart, to that label. I have updated the title property with a different text for each flavor, as shown in the following code from flavors.dart.
class F {

  static Flavor? appFlavor;

  static String get name => appFlavor?.name ?? '';

  static String get title {

    switch (appFlavor) {

      case Flavor.dev:

        return 'Development';

      case Flavor.demo:

        return 'Demo';

      case Flavor.prod:

        return 'Prod';

      default:

        return 'title';

    }

  }

}Code language: JavaScript (javascript)

Let’s create a text property in the welcome_screen.dart file and set the title text and color according to the flavor. You can refer to the following code for details

class WelcomeScreen extends StatelessWidget {

  const WelcomeScreen({super.key});

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      home: Scaffold(

        body: Center(

          child: Padding(

            padding: const EdgeInsets.all(10.0),

            child: Text(

              'Welcome to ${F.title} Flavor',

              style: TextStyle(fontSize: 21, color: _getTextColor()),

              textAlign: TextAlign.center,

            ),

          ),

        ),

      ),

    );

  }

  Color _getTextColor() {

    switch (F.appFlavor) {

      case Flavor.dev:

        return Colors.red;

      case Flavor.demo:

        return Colors.blue;

      case Flavor.prod:

        return Colors.green;

      default:

        return Colors.white;

    }

  }

}

Call the initial welcome screen within the buildFlavor function as shown below.

void buildFlavor(Flavor flavor) {

  F.appFlavor = flavor;

  runApp(const WelcomeScreen());

}Code language: JavaScript (javascript)

This is how the welcome screen appears for various flavors after execution.

Final Results of Flutter App Multi-Environment Setup

Summary   

I hope you found this tutorial on Customizing your Flutter app with flavors for different environments helpful. To download the source code for the sample app, click here.

 Scale Your Flutter App with Custom Flavors for All Environments

Author's Bio

Abhijit Muthe
Abhijit Muthe

Abhijit Muthe is a Principal Software Engineer at Mobisoft Infotech, bringing over 8.5 years of experience in mobile application development. He specializes in iOS, Flutter, and Xamarin technologies, demonstrating a strong commitment to creating innovative and user-friendly applications