Sagar Chopra
Sagar Chopra

Reputation: 45

How can I dynamically change the firebase configurations in .net maui application?

I am working on building a .Net MAUI Application. During the Application initialisation in MAUIProgram.cs, I am registering the firebase services. However after the startup, when the login screen comes, user has an option to choose the configuration (Dev, Prod, Pre). I want to update the firebase configurations based on user selection. By default it is set to Prod during the Initial load because the prod config details are mentioned in the google-services.json and googleservice-info.plist files.

In my google-services.json and Info.plist file , by default the prod Server ID is mentioned which gets initialised in MAUIProgram.cs.

I tried updating the configurations by passing the keys after user selection. But it did not work. I guess IOS does not allow you to update the Info.plist file and Android does not allow to initialize again.

ServerConfigData , ServerCOnfig(URL,Name, ServerID)

  public List<ServerConfig> _Servers = new List<ServerConfig>()
        {
            new ServerConfig("https://prod.mywebsite.com/api/v1", "Prod", 123456789),
            new ServerConfig("https://pre.mywebsite.com/api/v1", "Pre", 123456789),
            new ServerConfig("https://dev.mywebsite.com/api/v1", "Dev", 123456789),     
        };
   

MAUIProgram.cs

private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
        {
            builder.ConfigureLifecycleEvents(events => {
    #if IOS
                events.AddiOS(iOS => iOS.FinishedLaunching((app, launchOptions) => {
                    CrossFirebase.Initialize(app, launchOptions, CreateCrossFirebaseSettings());
                    FirebaseCloudMessagingImplementation.Initialize();
                    return false;
                }));
    #elif ANDROID
                //Firebase.FirebaseOptions options = new Firebase.FirebaseOptions();
    
                events.AddAndroid(android => android.OnCreate((activity, state) =>
                CrossFirebase.Initialize(activity, state, CreateCrossFirebaseSettings())));
    #endif
            });
    
            builder.Services.AddSingleton(_ => CrossFirebaseAuth.Current);
            return builder;
        }

PushMessagingService.cs - Common Code to get token

    public async Task<string> GetNotificationTokenAsync(FirebaseConfig firebaseConfig)
        {
#if WINDOWS
                    return Guid.NewGuid().ToString();
#endif

            // Initialize Firebase based on the selected server configuration
            Firebase.FirebaseOptions opt = new Firebase.FirebaseOptions();
            // Initialize Firebase with the appropriate configuration
#if IOS
            // iOS specific Firebase initialization
            IFirebaseInitializer fb = new EngineerX.Platforms.iOS.FirebaseInitializer();
            fb.InitializeFirebase(firebaseConfig.ApiKey, firebaseConfig.AppId, firebaseConfig.ProjectId);
#elif ANDROID
              // Android specific Firebase initialization
            IFirebaseInitializer fb = new EngineerX.Platforms.Android.FirebaseInitializer();
            fb.InitializeFirebase(firebaseConfig.ApiKey, firebaseConfig.AppId, firebaseConfig.ProjectId);
#endif           
            return await CrossFirebaseCloudMessaging.Current.GetTokenAsync();
        }

FirebaseInitializer.cs - Android specific code to update config

public class FirebaseInitializer : IFirebaseInitializer
{
    public void InitializeFirebase(string apiKey, string appId, string projectId)
    {
        // Update Firebase configuration for Android
        // Initialize Firebase with the new configuration
        FirebaseOptions options = new FirebaseOptions.Builder()
            .SetApiKey(apiKey)
            .SetApplicationId(appId)
            .SetProjectId(projectId)
            .Build();

        FirebaseApp.InitializeApp(Platform.AppContext, options);
    }
   
}

FirebaseInitializer.cs - IOS specific code to update config

public class FirebaseInitializer : IFirebaseInitializer
{
    public void InitializeFirebase(string apiKey, string appId, string projectId)
    {
     
        Firebase.Core.App.Configure(new Options(appId, projectId));
        
    }
}

Upvotes: 0

Views: 777

Answers (1)

Sagar Chopra
Sagar Chopra

Reputation: 45

After some research, I found the answer. The below solution worked for me:

Common Interface

public interface IFirebaseInitializer
 {
     void ReInitializeFirebase(string gcmSenderID);
     
 }

Service Class to implement a method to get notification token:

    public async Task<string> GetNotificationTokenAsync(long gcmServerID)
        {
#if WINDOWS
            return Guid.NewGuid().ToString();
#else
            _firebaseInitializer.ReInitializeFirebase(gcmServerID.ToString());

            // Android specific code to get the notification token
            return await CrossFirebaseCloudMessaging.Current.GetTokenAsync();
#endif
        }

FirebaseInitializer_ios.cs

 public class FirebaseInitializer_iOS : IFirebaseInitializer
 {    
     public void ReInitializeFirebase(string gcmSenderID)
     {
         //created named instance
         if (Firebase.Core.App.DefaultInstance != null)
         {
             Firebase.Core.Options currentOptions = Firebase.Core.App.DefaultInstance.Options;
             if (currentOptions.GcmSenderId == gcmSenderID)
                 return;

             ManualResetEvent completionEvent = new ManualResetEvent(false);
             Firebase.Core.Options altOptions = new Firebase.Core.Options(currentOptions.GoogleAppId, gcmSenderID);
             altOptions.ApiKey = currentOptions.ApiKey;
             altOptions.ProjectId = currentOptions.ProjectId;
             Firebase.Core.App.DefaultInstance.Delete((bool success) =>
                 {
                     if (!success)
                         throw new InvalidOperationException("Firebase.Core.App.DefaultInstance.Delete() failed!");
                     completionEvent.Set();
                 });
             completionEvent.WaitOne();
             Firebase.Core.App.Configure(altOptions);
         }
     }
 }

FirebaseInitializer_android.cs

 public class FirebaseInitializer_Android : IFirebaseInitializer
 {
     public void ReInitializeFirebase(string gcmSenderID)
     {
         
         FirebaseApp existingApp = FirebaseApp.Instance;
         
         if (existingApp != null)
         {               
             // Get the FirebaseOptions from the production configuration
             FirebaseOptions currentOptions = existingApp.Options;

             if (currentOptions.GcmSenderId == gcmSenderID)
                 return;

             // Create a copy of the production FirebaseOptions
             FirebaseOptions updatedOptions = new FirebaseOptions.Builder()
                 .SetApiKey(currentOptions.ApiKey)
                 .SetApplicationId(currentOptions.ApplicationId)
                 .SetGcmSenderId(gcmSenderID)
                 .SetProjectId(currentOptions.ProjectId)
                 .SetDatabaseUrl(currentOptions.DatabaseUrl)
                 .SetStorageBucket(currentOptions.StorageBucket)
                 .SetGaTrackingId(currentOptions.GaTrackingId)                    
                 .Build();

             existingApp.Delete();

             // Initialize Firebase for Dev configuration
             FirebaseApp.InitializeApp(Platform.AppContext, updatedOptions);                                
         }
         else
         {
             // If Firebase app doesn't exist, initialize a new one
             FirebaseApp.InitializeApp(Platform.AppContext);               
         }           
     }
    
 }

Upvotes: 0

Related Questions