Flutter Android — Setup flavor with different Firebase Config

Yusuf Fachroni
5 min readMay 15, 2023

--

Google Sign-In for Android using Firebase | by Ari SWS | DOT Intern | Medium

What is the purpose of flavors? Flavors serve as a means to tailor your application for various contexts, including development and production. Let’s consider an example:

  • During the development phase, you may want your app to connect with the API host at https://dev.mobileapp.com/v1/ with project ID com.mobileapp.dev
  • Conversely, when you’re ready to release the app, the production version should connect to https://api.mobileapp.com/v1/ with project ID com.mobileapp.prod

Rather than manually coding these values into variables and creating separate app builds for each environment, the recommended approach is to utilize flavors. By employing flavors, you can provide these values as build-time configurations, streamlining the process.

The methodology employed in this tutorial involves creating a sample application with two flavors: dev and prod. Throughout the tutorial, the sample app will have commits after each step, enabling you to examine code differences and comprehend the changes made.

Furthermore, I will provide comprehensive instructions to ensure ease of use, making it effortless to apply these instructions to an already existing app.

Step 1: Initialize a default Flutter app

Step 2: Configure the app to connect to Firebase

Create 2 Firebase projects, one is for dev and one is for prod. Create an app for Android in the Firebase console for each project, let's say for dev is using app ID com.mobileapp.dev and for prod is com.mobileapp.prod. You will need to download the google-services.json files for those 2 apps. Detailed instructions on how to add Firebase to your Flutter project can be found here: Firebase Flutter Setup Guide.

Create 2 Firebase Project for Dev & Prod

Copy google-services.json on dev and prod to separate folder in android/app/src folder

You also can set different name for dev and prod App like this

Step 3: Create 2 configuration file in root project directory for set pointing to different api endpoint

dev.json

prod.json

Set on product flavors on build.gradle

add these line to android/app/build.gradle inside android { }

    flavorDimensions "env"

productFlavors {

dev {
dimension "env"
applicationId "com.mobileapp.dev"
}

prod {
dimension "env"
applicationId "com.mobileapp.prod"
}
}

Step 4: Create some dart file to handle configuration based on flavor

lib/utils/environment.dart

abstract class Environment {
static const dev = 'dev';
static const prod = 'prod';
}

lib/utils/config_reader.dart

import 'dart:convert';

import 'package:flutter/services.dart';

abstract class ConfigReader {
static Map<String, dynamic>? _config;
static bool _isDevMode = false;

static Future<void> initialize(String env) async {
var configString = '{}';
try {
configString = await rootBundle.loadString('config/$env.json');
} catch (_) {
configString = await rootBundle.loadString('config/dev.json');
}
_config = json.decode(configString) as Map<String, dynamic>;
_isDevMode = env == "dev";
}

static bool isDevMode() {
return _isDevMode;
}

static String getBaseUrl() {
return _config!['baseUrl'] as String;
}
}

Step 5: Create 3 different main dart file to manage flavor

lib/main_dev.dart

Future<void> main() async {
await mainCommon(Environment.dev);
}

lib/main_prod.dart

Future<void> main() async {
await mainCommon(Environment.prod);
}

lib/main_common.dart

Future<void> mainCommon(String env) async {
WidgetsFlutterBinding.ensureInitialized();
await ConfigReader.initialize(env);
runApp(const MyApp());
}

Step 6: Get variable based on flavor

You can get variable from config like this

debugShowCheckedModeBanner: ConfigReader.isDevMode(),

And get base_url for connection class file like this

class HttpGetConnect extends GetConnect {
final _baseUrl = ConfigReader.getBaseUrl();

static HttpGetConnect? _instance;

HttpGetConnect._internal() {
_instance = this;
httpClient.baseUrl = _baseUrl;
}
}

Step 7: Edit vscode launcher config

open .vscode/lunch.json

change launch.json to this code

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "[Debug] Development App",
"request": "launch",
"type": "dart",
"program" : "lib/main_dev.dart",
"args": [
"--flavor",
"Dev"
]
},
{
"name": "[Debug] Production App",
"request": "launch",
"type": "dart",
"program" : "lib/main_prod.dart",
"args": [
"--flavor",
"Prod"
]
},
{
"name": "[Release] Production App",
"request": "launch",
"type": "dart",
"flutterMode": "release",
"program" : "lib/main_prod.dart",
"args": [
"--flavor",
"Prod"
]
},
]
}


and now you can launch your app using dev flavor or prod flavor
Left: Running production in debug mode | Right: Running development in debug mode

Step 8: Create apk for dev / aab for production

You can build apk for dev using this command

flutter build apk --flavor dev -t lib/main_dev.dart

And aab for prod using this command

flutter build appbundle --flavor prod -t lib/main_prod.dart

Would you like to proceed with setting up flavors in iOS? Let’s move on to the next step.

https://ahmedyusuf.medium.com/setup-flavors-in-ios-flutter-with-different-firebase-config-43c4c4823e6b

Github Project

https://github.com/c0deslinger/flutter-learn-flavor

--

--