Oliver Dixon
Oliver Dixon

Reputation: 7424

Switching between multiple Firebase projects/environments in Flutter?

Has anyone figure out how to switch Firebase project/environments inside the app, say you had a drop down with different dev URLs. We are not talking about different builds, that won't work for us and would require sending multiple versions to TestFlight.

There's a snippet of code we found here.

final options = FirebaseOptions.from({});
final firebaseApp = await FirebaseApp.configure(name: 'some_app_name', options: options);

But we can't figure out how to use it, and don't know if it works correctly.

Edit

It was not officially supported when I wrote this. It now is.

Upvotes: 5

Views: 5693

Answers (2)

Jared Anderton
Jared Anderton

Reputation: 1026

My approach to multiple environments - use multiple projects, and a .env file to determine which to use.

Project setup

  1. I used Flutterfire CLI to set up a Firebase project:
flutterfire configure
  1. After the project is created, I renamed the config files to represent the environment:
mv android/app/google-services.json android/app/google-services-<env>.json
mv ios/firebase_app_id_file.json ios/firebase_app_id_file-<env>.json 
mv lib/firebase_options.dart lib/firebase_options_<env>.dart

Repeat steps 1-2, for each environment you need.

Environment variable setup

  1. Used flutter_dotenv to load an environment variable used to determine the environment: .env:
# Set choose environment. Options: production, stage, etc...
ENVIRONMENT=production
  1. Don't forget to add .env to pubspec.yaml
flutter:
  assets:
    - .env

Connect the environment set in .env

  1. Update main.dart to import env configs, and flutter_dotenv:

main.dart:

import 'firebase_options_prod.dart' as prod;
import 'firebase_options_stage.dart' as stage;
import 'package:flutter_dotenv/flutter_dotenv.dart';
  1. Load .env the following line before you initialize Firebase:

main.dart:

await dotenv.load(fileName: '.env');
  1. Pass in the appropriate config based on the value ENVIRONMENT:

main.dart:

await Firebase.initializeApp(
  options:
    dotenv.env['ENVIRONMENT'] == 'stage' ? stage.DefaultFirebaseOptions.currentPlatform :
    prod.DefaultFirebaseOptions.currentPlatform);

Here is main() in its entirety:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: '.env');
  try {
    await Firebase.initializeApp(
      options:
        dotenv.env['ENVIRONMENT'] == 'stage' ? stage.DefaultFirebaseOptions.currentPlatform :
        prod.DefaultFirebaseOptions.currentPlatform);
  } catch(exception) {
    if(exception is FirebaseException && exception.code == 'duplicate-app') {
      debugPrint("Did you forget to recompile the Runner app, after changing environments?");
    }
    rethrow;
  }
  runApp(const MyApp());
}

Note the try/catch/rethrow added in. I added this because when you change environments, you cannot hot restart. You need to recompile the runner app. If you do not, and then you change environments, Firebase throw an error that looks like this:

Unhandled Exception: [core/duplicate-app] A Firebase App named "[DEFAULT]" already exists

So I wanted an easy reminder of why I might see that error.

Upvotes: 11

Niteesh
Niteesh

Reputation: 3150

final FirebaseApp app = await FirebaseApp.configure(
    name: 'test',
    options: const FirebaseOptions(
      googleAppID: '1:79601577497:ios:5f2bcc6ba8cecddd',
      gcmSenderID: '79601577497',
      apiKey: 'AIzaSyArgmRGfB5kiQT6CunAOmKRVKEsxKmy6YI-G72PVU',
      projectID: 'flutter-firestore',
    ),
  );
  final Firestore firestore = Firestore(app: app); // this line is imp

Use firebase core package for it to work, https://pub.dev/packages/firebase_core For more info: https://firebase.google.com/docs/projects/multiprojects#node.js

Upvotes: 2

Related Questions