skip to Main Content

I recently added Flutter Flavors to my Flutter project because I wanted production, staging, and development environments. I also wanted different Firebase projects for each flavor so I created a config folder with their own each individual folder for each Firebase Project GoogleService-Info.plist files

enter image description here

I also added this Build Phase Script in the Runner Target –

environment="default"
# Regex to extract the scheme name from the Build Configuration
# We have named our Build Configurations as Debug-dev, Debug-prod etc.
# Here, dev and prod are the scheme names. This kind of naming is required by Flutter for flavors to work.
# We are using the $CONFIGURATION variable available in the XCode build environment to extract 
# the environment (or flavor)
# For eg.
# If CONFIGURATION="Debug-prod", then environment will get set to "prod".
if [[ $CONFIGURATION =~ -([^-]*)$ ]]; then
environment=${BASH_REMATCH[1]}
fi
echo $environment
# Name and path of the resource we're copying
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
GOOGLESERVICE_INFO_FILE=${PROJECT_DIR}/config/${environment}/${GOOGLESERVICE_INFO_PLIST}
# Make sure GoogleService-Info.plist exists
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_FILE}"
if [ ! -f $GOOGLESERVICE_INFO_FILE ]
then
echo "No GoogleService-Info.plist found. Please ensure it's in the proper directory."
exit 1
fi

Located here in the Build Phases (the script called ‘Copy GoogleService-Info.plist to the correct location’

enter image description here

I know that these files are not getting used because I have another GoogleService-Info.plist from before I was using Flutter Flavors and only had one Firebase Account.

enter image description here

When I delete the original GoogleService-Info.plist (Not the one’s from the config file) my flutter project complains that it cannot find the GoogleService-Info.plist file. Not sure why this is happening.

I followed this
Medium Tutorial –
https://medium.com/@animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b

and this YouTube video –
https://www.youtube.com/watch?v=Vhm1Cv2uPko

2

Answers


  1. I think you missed adding explicitly config folder to Xcode, to do that, open your iOS folder and drag your ‘config‘ folder into your Xcode (just under the top Runner), then make sure it only creates folder references like this:
    enter image description here

    Then you must see your Xcode navigator like this:
    enter image description here

    Then after that, you can simply remove the original GoogleService-Info.plist and your app without issue.

    There is an issue in your script, please replace your shell script with this:

    environment="default"
    
    # Regex to extract the scheme name from the Build Configuration
    # We have named our Build Configurations as Debug-dev, Debug-prod etc.
    # Here, dev and prod are the scheme names. This kind of naming is required by Flutter for flavors to work.
    # We are using the $CONFIGURATION variable available in the XCode build environment to extract 
    # the environment (or flavor)
    # For eg.
    # If CONFIGURATION="Debug-prod", then environment will get set to "prod".
    if [[ $CONFIGURATION =~ -([^-]*)$ ]]; then
    environment=${BASH_REMATCH[1]}
    fi
    
    echo $environment
    
    # Name and path of the resource we're copying
    GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
    GOOGLESERVICE_INFO_FILE=${PROJECT_DIR}/config/${environment}/${GOOGLESERVICE_INFO_PLIST}
    
    # Make sure GoogleService-Info.plist exists
    echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_FILE}"
    if [ ! -f $GOOGLESERVICE_INFO_FILE ]
    then
    echo "No GoogleService-Info.plist found. Please ensure it's in the proper directory."
    exit 1
    fi
    
    # Get a reference to the destination location for the GoogleService-Info.plist
    # This is the default location where Firebase init code expects to find GoogleServices-Info.plist file
    PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
    echo "Will copy ${GOOGLESERVICE_INFO_PLIST} to final destination: ${PLIST_DESTINATION}"
    
    # Copy over the prod GoogleService-Info.plist for Release builds
    cp "${GOOGLESERVICE_INFO_FILE}" "${PLIST_DESTINATION}"
    
    Login or Signup to reply.
  2. I struggled a lot with this problem, and this was the tutorial that worked best for me: https://demmss.medium.com/creating-development-environments-for-firebase-using-the-very-good-flutterfire-clis-in-flutter-250eba52bd4d

    In XCode:

    1. Save all your GoogleService-Info.plist files somewhere in XCode, like so:
      Folder structure for GoogleService-Info.plist files
    2. Create New Configuration Settings Files in the Flutter folder for each flavor (and release/debug optionally). Note: make sure the files are physically in the Flutter folder and not just in the same Group.

    Folder structure for xcconfig files

    1. In each file, paste the following, replacing the content in []:
    #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.[debug/release].xcconfig"
    #include "Generated.xcconfig"
    // If needed, replace Config/flavor with the your path to the plist file
    GOOGLESERVICE_INFO_PLIST = ${PROJECT_DIR}/Config/[flavor]/GoogleService-Info.plist
    
    1. In your Project Info settings, update all the configurations with these new xcconfig files:

    Configuration settings

    1. In Info.plist, add a new key value pair exactly like so:

    Info.plist file

    1. Update your Build Phase Script with the following code:
    # The destination for plist file
    PLIST_DESTINATION="${PROJECT_DIR}/Runner/GoogleService-Info.plist"
    
    # Copy plist
    echo "Using ${GOOGLESERVICE_INFO_PLIST} ${PLIST_DESTINATION}"
    cp -r "${GOOGLESERVICE_INFO_PLIST}" "${PLIST_DESTINATION}"
    

    These steps worked for me and I was able to see the GoogleService-Info.plist file copied correctly after each build. You can verify by adding --verbose to your launch configuration and searching for the echo output in the debug console of your IDE.

    In the final step, initialize your firebase app with the proper FirebaseOptions in your app startup. I like this implementation inspired by Coding With Andrea:

    import 'package:firebase_core/firebase_core.dart';
    import 'package:my_project/firebase_options.dart' as prod;
    import 'package:my_project/firebase_options_stg.dart' as stg;
    import 'package:my_project/firebase_options_dev.dart' as dev;
    import 'package:flutter/foundation.dart';
    import 'package:flutter/services.dart';
    
    Future<void> initializeFirebaseApp() async {
      final flavor = kIsWeb ? 'production' : appFlavor;
      final firebaseOptions = switch (flavor) {
        'production' => prod.DefaultFirebaseOptions.currentPlatform,
        'staging' => stg.DefaultFirebaseOptions.currentPlatform,
        'development' => dev.DefaultFirebaseOptions.currentPlatform,
        _ => throw Exception('$flavor not supported'),
      };
    
      // Use default app instance. The `name` parameter may cause crash in iOS.
      await Firebase.initializeApp(options: firebaseOptions);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search