Flutter Flavor Setup

yazar:

kategori:

# Flutter Firebase Flavor Configuration Guide

## 1. Installation of Required Tools

First, install the FlutterFire CLI:

“`bash
dart pub global activate flutterfire_cli
“`

## 2. Creating Firebase Projects

Create separate Firebase projects for each environment (dev, staging, prod).

## 3. Firebase Configuration with FlutterFire CLI

Run FlutterFire configuration separately for each environment:

“`bash
# For Dev environment
flutterfire configure \
–project=your-dev-project-id \
–out=lib/firebase_options_dev.dart \
–ios-bundle-id=com.yourcompany.yourapp.dev \
–android-app-id=com.yourcompany.yourapp.dev

# For Staging environment
flutterfire configure \
–project=your-staging-project-id \
–out=lib/firebase_options_staging.dart \
–ios-bundle-id=com.yourcompany.yourapp.staging \
–android-app-id=com.yourcompany.yourapp.staging

# For Production environment
flutterfire configure \
–project=your-prod-project-id \
–out=lib/firebase_options_prod.dart \
–ios-bundle-id=com.yourcompany.yourapp \
–android-app-id=com.yourcompany.yourapp
“`

## 4. Flavor Configuration

### 4.1 Creating lib/firebase_options.dart File

“`dart
import ‘package:firebase_core/firebase_core.dart’ show FirebaseOptions;
import ‘package:flutter/foundation.dart’
show defaultTargetPlatform, kIsWeb, TargetPlatform;

import ‘firebase_options_dev.dart’ as dev;
import ‘firebase_options_staging.dart’ as staging;
import ‘firebase_options_prod.dart’ as prod;

enum Flavor { dev, staging, prod }

class DefaultFirebaseOptions {
static FirebaseOptions getOptions(Flavor flavor) {
switch (flavor) {
case Flavor.dev:
if (kIsWeb) return dev.DefaultFirebaseOptions.web;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return dev.DefaultFirebaseOptions.android;
case TargetPlatform.iOS:
return dev.DefaultFirebaseOptions.ios;
default:
throw UnsupportedError(‘Unsupported platform’);
}
case Flavor.staging:
if (kIsWeb) return staging.DefaultFirebaseOptions.web;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return staging.DefaultFirebaseOptions.android;
case TargetPlatform.iOS:
return staging.DefaultFirebaseOptions.ios;
default:
throw UnsupportedError(‘Unsupported platform’);
}
case Flavor.prod:
if (kIsWeb) return prod.DefaultFirebaseOptions.web;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return prod.DefaultFirebaseOptions.android;
case TargetPlatform.iOS:
return prod.DefaultFirebaseOptions.ios;
default:
throw UnsupportedError(‘Unsupported platform’);
}
}
}
}
“`

### 4.2 Editing lib/main.dart File

“`dart
import ‘package:flutter/material.dart’;
import ‘package:firebase_core/firebase_core.dart’;
import ‘firebase_options.dart’;

Future mainCommon(Flavor flavor) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.getOptions(flavor),
);
runApp(MyApp(flavor: flavor));
}

void main() => mainCommon(Flavor.prod);
void mainDevelopment() => mainCommon(Flavor.dev);
void mainStaging() => mainCommon(Flavor.staging);

class MyApp extends StatelessWidget {
final Flavor flavor;

const MyApp({Key? key, required this.flavor}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter Firebase Demo’,
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: ‘Flutter Firebase: ${flavor.name}’),
);
}
}

// … MyHomePage and other widgets
“`

## 5. Android Configuration

### 5.1 Editing android/app/build.gradle File

“`gradle
android {

flavorDimensions “default”
productFlavors {
dev {
dimension “default”
applicationIdSuffix “.dev”
resValue “string”, “app_name”, “MyApp Dev”
}
staging {
dimension “default”
applicationIdSuffix “.staging”
resValue “string”, “app_name”, “MyApp Staging”
}
prod {
dimension “default”
resValue “string”, “app_name”, “MyApp”
}
}
}

// Managing google-services.json files
def flavorRegex = ~/\/(dev|staging|prod)\//
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def flavor = variant.flavorName
def task = project.tasks.create(“process${flavor.capitalize()}GoogleServices”, Copy) {
from(“${project.projectDir}/src/${flavor}/google-services.json”)
into(“${project.projectDir}/”)
}
variant.preprocessJavaResources.dependsOn(task)
}
}
“`

### 5.2 Placing google-services.json Files

Place the `google-services.json` file for each flavor in the relevant folder:

“`
android/
app/
src/
dev/
google-services.json
staging/
google-services.json
prod/
google-services.json
“`

## 6. iOS Configuration

### 6.1 Editing ios/Runner/AppDelegate.swift File

“`swift
import UIKit
import Flutter
import Firebase

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let filePath: String
#if DEBUG
filePath = Bundle.main.path(forResource: “GoogleService-Info-Dev”, ofType: “plist”)!
#elseif STAGING
filePath = Bundle.main.path(forResource: “GoogleService-Info-Staging”, ofType: “plist”)!
#else
filePath = Bundle.main.path(forResource: “GoogleService-Info”, ofType: “plist”)!
#endif

guard let options = FirebaseOptions(contentsOfFile: filePath) else {
fatalError(“Firebase configuration file not found.”)
}
FirebaseApp.configure(options: options)

GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
“`

### 6.2 Placing GoogleService-Info.plist Files

Place the `GoogleService-Info.plist` file for each flavor in the relevant folder:

“`
ios/
Runner/
Firebase/
dev/
GoogleService-Info-Dev.plist
staging/
GoogleService-Info-Staging.plist
prod/
GoogleService-Info.plist
“`

### 6.3 Creating Configurations in Xcode

1. Open your project in Xcode.
2. Select your project in the Project navigator.
3. Go to the “Info” tab in the “Configurations” section.
4. Create Debug and Release configurations for each flavor (e.g., Debug-Dev, Release-Dev, Debug-Staging, Release-Staging).

## 7. Running the Application

You can run the application for different flavors with these commands:

“`bash
# For Dev
flutter run –flavor dev -t lib/main.dart

# For Staging
flutter run –flavor staging -t lib/main.dart

# For Prod
flutter run –flavor prod -t lib/main.dart
“`

## 8. CI/CD Integration

Create separate build and deploy steps for each flavor in your CI/CD pipeline. An example fastlane configuration:

“`ruby
lane :build_and_deploy_dev do
sh “flutter build ios –release –flavor dev -t lib/main.dart”
build_ios_app(
scheme: “dev”,
export_method: “development”
)
# Steps to upload to Firebase App Distribution or TestFlight
end

# Create similar lanes for staging and prod
“`

## 9. Points to Consider

– Make sure you’re using the correct Firebase project and configuration files for each environment.
– Avoid keeping sensitive information (API keys, etc.) directly in the code.
– Ensure all team members understand and use this structure correctly.
– Regularly test and update each flavor.

This guide explains step by step how to set up flavor configuration using FlutterFire CLI. Remember that each project may have its own unique requirements, so adapt this structure to your project’s needs when necessary.

Using flavors in app development, particularly with Flutter and Firebase, offers several important benefits. Here’s why you should consider using flavors:

1)Environment Separation:
Flavors allow you to maintain separate environments (e.g., development, staging, production) within a single codebase.

2)Simultaneous Installation:
Different versions of your app can be installed on the same device concurrently, facilitating testing and comparison.

3)Configuration Management:
You can easily manage different configurations (API endpoints, feature flags, etc.) for each environment.

4)Isolated Testing:
Flavors enable isolated testing of features in different environments without affecting the production app.

5)Streamlined Development Process:
Developers can work on new features or bug fixes in a development environment without risking the stability of the production app.

6)Firebase Project Separation:
With flavors, you can use different Firebase projects for each environment, keeping analytics, crash reports, and other data separate.

7)App Store and Play Store Management:
Flavors allow you to manage different app versions in the stores, such as beta versions alongside the main app.

8)Resource Management:
You can use different resources (icons, splash screens, etc.) for each flavor, useful for branding different versions.

9)Build Optimization:
Flavors can help optimize builds by including or excluding certain dependencies or features based on the environment.

10)Team Collaboration:
Flavors facilitate better team collaboration by allowing different team members to work on different environments simultaneously.

11)Continuous Integration/Continuous Deployment (CI/CD):
Flavors integrate well with CI/CD pipelines, allowing automated builds and deployments for different environments.

12)Client Management:
For agencies or companies with multiple clients, flavors can help manage different client versions of an app.

13)A/B Testing:
Flavors can be used to create different versions of an app for A/B testing purposes.

14)Compliance and Regulations:
In some industries, separate environments are required for compliance with regulations and standards.

Using flavors does add some complexity to your project setup, but the benefits in terms of development efficiency, testing capabilities, and environment management often outweigh this initial setup cost. It’s particularly valuable for larger projects, teams, or any application that requires a clear separation between development, testing, and production environments.


Yorumlar

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir