You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI应用中如何动态切换Firebase配置?

.NET MAUI动态切换Firebase环境配置方案

核心问题

  • Android端:Firebase默认实例初始化后无法重复调用InitializeApp覆盖,会抛出异常
  • iOS端:Firebase.Core.App.Configure仅能在App启动时生效一次,后续调用无法修改已加载的配置,且无法动态修改Info.plist
  • 初始启动时通过google-services.json/Info.plist初始化的Prod环境会占用默认实例,导致后续切换环境失败

步骤1:补充ServerConfig的Firebase配置字段

原ServerConfig仅存储了API地址、环境名和ServerID,需要新增每个环境对应的Firebase专属配置项:

public class ServerConfig
{
    public string ApiUrl { get; set; }
    public string Name { get; set; }
    public long ServerId { get; set; }
    // 新增Firebase配置字段
    public string FirebaseApiKey { get; set; }
    public string FirebaseAppId { get; set; }
    public string FirebaseProjectId { get; set; }
}

public List<ServerConfig> _Servers = new List<ServerConfig>()
{
    new ServerConfig
    {
        ApiUrl = "https://prod.mywebsite.com/api/v1",
        Name = "Prod",
        ServerId = 123456789,
        FirebaseApiKey = "prod-api-key",
        FirebaseAppId = "prod-app-id",
        FirebaseProjectId = "prod-project-id"
    },
    new ServerConfig
    {
        ApiUrl = "https://pre.mywebsite.com/api/v1",
        Name = "Pre",
        ServerId = 123456789,
        FirebaseApiKey = "pre-api-key",
        FirebaseAppId = "pre-app-id",
        FirebaseProjectId = "pre-project-id"
    },
    new ServerConfig
    {
        ApiUrl = "https://dev.mywebsite.com/api/v1",
        Name = "Dev",
        ServerId = 123456789,
        FirebaseApiKey = "dev-api-key",
        FirebaseAppId = "dev-app-id",
        FirebaseProjectId = "dev-project-id"
    }
};

步骤2:修改MAUIProgram.cs,延迟Firebase初始化

移除启动时自动初始化Firebase的逻辑,改为用户选择环境后手动初始化:

private static MauiAppBuilder RegisterFirebaseServices(this MauiAppBuilder builder)
{
    // 移除生命周期中的Firebase初始化代码,改为后续手动触发
    builder.Services.AddSingleton<IPushMessagingService, PushMessagingService>();
    return builder;
}

步骤3:调整Android平台的Firebase初始化逻辑

通过命名实例区分不同环境,避免重复初始化默认实例:

public class FirebaseInitializer : IFirebaseInitializer
{
    public FirebaseApp InitializeFirebase(string apiKey, string appId, string projectId, string environmentName)
    {
        var options = new FirebaseOptions.Builder()
            .SetApiKey(apiKey)
            .SetApplicationId(appId)
            .SetProjectId(projectId)
            .Build();

        // 检查是否已存在对应环境的命名实例
        var existingApp = FirebaseApp.GetApps(Platform.AppContext)
            .FirstOrDefault(app => app.Name.Equals(environmentName));

        return existingApp ?? FirebaseApp.InitializeApp(Platform.AppContext, options, environmentName);
    }
}

步骤4:调整iOS平台的Firebase初始化逻辑

iOS同样使用命名实例,且手动构建配置不依赖Info.plist:

public class FirebaseInitializer : IFirebaseInitializer
{
    public Firebase.Core.App InitializeFirebase(string apiKey, string appId, string projectId, string environmentName)
    {
        // 检查是否已存在对应环境的命名实例
        var existingApp = Firebase.Core.App.AllApps
            .FirstOrDefault(app => app.Name.Equals(environmentName));

        if (existingApp != null)
        {
            return existingApp;
        }

        // 手动构建Firebase配置,脱离plist依赖
        var options = new Firebase.Core.Options
        {
            ApiKey = apiKey,
            AppId = appId,
            ProjectId = projectId
        };
        // 创建并返回命名实例
        return Firebase.Core.App.Configure(options, environmentName);
    }
}

步骤5:修改PushMessagingService,绑定指定环境实例获取Token

获取Token时指定使用对应环境的命名实例,而非默认实例:

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

    object targetApp = null;
#if IOS
    var iosInitializer = new EngineerX.Platforms.iOS.FirebaseInitializer();
    targetApp = iosInitializer.InitializeFirebase(
        selectedServer.FirebaseApiKey, 
        selectedServer.FirebaseAppId, 
        selectedServer.FirebaseProjectId, 
        selectedServer.Name);
#elif ANDROID
    var androidInitializer = new EngineerX.Platforms.Android.FirebaseInitializer();
    targetApp = androidInitializer.InitializeFirebase(
        selectedServer.FirebaseApiKey, 
        selectedServer.FirebaseAppId, 
        selectedServer.FirebaseProjectId, 
        selectedServer.Name);
#endif

    // 基于指定实例获取推送Token
#if IOS
    return await Firebase.CloudMessaging.Messaging.GetMessaging((Firebase.Core.App)targetApp).GetTokenAsync();
#elif ANDROID
    return await Firebase.Messaging.FirebaseMessaging.GetInstance((FirebaseApp)targetApp).GetToken();
#endif
}

步骤6:默认Prod环境初始化处理

如果需要启动时默认使用Prod环境,可在登录页加载完成后,自动调用GetNotificationTokenAsync传入Prod的ServerConfig完成初始化。


关键注意事项

  • Android:禁止重复初始化默认实例,必须用命名实例区分环境
  • iOS:必须手动构建Firebase配置,不能依赖Info.plist的默认配置,否则无法切换环境
  • 所有Firebase服务(Auth、Messaging等)都需绑定对应环境的命名实例,不能直接使用Current属性(默认指向默认实例)

内容的提问来源于stack exchange,提问作者Sagar Chopra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:54:55