Reputation: 45
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
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