slidersFlavor

Set up 3 environments (dev, staging, production) for mobile in Flutter (3 separate mobile apps)

As a Flutter project grows, separating dev / staging / production environments becomes very important. More importantly, splitting them into 3 different apps helps ensure product quality. My goals are:

  • Set up clear environments for the whole team with 3 separate apps.

  • Split Firebase config by environment.

  • Reduce build and release errors.

Before we start, here is what will change after setting up 3 separate apps for 3 environments.

Android: Set up 3 environments

Step 1: Declare environments in android/app/build.gradle

Go to this file:

Inside the android { ... } block, add the following right after defaultConfig { ... }:

Note: applicationIdSuffix helps separate package IDs so multiple apps can be installed in parallel.

Then add this after compileOptions:

Run the following command to verify:

Step 2: Split google-services.json by flavor

Create 3 folders:

Copy each corresponding google-services.json file into the correct folder. Note: each file must match the app ID of its environment.

How to get the files:

  • Go to your project in Firebase Console.

  • Add App -> choose Android -> enter each environment app ID.

  • Download google-services.json for each app.

Run the following commands to verify:

Step 3: Run Android app by flavor

Method 1: Run from terminal

If you do not know what FVM is, you can read this article:

code-branchFVMchevron-right

You can also apply this article to make your commands shorter:

terminalMakechevron-right

Method 2: Run with Configuration in Android Studio

  • Configuration -> select Edit

  • Fill the matching Build flavor (dev, staging, production)

  • Choose the matching entry file for each environment

Run app by Build flavor in IDE

iOS: Set up 3 environments

Step 1: Create Configurations

Open:

In Xcode:

  • Runner (PROJECT) > Info > Configurations

  • Duplicate into 9 configurations:

    • Debug-dev, Debug-staging, Debug-production

    • Profile-dev, Profile-staging, Profile-production

    • Release-dev, Release-staging, Release-production

Run the commands below to create .xcconfig files (example for dev):

In the Based on Configuration File column, map correctly:

  • Debug-dev -> Debug-dev.xcconfig

  • Profile-dev -> Profile-dev.xcconfig

  • Release-dev -> Release-dev.xcconfig

Go to TARGETS > Runner > Build Settings -> filter Product Bundle Identifier, then change by environment.

Example for dev:

Step 2: Update ios/Podfile

In:

Replace:

With:

Run to verify:

Step 3: Create schemes by environment

In Xcode:

  • Product > Scheme > Manage Schemes...

  • Click + -> choose Target Runner -> name it dev

  • Tick the Shared column

  • Select scheme dev -> Edit...

  • Change to Debug-dev

  • Do the same for the remaining ones based on this map:

    • Run = Debug-dev

    • Test = Debug-dev

    • Profile = Profile-dev

    • Analyze = Debug-dev

    • Archive = Release-dev

Add the line below:

into these 3 files: Debug-dev.xcconfig Profile-dev.xcconfig Release-dev.xcconfig

Run to verify:

Then do the same for staging and production.

Step 4: Create Firebase config files by environment

Create directories for Firebase:

Copy the 3 corresponding GoogleService-Info.plist files into the correct folders, making sure app IDs match.

Add GOOGLE_SERVICE_INFO_PLIST to all 9 .xcconfig files:

Step 5: Add Build Phase Select Firebase Plist

In TARGETS > Runner > Build Phases:

  • Click + -> New Run Script Phase

  • Rename it to: Select Firebase Plist

  • Paste this script:

In this phase:

  • Input Files: $(PROJECT_DIR)/$(GOOGLE_SERVICE_INFO_PLIST)

  • Output Files: ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist

Move this phase near the bottom (usually below Copy Bundle Resources or before signing scripts).

Step 6: Remove static plist from Resources

In Copy Bundle Resources:

  • Find GoogleService-Info.plist

  • Remove it from the phase

  • No need to delete the file on disk

Step 7: GOOGLE_REVERSED_CLIENT_ID by environment

Add to all 9 .xcconfig files:

The value comes from the REVERSED_CLIENT_ID field in each GoogleService-Info.plist file.

Edit <path-to-your-project>/ios/Runner/Info.plist:

Step 8: Change App Name by flavor

Add to all 9 .xcconfig files:

Edit ios/Runner/Info.plist:

Run app by flavor (iOS/Android)

Method 1: Run debug from terminal

Method 2: Run via IDE / Xcode

  • Android Studio/VS Code:

    • Configuration > Edit

    • Fill the matching Build flavor

    • Choose the matching entry file for each environment

    Run app by Build flavor in IDE
  • Xcode:

    • Choose the correct scheme dev / staging / production

    • Run directly with that scheme

Note: Instead of creating 3 apps, you can simplify it to 2 apps for 2 environments to reduce setup effort.

Conclusion

Above is how I separate familiar environments (dev, staging, production) into 3 separate applications. Here is the result:

If you want to standardize from the start for your team, combine this with the Base Project article to build your own project template:

atomBase Projectchevron-right

Buy Me a Coffeearrow-up-right | Support Me on Ko-fiarrow-up-right

Last updated