Flutter Android — Setup flavor with different Firebase Config
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.
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"
]
},
]
}
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.
Github Project