firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.68k stars 3.97k forks source link

🐛 [firebase_core] [firebase_auth] No Firebase App '[DEFAULT]' has been created - call initializeApp() first (app/no-app). #12219

Closed mhmzdev closed 8 months ago

mhmzdev commented 8 months ago

Bug report

Describe the bug This works really fine if I'm using flutterfire cli and config any app android/ios/web etc. BUT for one project. If I have to create flavors, I can do that for android and iOS and two separate firebase projects are integrated into the app and I've to integrate firebase manually for android and IOS which makes sense.

For web, since we don't have native flavors in flutter web. Hence, I tried to write down my own service that goes like this:

app_flavors.dart

class AppFlavor {
  static late Flavor flavor;
  static late FirebaseOptions firebaseOptions;
  static late String firebaseProjectName;

  static void init({required Flavor flv}) {
    flavor = flv;

    //
    if (flavor == Flavor.stage) {
      firebaseOptions = adminStage;
      firebaseProjectName = 'project-stage';
    } else {
      firebaseOptions = admin;
      firebaseProjectName = 'project-prod'';
    }
  }

  static const adminStage = FirebaseOptions(
    apiKey: "xxxxxx",
    authDomain: "xxxxxxx",
    databaseURL:
        "xxxxx",
    projectId: "xxxxxx",
    storageBucket: "xxxxx",
    messagingSenderId: "xxxxxx",
    appId: "xxxxxxxx",
    measurementId: "xxxxx",
  );

  static const admin = FirebaseOptions(
    apiKey: "xxxxxx",
    authDomain: "xxxxxxx",
    databaseURL:
        "xxxxx",
    projectId: "xxxxxx",
    storageBucket: "xxxxx",
    messagingSenderId: "xxxxxx",
    appId: "xxxxxxxx",
    measurementId: "xxxxx",
  );
}

And my main.dart becomes this:

main.dart

void main() {
  // removes the '#' in the URL for web
  setPathUrlStrategy();
  setUpLocator();

  runZonedGuarded(
    () async {
      AppFlavor.init(flv: Flavor.stage);

      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp(
        name: AppFlavor.firebaseProjectName,
        options: AppFlavor.firebaseOptions,
      );

      runApp(const MyApp());
    },
    (error, stack) {},
  );
}

But it doesn't work, either the exception is what I've mentioned in the title, or its returning null at Firebase.initializeApp.

Unexpected Behaviour

Another reason why I might be getting this error is my firebase auth service is in a separate package named as engine So, the folders look like this: Screenshot 2024-01-30 at 1 38 07 PM

So, is this correct that we are not able to access our firebase app instances in separate package as we are not intializing them over there but in the main app.

Steps to reproduce

Steps to reproduce the behavior:

  1. Create two firebase proejcts
  2. Add two web app into each of them
  3. Get the firebaseConfigs from project settings
  4. Intialize the flutter web app manually without using flutterfire cli to hit each of them based on any bool or enum

Expected behavior

Although web doesn't support native flavors, but the way firebase is integrated into flutter is same as we integrate one project. It should work if we add any conditional statement to handle two or multiple firebase projects at a time.

Sample project

Shared the code in the above top section.

Additional context

Add any other context about the problem here.


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand ``` [✓] Flutter (Channel stable, 3.13.6, on macOS 14.2.1 23C71 darwin-arm64, locale en-PK) • Flutter version 3.13.6 on channel stable at /Users/hamza/Development/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision ead455963c (4 months ago), 2023-09-26 18:28:17 -0700 • Engine revision a794cf2681 • Dart version 3.1.3 • DevTools version 2.25.0 [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/hamza/Library/Android/sdk • Platform android-34, build-tools 34.0.0 • ANDROID_HOME = /Users/hamza/Library/Android/sdk • ANDROID_SDK_ROOT = /Users/hamza/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 15.0.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15A507 • CocoaPods version 1.14.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231) [✓] VS Code (version 1.85.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.80.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-arm64 • macOS 14.2.1 23C71 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 120.0.6099.234 [✓] Network resources • All expected network resources are available. • No issues found! ```

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand ``` Dart SDK 3.1.3 Flutter SDK 3.13.6 hop_maldives 0.0.0 dev dependencies: - melos 3.4.0 [ansi_styles args cli_launcher cli_util collection conventional_commit file glob graphs http meta mustache_template path platform pool prompts pub_semver pub_updater pubspec string_scanner yaml yaml_edit] transitive dependencies: - ansi_styles 0.3.2+1 - args 2.4.2 - async 2.11.0 [collection meta] - boolean_selector 2.1.1 [source_span string_scanner] - charcode 1.3.1 - cli_launcher 0.3.1 [path yaml] - cli_util 0.4.1 [meta path] - collection 1.18.0 - conventional_commit 0.6.0+1 - file 6.1.4 [meta path] - glob 2.1.2 [async collection file path string_scanner] - graphs 2.3.1 [collection] - http 1.1.0 [async http_parser meta] - http_parser 4.0.2 [collection source_span string_scanner typed_data] - io 1.0.4 [meta path string_scanner] - json_annotation 4.8.1 [meta] - matcher 0.12.16+1 [async meta stack_trace term_glyph test_api] - meta 1.11.0 - mustache_template 2.0.0 - path 1.9.0 - platform 3.1.4 - pool 1.5.1 [async stack_trace] - process 4.2.4 [file path platform] - prompts 2.0.0 [charcode io] - pub_semver 2.1.4 [collection meta] - pub_updater 0.3.1 [http json_annotation process pub_semver] - pubspec 2.3.0 [path pub_semver yaml uri] - quiver 3.2.1 [matcher] - source_span 1.10.0 [collection path term_glyph] - stack_trace 1.11.1 [path] - stream_channel 2.1.2 [async] - string_scanner 1.2.0 [source_span] - term_glyph 1.2.1 - test_api 0.7.0 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph] - typed_data 1.3.2 [collection] - uri 1.0.0 [matcher quiver] - yaml 3.1.2 [collection source_span string_scanner] - yaml_edit 2.1.1 [collection meta source_span yaml] ```

darshankawar commented 8 months ago
void main() {
  // removes the '#' in the URL for web
  setPathUrlStrategy();
  setUpLocator();

  runZonedGuarded(
    () async {
      AppFlavor.init(flv: Flavor.stage);

      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp(
        name: AppFlavor.firebaseProjectName,
        options: AppFlavor.firebaseOptions,
      );

      runApp(const MyApp());
    },

@mhmzdev Can you move the ensureInitialized() and Firebase.initializeApp right before the main() method and try again ?

The intialization should be the first step after main method is called.

Also, does the same reported behavior occur just using barebone flutter app and fresh firebase integration without using any third party package usage / implementation ?

mhmzdev commented 8 months ago

@darshankawar is this what you are asking for?

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  AppFlavor.init(flv: Flavor.stage);

  await Firebase.initializeApp(
    name: AppFlavor.firebaseProjectName,
    options: AppFlavor.firebaseOptions,
  );

  // removes the '#' in the URL for web
  setPathUrlStrategy();
  setUpLocator();

  runZonedGuarded(
    () async {
      runApp(const MyApp());
    },
    (error, stack) {},
  );
}

The error still persist in the auth service as: Screenshot 2024-01-30 at 5 39 40 PM

About second question, if I integrate flutter and firebase in very simplest manner using flutterfire cli it works and there is no trouble at all.

But I just want to resolve the issue for my architecture i.e. we have 3 apps and we need to write only one auth service rather than repeating the logic in all three of them. So, I put it in a separate package and consumed it in all three.

darshankawar commented 8 months ago

Thanks for the update @mhmzdev

Steps to reproduce the behavior:

  1. Create two firebase proejcts
  2. Add two web app into each of them
  3. Get the firebaseConfigs from project settings
  4. Intialize the flutter web app manually without using flutterfire cli to hit each of them based on any bool or enum

I'll try to come up with a setup as mentioned here and see if I am able to replicate the error or not. But meantime, since the issue is specific to your case as you described:

But I just want to resolve the issue for my architecture i.e. we have 3 apps and we need to write only one auth service rather than repeating the logic in all three of them. So, I put it in a separate package and consumed it in all three.

It could be that the error could be occuring due to misconfiguration, but will this issue open for team's input.

mhmzdev commented 8 months ago

Hey @darshankawar , I was able to fix it by writing down my own service for Firebase services itself:

class AppFire {
  static late FirebaseAuth auth;
  static late FirebaseFirestore firestore;
  static late FirebaseStorage storage;

  static void init() {
    try {
      final app = Firebase.app(AppFlavor.firebaseProjectName);

      //
      auth = FirebaseAuth.instanceFor(app: app);
      firestore = FirebaseFirestore.instanceFor(app: app);
      storage = FirebaseStorage.instanceFor(app: app);
    } catch (e) {
      debugPrint(e.toString());
    }
  }
}

And I'm using AppFire.auth and AppFire.firestore rather than FirebaseFirestore.instance and its working beautyfully fine. You may close the issue if you think this is very specific case but not a general one :)

darshankawar commented 8 months ago

Closing as resolved.