How to set up multiple Firebase environments in a Flutter app

When building a mobile app, it's pretty bad practice to do your development and testing work using data that real users are interacting with. Most developers have some kind of test or staging environment which can be used during development and testing, alongside a production environment for real users.

If you're using Firebase in your Flutter project, it can be pretty tricky to set this up. But I promise - taking an hour of your time to separate your environments up-front is much better than spending a weekend trying to clean up the mess after you accidentally deleted all your production data during development.

The steps

  1. Create Firebase Projects
  2. Set up Firebase in your app
  3. Set up Android configuration
  4. Set up iOS configuration
  5. Run or build using the correct flavor

Step 1: Create Firebase Projects

You'll need to create 2 Firebase projects: one for your production environment, and another for your staging environment.

Within each project, add iOS and Android apps in the usual way, and download the configuration files (google-services.json for Android, and GoogleService-Info.plist for iOS). Remember somehow which configuration files correspond to which project. Maybe keep them in subfolders in your Downloads folder for now.

Set up any Firebase products you need in each project (e.g. Cloud Firestore, Analytics, Authentication).

Step 2: Set up Firebase in your app

Follow the setup steps linked here to integrate Firebase into your app, including the platform-specific setup guides for iOS and Android. However, don't add the configuration files yet.

Step 3: Android configuration setup

We first need to create product flavors for the staging and production environments. In the android/app/build.gradle file, in the android section, add the following:

flavorDimensions "env"
productFlavors {
	production {
		dimension "env"
	}
	staging {
		dimension "env"
	}
}

Then, copy the google-services.json files we downloaded earlier into the following directories:

  • Production: android/app/src/production
  • Staging: android/app/src/staging

That's it!

Step 4: iOS Configuration Setup

Add your PLIST files

Take the GoogleService-Info.plist files we downloaded from Firebase earlier and rename them as follows:

  • Staging: GoogleService-Info-stg.plist
  • Production: GoogleService-Info-prod.plist

Then, create a directory under ios/Runner called Firebase, and move the PLIST files into that folder. Don't use Xcode for this step!

Next, open Xcode and drag the Firebase directory we just created into the project.

Be sure to uncheck "Copy items if needed", and all targets under "Add to targets".

Create custom schemes

In Xcode, go to Product → Scheme → Manage Schemes and use the + button to create two new schemes, targeting "Runner", named production and staging.

Make sure the Shared checkbox is enabled for each of these new schemes.

Now select the Runner project and check that you have the following configurations set up:

Add a new Run Script build phase

Select the Runner target in Xcode and go to Build Phases. Use the + button to add a new Run Script phase, and paste the following script:

PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app

if [ "${CONFIGURATION}" == "Debug-staging" ] || [ "${CONFIGURATION}" == "Release-staging" ] || [ "${CONFIGURATION}" == "Profile-staging" ]; then
cp -r "${PROJECT_DIR}/Runner/Firebase/GoogleService-Info-stg.plist" "${PLIST_DESTINATION}/GoogleService-Info.plist"
echo "Staging plist copied"
elif [ "${CONFIGURATION}" == "Debug-production" ] || [ "${CONFIGURATION}" == "Release-production" ] || [ "${CONFIGURATION}" == "Profile-production" ]; then
cp -r "${PROJECT_DIR}/Runner/Firebase/GoogleService-Info-prod.plist" "${PLIST_DESTINATION}/GoogleService-Info.plist"
echo "Production plist copied"
fi

This script will copy the relevant PLIST file into the final app binary.

Step 5: Run or build using the correct flavor

Now, whenever you run or build the app, simply add --flavor staging or --flavor production to the command to specify which flavor you need.

Peter Bryant

Peter Bryant

York, UK