Closed ghensto closed 3 months ago
I have the same requirement so I can comment on this.
My app is configured to use multiple flavors.
As such, I have three sets of package_names / bundle IDs:
com.codewithandrea.flutterfire-flavors.dev
com.codewithandrea.flutterfire-flavors.stg
com.codewithandrea.flutterfire-flavors
Here's how they look like on the Xcode build settings:
And here's how they're set up inside android/app/build.gradle
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.codewithandrea.flutterfire_flavors"
minSdkVersion 16
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
...
flavorDimensions "default"
productFlavors {
production {
dimension "default"
applicationIdSuffix ""
manifestPlaceholders = [appName: "Flutterfire Flavors"]
}
staging {
dimension "default"
applicationIdSuffix ".stg"
manifestPlaceholders = [appName: "[STG] Flutterfire Flavors"]
}
development {
dimension "default"
applicationIdSuffix ".dev"
manifestPlaceholders = [appName: "[DEV] Flutterfire Flavors"]
}
}
Accordingly, I want to have a separate Firebase project for each flavor.
I tried to run flutterfire configure
on my project, but by default it only works with one Firebase project and doesn't take into account the platform-specific configuration.
Here's a log:
✔ Select a Firebase project to configure your Flutter application with · <create a new project>
✔ Enter a project id for your new Firebase project (e.g. my-cool-project) · flutterfire-flavors-dev
i New Firebase project flutterfire-flavors-dev created succesfully.
✔ Which platforms should your configuration support (use arrow keys & space to select)? · android, ios, web, macos
i Firebase android app com.codewithandrea.flutterfire_flavors is not registered on Firebase project flutterfire-flavors-dev.
i Registered a new Firebase android app on Firebase project flutterfire-flavors-dev.
✔ Which ios bundle id do you want to use for this configuration, e.g. 'com.example.app'? · com.codewithandrea.flutterfire-flavors.dev
i Firebase ios app com.codewithandrea.flutterfire-flavors.dev is not registered on Firebase project flutterfire-flavors-dev.
i Registered a new Firebase ios app on Firebase project flutterfire-flavors-dev.
✔ Which macos bundle id do you want to use for this configuration, e.g. 'com.example.app'? · com.codewithandrea.flutterfire-flavors
i Firebase macos app com.codewithandrea.flutterfire-flavors is not registered on Firebase project flutterfire-flavors-dev.
i Registered a new Firebase macos app on Firebase project flutterfire-flavors-dev.
i Firebase web app flutterfire_flavors (web) is not registered on Firebase project flutterfire-flavors-dev.
i Registered a new Firebase web app on Firebase project flutterfire-flavors-dev.
Note how it detected com.codewithandrea.flutterfire_flavors
as the Android app (non-flavored version) and it asked for the bundle ID on iOS and macOS.
flutterfire
should detect if the app is configured with multiple flavors, and ask if I want to use/create a separate Firebase project for each.firebase_options_dev.dart
, firebase_options_staging.dart
, firebase_options_prod.dart
files that can be imported in each of the entry points (in my case I have main_development.dart
, main_staging.dart
, main_production.dart
).Note: I use very_good_cli to automate the process of creating an app with multiple flavors, but the same applies if multiple flavors are created manually.
As it stands, the only reliable way of getting this to work is to:
flutterfire configure
on eachfirebase_options.dart
into the main Flutter app for each flavorIt can be done, but it's error prone and the whole point of flutterfire is to automate all this configuration.
Any serious project would use multiple flavors, so I believe this is a very important feature to add.
This is technically possible already with using the CLI flags, e.g.:
flutterfire config \
--project=mycoolproject-dev \
--out=lib/firebase_options_dev.dart \
--ios-bundle-id=com.codewithandrea.flutterfire-flavors.dev \
--macos-bundle-id=com.codewithandrea.flutterfire-flavors.dev \
--android-app-id=com.codewithandrea.flutterfire-flavors.dev
So the options are already in place - albeit maybe a little manual
If someone would like to PR to make this less manual then please do :)
@Salakar that's great! That already takes much of the pain away as it needs to be run 3 times but at least it can be automated.
I'm going to close this now since I think this is essentially covered now with the above flags and along with the recent addition of the --yes
flag (to skip prompts and accept defaults). Meaning this can be automated, e.g. defining commands in melos scripts to switch environments
@Salakar that is not a solution, as there is no documentation describing how to do that, nor it seems trivial.
Running flutterfire config
also creates a firebase_app_id_file.json
file that needs to exist in each of android
and ios
folder. This file doesn't seem to allow for flavors
, so I can't have them scoped like firebase_app_id_file_development.json
.
I agree with @JCQuintas. Plus those files were not generated by the first version of FlutterFire CLI, and when I delete google_services.json
and the corresponding plugin configuration from android/app/build.gradle
, and the firebase_app_id_file.json
file from ios
, everything seems to work fine without them. Why were those files added by default? What is their purpose? And if they are absolutely useful, you need to add command-line arguments to make it possible to override where these files will be generated so that they don't overwrite the last version when I run flutterfire configure
for each of my flavor projects.
Unfortunately these firebase_app_id_file.json
files and .gradle file updates are required for native builds if you want certain plugins (like Analytics, Crashlytics & Performance) to function correctly on Android, iOS & macOS. Since these interact with native builds there isn't really a way to make them environment specific since the CLI would be unware of your Android/iOS build targets etc. Open to suggestions/pull requests on these.
Having said that, in the latest release I've just shipped two new flags (hidden), --no-apply-gradle-plugins
and --no-app-id-json
- which will disable these files being generated/changed should you need to opt-out, though I'd caution against doing so unless you know what you're doing with configuring the native parts of Android / iOS to work properly with the Firebase services mentioned above.
The first thing is to document why those files can be necessary. For example, in the CLI documentation, on the line about --[no-]apply-gradle-plugin
there should be a mention explaining why you might not need to apply the gradle plugin and create the google-services.json file. There are a lot of projects that only use firebase core, auth and firestore, but not analytics, crashlytics and performance.
Second of all, there should be an equivalent option to this one for the app-id-json and that's great that you added that. Is it already in the current version, but just undocumented?
You could also make it so that flutterfire configure
doesn't generate any of those files by default, and then add a command to flutterfire that adds those files for native plugins, something like flutterfire configure-native-plugins
, but maybe that's overkill.
Then the most important thing is to make is possible to customize the path and the name of those files, just like -out
lets us do it for firebase_options.dart
. I use that already to have 3 versions of this file in my project, one for each environment/flavor, that I import into each of my main.dart
s. In Android, google-services-json could be stored in flavor-specific subdirectories (android/app/src/dev
or android/app/src/prod
instead of the default android/app
) so that Gradle picks up on the right version depending on the flavor. So maybe a command-line parameter like -android-native-out
that accepts a full path for google-services.json.
And finally, I would like a command line parameter to customize where the app id json file is generated for ios, path and file name as well, which would allow me to have different versions of that file for my different environments. And then because Firebase native libraries look for this file in a specific place with a specific name, I can have a script in my XCode build pipeline that picks up the proper version of the file and copies it where Firebase is expecting it to be. That's already what we did for flavor builds before. Agreed, you don't need to document that process in the CLI documentation, but giving that option makes it more flexible.
By the way, I'm preparing a step-by-step tutorial on how to flavorize a Flutter project including web support and firebase support, so if those options are added, I will also document them there.
By the way, I just tried to add the --no-apply-gradle-plugin
flag, as described in the CLI documentation, but I got an error: Could not find an option named "no-apply-gradle-plugin"
And indeed, it is not documented in flutterfire help configure
By the way, I just tried to add the
--no-apply-gradle-plugin
flag, as described in the CLI documentation, but I got an error:Could not find an option named "no-apply-gradle-plugin"
And indeed, it is not documented in
flutterfire help configure
--no-apply-gradle-plugins
(plural on plugins) there's an update for the docs waiting to fix the docs but we're in a docs change freeze right now sorry 🙈 it's a hidden flag so won't show on help commands currently but it is there - hidden until properly documented since we don't want anyone using it without knowing the full implications
Thanks for all the input previously also, I can certainly add options to change the output paths for both json files so let me look into that, the only caveat to this is that we need to note on the CLI that if you do this it won't work by default and you shouldn't do it unless you know what you're doing.
--no-app-id-json
also exists in current version released yesterday, also hidden currently so won't show in --help
. I wonder perhaps if these two flags should become one flag, something like --[no-]native-integration
since effectively similar just ones for android and one ios.
@Salakar In our app we have defined two flavors (ios schemes) but only one Firebase project. How can we achieve to have firebase_app_id_file.json
per scheme?
One of the older project we have defined custom Build Phase which will copy correct GoogleServices.plist into project based on current scheme. Do we need something similar?
Hey guy, as long as the flutterfire_cli does not support multiple schemes for the firebase_app_id_file.json
, can we keep using our old google-services.json
and the GoogleService-Info-***.plist
files with the new version of firebase_core (^1.16.0) and firebase_crashlytics (^2.7.2), or is it better to revert to previous versions?
Don't know anyone who doesn't use flavors for the production app, so this issue should be a priority otherwise what's the point.
@GitHelge Yes it works, if you set up Firebase the old way.
For all who are searching for a solution (also working in pipelines):
# Install Firebase-CLI
curl -sL firebase.tools | bash
# Install FlutterFire CLI
flutter pub global activate flutterfire_cli
# Configure FlutterFire for ios, android and web
flutterfire configure -y --project MYAPP-$SCHEME --android-app-id=$BUNDLE_ID --ios-bundle-id=$BUNDLE_ID --macos-bundle-id=$BUNDLE_ID --platforms=android,ios,web
Edit: I suppose you to know how to handle flavors with flutter_flavorizr to use this solution!
Flutter Flavors are a feature of flutter overall that the CLI is completely oblivious to at the moment. We are going to have to stay on an older version of firebase, but as customers of firebase this is a major blocker to being able to adopt some of the new features.
If you check out this article that I published recently, you will see that it's possible to work around it. The article is now also referenced in the documentation.
@sarbogast this doesn't solve the issue with firebase_app_id_file.json file being not flavoured.
No but you only need this file in certain not so frequent situations. So at the very least for now you can disable its generation when you don't need it. Hopefully at some point we can customize its name and use a script to copy the right one. Or the libraries that need it for now won't need it anymore.
I used https://medium.com/@animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b method to copy google-services.json with the old method. Maybe, something similar should work for the firebase_app_id_file.json.
Something like :
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
FIREBASEPPID_INFO_PLIST=firebase_app_id_file.json
FIREBASEPPID_INFO_FILE=${PROJECT_DIR}/config/${environment}/${FIREBASEPPID_INFO_PLIST}
# Make sure firebase_app_id_file.json exists
echo "Looking for ${FIREBASEPPID_INFO_PLIST} in ${FIREBASEPPID_INFO_FILE}"
if [ ! -f $FIREBASEPPID_INFO_FILE ]
then
echo "No firebase_app_id_file.json found. Please ensure it's in the proper directory."
exit 1
fi
# Get a reference to the destination location for the firebase_app_id_file.json
# This is the default location of firebase_app_id_file.json file
PLIST_DESTINATION=${PROJECT_DIR}
echo "Will copy ${FIREBASEPPID_INFO_PLIST} to final destination: ${PLIST_DESTINATION}"
# Copy over the prod firebase_app_id_file.json for Release builds
cp "${FIREBASEPPID_INFO_FILE}" "${PLIST_DESTINATION}"
Also instead of executed at the build phase, it should probably be place in the Pre-Action of the Scheme.
@Salakar my app was configured last year to use FlutterFire, in a manual process. At each release I always take a look at the Quick Start guide, to see if I need to change some configuration, json, gradle, etc.
On the last release the docs were migrated and updated to only have a CLI option for the configurations, but my app has several whitelabel versions and stages, which I can't find a documentation on how to configure those.
I think there are 2 scenarios here:
Multiple Apps on the same project. This will happen with whitelabel apps, or free and paid versions of the same app, where they have different package ids/bundle ids, but they all use the same crashlytics or remote config.
Multiple Apps on different projects. This will happen with different stages of release (development, tests, production), so we could have a database segregation and not impact customers if we are playing with the database.
The CLI must support both of these scenarios, which can include flavors and dimensions on Android or Schemes and Targets on iOS. I can't see how could I configure 4 different Android package ids for the same project using the flags you provided before, as I have several flavors and dimensions.
For now I just updated the packages versions on pubspec.yaml, but since I can't run the CLI and have dart initialization, I imagine my Crashlytics reports won't be optimized for Flutter.
Unfortunately these firebase_app_id_file.json files and .gradle file updates are required for native builds if you want certain >plugins (like Analytics, Crashlytics & Performance) to function correctly on Android, iOS & macOS.
I am using Crashlytics (who Flutter/Firebase developer isn't?) so if I understood this correctly, I cannot remove google-services.json
from my Android project after all. It is unclear can I still remove google-services
related stuff from .gradle
files as documented here. From the iOS project I can remove GoogleService-Info.plist
, but I need to add a similar file firebase_app_id_file.json
. So things do not get any simpler with iOS either especially with the flavors I have already configured years ago.
So I need google-services.json
and similar config file for iOS as earlier, plus now there is also a new file firebase_options.dart
which only contains duplicate information to what is already available in google-services.json
and GoogleService-Info.plist
(or firebase_app_id_file.json
).
Maybe and hopefully this new command line tool helps new Flutter developers, but for me this seems only like a new problem and more work without any additional value.
UPDATE:
It seems that GoogleService-Info.plist
cannot be removed either. It is required by at least the plugin google_sign_in
(there is no Firebase app without google_sign_in
). Debug log also has other warnings from Firebase/Core and Firebase/Analytics complaining that GoogleService-Info.plist
cannot be found. So I really don't understand what is this new documentation about "Dart-only initialization". It is not possible for a real world Flutter/Firebase app.
I summarized my findings and suggestions here: https://github.com/invertase/flutterfire_cli/issues/85
Just to resume a bit the discussion for a typical simple project with dev and prod (no staging here to make it simple) :
When running firebasecli configure:
firebase_options.dart
created in the dart directorygoogle-services.json
and GoogleService-Info.plist
created in the native directoriesThe following command allows to create multiple versions of the json and plist:
flutterfire config \
--project=mycoolproject-dev \
--out=lib/firebase_options_dev.dart \
--ios-bundle-id=com.mycoolproject.app.dev \
--macos-bundle-id=com.mycoolproject.app.dev \
--android-app-id=com.mycoolproject.app.dev
However this is necessary only for crashalytics and and analytics. In the event that someone only has dev and prod, where dev does not need crashalytics nor analytics, the following strategy can be used:
firebase_options_dev
that will be used by the dev version Is the above correct ?
I am not sure how those commands will deal with flavors, since we need multiple json/plist in different native folders. Example: one json in the Android prod folder and another in the dev folder.
All that is needed if for the command to let us customize the path and/or name of those files so that we can then add our own scripts to copy the right version to the location and name expected by the native plugins, just like we used to do with legacy configuration.
Could a PR eventually land to remove the need for the json and plist files eventually ? Similar to this one https://github.com/flutter/plugins/pull/5250
@bizz84 what's your thoughts on this now?
For what it's worth, I resolved this issue by running flutterfire config
multiple times. if you run flutterfire configure once for each flavor, and then move the resulting google-services.json
into android/app/src/${flavorName}
, then the build succeeds for each flavor. A big caveat here is that I have only tested this on Android so far, not on iOS. I haven't looked into what steps will be necessary to get the different flavors working on iOS with flutterfire.
For android it does work like you said @sdstolworthy but for iOS the cli only outputs one file ios/firebase_app_id_file.json
and it will overwrite it each time. We can manually fix it for iOS.
There is a warning printed when doing pod install
:
Warning: firebase_app_id_file.json file does not exist. This may cause issues in upload-symbols. If this error is unexpected, try running flutterfire configure again.
I guess it can be ignored as long as you're sure you have set things up correctly.
What I did:
ios/firebase_app_id_file.json
file into my respective flavor folder each time. This is the same folder I store my GoogleService-Info.plist
file for each flavor.
ios/Runner/Firebase/Prod/firebase_app_id_file.json
ios/Runner/Firebase/Sandbox/firebase_app_id_file.json
firebase_app_id_file.json
file into the root ios/
folder, just like the one for GoogleService-Info.plist
works.main.dart
I use package_info_plus
to know my package name to determine what flavor is running and configure firebase with the correct file accordingly:
import 'package:app/firebase_options_prod.dart';
import 'package:app/firebase_options_sandbox.dart';
import 'package:package_info_plus/package_info_plus.dart';
Future
final isSandbox = packageInfo.packageName == 'com.myapp.sandbox';
await Firebase.initializeApp( options: isSandbox ? firebase_sandbox.DefaultFirebaseOptions.currentPlatform : firebase_prod.DefaultFirebaseOptions.currentPlatform, ); }
Here is my run script I used:
```sh
# Name of the resource we're selectively copying
FIREBASE_APP_ID_FILE=firebase_app_id_file.json
# Get references to sandbox and prod versions of firebase_app_id_file.json
# NOTE: These should only live on the file system and should NOT be part of the target (since we'll be adding them to the target manually)
FIREBASE_APP_ID_FILE_SANDBOX=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Sandbox/${FIREBASE_APP_ID_FILE}
FIREBASE_APP_ID_FILE_PROD=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Prod/${FIREBASE_APP_ID_FILE}
# Make sure the sandbox version of firebase_app_id_file.json exists
echo "Looking for ${FIREBASE_APP_ID_FILE} in ${FIREBASE_APP_ID_FILE_SANDBOX}"
if [ ! -f $FIREBASE_APP_ID_FILE_SANDBOX ]
then
echo "No sandbox firebase_app_id_file.json found. Please ensure it's in the proper directory."
exit 1
fi
# Make sure the prod version of firebase_app_id_file.json exists
echo "Looking for ${FIREBASE_APP_ID_FILE} in ${FIREBASE_APP_ID_FILE_PROD}"
if [ ! -f $FIREBASE_APP_ID_FILE_PROD ]
then
echo "No prod firebase_app_id_file.json found. Please ensure it's in the proper directory."
exit 1
fi
# Get a reference to the destination location for firebase_app_id_file.json
FILE_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo "Will copy ${FIREBASE_APP_ID_FILE} to final destination: ${FILE_DESTINATION}"
# Copy over the correct firebase_app_id_file.json for the current build configuration
if [ "${CONFIGURATION}" == "Debug-prod" ] || [ "${CONFIGURATION}" == "Release-prod" ] || [ "${CONFIGURATION}" == "Profile-prod" ]
then
echo "Using ${FIREBASE_APP_ID_FILE_PROD}"
cp "${FIREBASE_APP_ID_FILE_PROD}" "${FILE_DESTINATION}"
elif [ "${CONFIGURATION}" == "Debug-sandbox" ] || [ "${CONFIGURATION}" == "Release-sandbox" ] || [ "${CONFIGURATION}" == "Profile-sandbox" ]
then
echo "Using ${FIREBASE_APP_ID_FILE_SANDBOX}"
cp "${FIREBASE_APP_ID_FILE_SANDBOX}" "${FILE_DESTINATION}"
else
echo "Error: invalid configuration specified: ${CONFIGURATION}"
fi
At build/run time, it all works as expected because there's only one ios/firebase_app_id_file.json
file and it's in the correct spot at build time thanks to the run script. Depending which flavor I select, it copies the right one into place just like it does for the GoogleService-Info.plist
file.
This is a tough thing to solve in the cli tool because flavors are by design such a flexibly-implemented thing - people use all sorts of different approaches. I think there might just need to be a good doc page outlining the approach for setting it up for flavors and it's up to the user to adapt it to their specific implementation.
Hello,
One of the things I'm missing right here is the option to create a "secured" prod version of the firebase_options.dart file. I mean, I've managed to successfully setup a project using the flutterfire cli with the configure command. However, this just adds a dart file with my keys in plain text. This is obviously fine for local development, but not very recommended for the production build. I would love to have an option where the FirebaseOptions class can read the encrypted keys from a file .json or some other file (e.g. the google-services.json file that can be saved encrypted in a CI/CD tool).
HI @MdeBruin93, the google-service.json
does not contain any confidential data. It's not a problem to commit this and publish it. Especially, for web apps it's super easy to access the google-service.json
. So you don't need to worry about to make the google-service.json
"secure". However, you set up your Firebase security rules and other server side protection to secure your data. See Firebase security checklist for more information.
@russellwheatley great thanks; I hope we can implement live environmental switching; Having the recompile the app is either not an option (for QA teams) or a tremendous waste of time.
@acoutts I'm running a copy script, basically, the same as I do with GoogleService-Info.plist. Can you tell me where in the build Phases you run this script? It seems that it's not there when Crashlytics script starts running.
@loolooii my phases look like this in terms of ordering including my crashlytics one
@acoutts thanks man! It seems you do the copying way earlier, that must have been it. I ended up removing Crashlytics completely, it's nice and all, but I'll wait for it to be supported in the "new way". If not, I will try to do it again some time later. I needed success yesterday 😄
For android it does work like you said @sdstolworthy but for iOS the cli only outputs one file
ios/firebase_app_id_file.json
and it will overwrite it each time. We can manually fix it for iOS.There is a warning printed when doing
pod install
:Warning: firebase_app_id_file.json file does not exist. This may cause issues in upload-symbols. If this error is unexpected, try running flutterfire configure again.
I guess it can be ignored as long as you're sure you have set things up correctly.
What I did:
Ran the configure command multiple times, making sure to copy the
ios/firebase_app_id_file.json
file into my respective flavor folder each time. This is the same folder I store myGoogleService-Info.plist
file for each flavor.
ios/Runner/Firebase/Prod/firebase_app_id_file.json
ios/Runner/Firebase/Sandbox/firebase_app_id_file.json
- Added an xcode run script build phase which copies the correct
firebase_app_id_file.json
file into the rootios/
folder, just like the one forGoogleService-Info.plist
works.- In my
main.dart
I usepackage_info_plus
to know my package name to determine what flavor is running and configure firebase with the correct file accordingly:import 'package:app/firebase_options_prod.dart'; import 'package:app/firebase_options_sandbox.dart'; import 'package:package_info_plus/package_info_plus.dart'; Future<void> main() async { late final PackageInfo packageInfo; try { packageInfo = await PackageInfo.fromPlatform(); } catch (e, s) { /// Fallback value packageInfo = PackageInfo( appName: 'MyApp', packageName: 'com.myapp.prod', buildNumber: '0', version: '0.0.0', ); } final isSandbox = packageInfo.packageName == 'com.myapp.sandbox'; await Firebase.initializeApp( options: isSandbox ? firebase_sandbox.DefaultFirebaseOptions.currentPlatform : firebase_prod.DefaultFirebaseOptions.currentPlatform, ); }
Here is my run script I used:
# Name of the resource we're selectively copying FIREBASE_APP_ID_FILE=firebase_app_id_file.json # Get references to sandbox and prod versions of firebase_app_id_file.json # NOTE: These should only live on the file system and should NOT be part of the target (since we'll be adding them to the target manually) FIREBASE_APP_ID_FILE_SANDBOX=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Sandbox/${FIREBASE_APP_ID_FILE} FIREBASE_APP_ID_FILE_PROD=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Prod/${FIREBASE_APP_ID_FILE} # Make sure the sandbox version of firebase_app_id_file.json exists echo "Looking for ${FIREBASE_APP_ID_FILE} in ${FIREBASE_APP_ID_FILE_SANDBOX}" if [ ! -f $FIREBASE_APP_ID_FILE_SANDBOX ] then echo "No sandbox firebase_app_id_file.json found. Please ensure it's in the proper directory." exit 1 fi # Make sure the prod version of firebase_app_id_file.json exists echo "Looking for ${FIREBASE_APP_ID_FILE} in ${FIREBASE_APP_ID_FILE_PROD}" if [ ! -f $FIREBASE_APP_ID_FILE_PROD ] then echo "No prod firebase_app_id_file.json found. Please ensure it's in the proper directory." exit 1 fi # Get a reference to the destination location for firebase_app_id_file.json FILE_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app echo "Will copy ${FIREBASE_APP_ID_FILE} to final destination: ${FILE_DESTINATION}" # Copy over the correct firebase_app_id_file.json for the current build configuration if [ "${CONFIGURATION}" == "Debug-prod" ] || [ "${CONFIGURATION}" == "Release-prod" ] || [ "${CONFIGURATION}" == "Profile-prod" ] then echo "Using ${FIREBASE_APP_ID_FILE_PROD}" cp "${FIREBASE_APP_ID_FILE_PROD}" "${FILE_DESTINATION}" elif [ "${CONFIGURATION}" == "Debug-sandbox" ] || [ "${CONFIGURATION}" == "Release-sandbox" ] || [ "${CONFIGURATION}" == "Profile-sandbox" ] then echo "Using ${FIREBASE_APP_ID_FILE_SANDBOX}" cp "${FIREBASE_APP_ID_FILE_SANDBOX}" "${FILE_DESTINATION}" else echo "Error: invalid configuration specified: ${CONFIGURATION}" fi
At build/run time, it all works as expected because there's only one
ios/firebase_app_id_file.json
file and it's in the correct spot at build time thanks to the run script. Depending which flavor I select, it copies the right one into place just like it does for theGoogleService-Info.plist
file.This is a tough thing to solve in the cli tool because flavors are by design such a flexibly-implemented thing - people use all sorts of different approaches. I think there might just need to be a good doc page outlining the approach for setting it up for flavors and it's up to the user to adapt it to their specific implementation.
this would be a better script:
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
FIREBASE_APP_ID_JSON=firebase_app_id_file.json
FIREBASE_APP_ID_FILE=${PROJECT_DIR}/Config/${environment}/${FIREBASE_APP_ID_JSON}
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
# Make sure firebase_app_id_file.json exists
echo "Looking for ${FIREBASE_APP_ID_JSON} in ${FIREBASE_APP_ID_FILE}"
if [ ! -f $FIREBASE_APP_ID_FILE ]
then
echo "No firebase_app_id_file.json found. Please ensure it's in the proper directory."
exit 1
fi
FIREBASE_PLIST_JSON_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
# 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
echo "Will copy ${GOOGLESERVICE_INFO_PLIST} to final destination: ${FIREBASE_PLIST_JSON_DESTINATION}"
# Get a reference to the destination location for the firebase_app_id_file.json
# This is the default location where Firebase init code expects to find firebase_app_id_file.json file
echo "Will copy ${FIREBASE_APP_ID_JSON} to final destination: ${FIREBASE_PLIST_JSON_DESTINATION}"
# Copy over the prod GoogleService-Info.plist for Release builds
cp "${GOOGLESERVICE_INFO_FILE}" "${FIREBASE_PLIST_JSON_DESTINATION}"
# Copy over the prod firebase_app_id_file.json for Release builds
cp "${FIREBASE_APP_ID_FILE}" "${FIREBASE_PLIST_JSON_DESTINATION}"
any update to configure the flavors using the cli directly?
Hey folks, we're looking to update the CLI to help users who require multiple environment setup. The biggest concern for us regards the different approaches to setting up build types/flavors/schemes. We don't want to make assumptions about your particular setup. We propose exposing 3 new options which allow you to choose where to write the service file (“Google-Service-Info.plist” for iOS/macOS & “google-services.json” for Android). So for instance, you could write:
flutterfire configure \
--project=mycoolproject-dev \
--out=lib/firebase_options_dev.dart \
--ios-bundle-id=com.codewithandrea.flutterfire-flavors.dev \
--macos-bundle-id=com.codewithandrea.flutterfire-flavors.dev \
--android-app-id=com.codewithandrea.flutterfire-flavors.dev \
--ios-out=/ios/directory/Google-Service-Info.plist \
--android-out=/android/directory/google-services.json \
--macos-out=/macos/directory/Google-Service-Info.plist \
This allows you to choose the path and the name of the file. According to the documentation for setting up multi-projects for android, it seems fairly straight forward configuring different environments. You just write the file to the relevant build type directory:
app/
google-services.json
src/development/google-services.json
src/release/google-services.json
...
iOS is more involved, Firebase recommends two methods in the the documentation:
Either:
There is also a third solution that would require having a build script to inject the correct Google-Service-Info.plist
. This would be a better way if you only use one target in your project.
Let me know what you think. Thanks.
Let me see if we are in the same page.
If I have a white label app, that turns out to be 2 different apps in production, with 2 different Android ids, I will have to run the CLI once for each of my Android apps, and the last time I run the CLI, it won't interfere with the previous times I have run it, and configured the other Android apps?
I want to be sure running the CLI multiple times, for different Android apps, won't mess up any previous configuration of other apps, since I have 3 android and 3 ios apps, generated from the same source code, just changing the app's IDs, names and icons.
Hey folks, we're looking to update the CLI to help users who require multiple environment setup. The biggest concern for us, regards the different approaches to setting up build types/flavors/schemes. We don't want to make assumptions about your particular setup. We propose exposing 3 new options which allow you to choose where to write the service file (“Google-Service-Info.plist” for iOS/macOS & “google-services.json” for Android). So for instance, you could write:
flutterfire config \ --project=mycoolproject-dev \ --out=lib/firebase_options_dev.dart \ --ios-bundle-id=com.codewithandrea.flutterfire-flavors.dev \ --macos-bundle-id=com.codewithandrea.flutterfire-flavors.dev \ --android-app-id=com.codewithandrea.flutterfire-flavors.dev \ --ios-out=/ios/directory/Google-Service-Info.plist \ --android-out=/android/directory/google-services.json \ --macos-out=/macos/directory/Google-Service-Info.plist \
Do we still need the Google-Service-Info.plist
and google-services.json
file when we have the firebase_options_dev.dart
?
Just to note; many of us switch on the login screen via a few different environments; real time. having to use different builds is very painful for QA.
Hey folks, we're looking to update the CLI to help users who require multiple environment setup. The biggest concern for us, regards the different approaches to setting up build types/flavors/schemes. We don't want to make assumptions about your particular setup. We propose exposing 3 new options which allow you to choose where to write the service file (“Google-Service-Info.plist” for iOS/macOS & “google-services.json” for Android). So for instance, you could write:
flutterfire config \ --project=mycoolproject-dev \ --out=lib/firebase_options_dev.dart \ --ios-bundle-id=com.codewithandrea.flutterfire-flavors.dev \ --macos-bundle-id=com.codewithandrea.flutterfire-flavors.dev \ --android-app-id=com.codewithandrea.flutterfire-flavors.dev \ --ios-out=/ios/directory/Google-Service-Info.plist \ --android-out=/android/directory/google-services.json \ --macos-out=/macos/directory/Google-Service-Info.plist \
The most important option would be that this tool does not write the service files at all and most importantly does not access my Firebase projects in the cloud in any way (for security reasons). I am developing my app actively and publishing updates almost monthly. I have updated the service files total of two times during the lifetime of my app and the last time I updated them was in June 2019. So it really is not a problem to download and update those files manually when needed as I have already done last 3 years. I don't have anything against automation, but in my opinion this is not a place where automation is really needed especially because it only causes security concerns. Well, I don't know if this tool can do anything useful if it cannot access the Firebase projects in cloud, but that's why I suggested to Add documentation how to use FlutterFire packages the old way without this tool (and keep the documentation up to date) which is still my preferred option.
Let me see if we are in the same page.
If I have a white label app, that turns out to be 2 different apps in production, with 2 different Android ids, I will have to run >the CLI once for each of my Android apps, and the last time I run the CLI, it won't interfere with the previous times I have >run it, and configured the other Android apps?
I want to be sure running the CLI multiple times, for different Android apps, won't mess up any previous configuration of other apps, since I have 3 android and 3 ios apps, generated from the same source code, just changing the app's IDs, names and icons.
Hey @feinstein, the idea is that it will grab the config from the Firebase Server and write to where ever you want it in your project setup with whatever file name you choose. They are independent file writes and won't interfere with each other. The setup part depends on how you've set it up. Firebase has its recommended way of setup for android flavors, not sure how else to set it up other than that method if that answers your question.
Do we still need the
Google-Service-Info.plist
andgoogle-services.json
file when we have thefirebase_options_dev.dart
?
Hey @erf, The service file is used before dart is initialized on native apps, therefore, the Dart config initialization code is ignored as default app has already been setup. We were thinking of removing android, iOS & macOS dart initialisation code from flutterfire configure
, but some users use it for second app initialization as you can change certain aspects like RTDB & Auth URL to a different address in your Firebase project.
Hey @kinex, you can find manual installation here. You don't have to use flutterfire configure
.
Do we still need the
Google-Service-Info.plist
andgoogle-services.json
file when we have thefirebase_options_dev.dart
?Hey @erf, The service file is used before dart is initialized on native apps, therefore, the Dart config initialization code is ignored as default app has already been setup. We were thinking of removing android, iOS & macOS dart initialisation code from
flutterfire configure
, but some users use it for second app initialization as you can change certain aspects like RTDB & Auth URL to a different address in your Firebase project.
Hey @russellwheatley i thought the Dart initialization would take over for the service file..? I liked the idea of adding multiple targets using pure Dart via --target=lib/main_dev.dart
and --target=lib/main_prod.dart
, which would load the appropriate firebase_options_{prod|dev}.dart
file. So much easier than using multiple schemes.
We wanted to move towards dart initialization, @erf. But there are too many unforeseen issues. Ultimately, we don't control how each Firebase product uses the service file, and it appears they are needed in certain circumstances.
@russellwheatley so the call to Firebase.initializeApp
given custom options
does not have any effect now? Will that argument be removed in the future?
Hey @kinex, you can find manual installation here. You don't have to use
flutterfire configure
.
The website has lots of warnings at the top, saying the content is not guaranteed to be updated and the manual configuration is not recommended, so when I read this, I get full of FUD that my project will be unstable.
Could you give some more details on what exactly it is you're looking for?