TobiasBuchholz / Plugin.Firebase

Wrapper around the native Android and iOS Firebase Xamarin SDKs
MIT License
211 stars 49 forks source link

NSInternalInconsistencyException when using DI and not Shell #201

Closed Bindslev closed 1 year ago

Bindslev commented 1 year ago

I'm using dependency injection in .NET MAUI following the example here: MauiDependencyInjectionSample by jfversluis

To make it short, my App.xaml.cs class looks like this:

public App(MainPage mainPage)
    {
        InitializeComponent();
                 MainPage = mainPage;
    }

Instead of making a new AppShell instance. However, this is now giving me troubles with this plugin and I'm getting the following error:

Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: The default FirebaseApp instance must be configured before the default Authinstance can be initialized. One way to ensure this is to callFirebaseApp.configure()in the App Delegate'sapplication(_:didFinishLaunchingWithOptions:)(or the@mainstruct's initializer in SwiftUI).

My MauiProgram.cs looks like so:

private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
    {
        builder.ConfigureLifecycleEvents(events =>
        {
#if IOS
            events.AddiOS(iOS => iOS.FinishedLaunching((_, _) =>
            {
                Plugin.Firebase.Core.Platforms.iOS.CrossFirebase.Initialize();
                return false;
            }));
#endif
#if __ANDROID__
            events.AddAndroid(android => android.OnCreate((activity, _) =>
            {
                Plugin.Firebase.Core.Platforms.Android.CrossFirebase.Initialize(activity);
            }));
#endif
        });

        builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);
        builder.Services.AddSingleton(_ => CrossFirebaseFirestore.Current);
        builder.Services.AddSingleton(_ => CrossFirebaseAnalytics.Current);
        builder.Services.AddSingleton(_ => CrossFirebaseCloudMessaging.Current);

        CrossFirebaseCloudMessaging.Current.CheckIfValidAsync();

        return builder;
    }

The line of code that throws the exception is this: builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);

Investigating the issue led me to this stackoverflow, where a firebase team member has a suggestion on what the issue might be: the-default-firebaseapp-instance-must-be-configured-before-the-defaultfirebaseap

However, I don't see the runtime message that indicates that there are multiple definitions of firebaseauth.

I'm only targeting android and IOS and I'm on .NET 7

Any idea what could be causing this?

TobiasBuchholz commented 1 year ago

Hmm, your code looks fine to me. This error might also appear at a wrongly configured [GoogleService-Info.plist|google-services.json] setup, so make sure it's configured correctly as described in the basic setup instructions.

Bindslev commented 1 year ago

@TobiasBuchholz I have double checked and it seems to be configured correctly as described on that page. I have multiple projects in my solution which has access to firebase through DI, do you think that could cause any issues? I'm asking because it feels like it has to do with DI since I'm no longer creating a new appshell on launch, but simply injecting the mainpage via DI.

Bindslev commented 1 year ago

Alright, I did some testing and I found out that I was accidentally using the IFirebaseUser in the constructor of a class. So, the error message I got

"The default FirebaseApp instance must be configured before the default Authinstance can be initialized"

Was quite precise, since I was trying to use a functionality of this framework before it was initialized. I removed the call from the constructor and the error disappeared. I don't quite understand why this didn't happen to me before the AppShell change, but I'll leave this answer here in case someone else faces this error and accidentally use the library before it's instantiated.