如何为Flutter项目配置两个Firebase项目,实现生产与预发布环境分离
单个Flutter项目配置双Firebase环境(生产/测试)解决方案
针对iOS平台GoogleService-Info.plist无法重名的问题,目前最成熟的方案是通过构建脚本/编译变种自动切换配置文件,结合Flutter层环境标识实现数据隔离。以下是分步实现指南:
1. 配置文件目录规划
先把两个环境的Firebase配置文件分开存放,避免冲突:
- 在项目根目录创建
firebase_configs文件夹 - 内部新建
dev(预发布/测试)和prod(生产)子文件夹 - 将对应环境的
GoogleService-Info.plist(iOS)、google-services.json(Android)分别放入两个子文件夹
2. iOS平台:构建前自动切换配置文件
利用Xcode的Run Script Phase,在编译前自动复制对应环境的plist文件到指定位置:
- 打开
ios/Runner.xcworkspace,选中RunnerTarget - 切换到
Build Phases标签,点击+选择New Run Script Phase - 将以下脚本粘贴到脚本框中(可根据自己的编译配置调整判断逻辑):
# 根据编译配置切换环境 if [ "${CONFIGURATION}" = "Debug" ] || [ "${CONFIGURATION}" = "AdHoc" ]; then # 测试环境:复制dev目录下的plist到Runner目录 cp "${PROJECT_DIR}/../firebase_configs/dev/GoogleService-Info.plist" "${PROJECT_DIR}/Runner/GoogleService-Info.plist" else # 生产环境:复制prod目录下的plist到Runner目录 cp "${PROJECT_DIR}/../firebase_configs/prod/GoogleService-Info.plist" "${PROJECT_DIR}/Runner/GoogleService-Info.plist" fi
- 确保
Runner项目中已添加GoogleService-Info.plist,并勾选Target Membership中的Runner
3. Android平台:用编译变种(Product Flavors)隔离环境
Android原生支持通过Product Flavors加载不同环境的配置文件:
- 打开
android/app/build.gradle - 在
android代码块中添加编译变种配置:
android { // ...其他原有配置 flavorDimensions "environment" productFlavors { dev { dimension "environment" applicationIdSuffix ".dev" // 给测试包加后缀,避免与生产包冲突 resValue "string", "app_name", "MyApp Dev" // 可选:修改测试包名称 } prod { dimension "environment" resValue "string", "app_name", "MyApp" } } }
- 将
dev环境的google-services.json放入android/app/src/dev/,prod环境的放入android/app/src/prod/ - Google Services插件会自动根据当前编译变种加载对应配置文件
4. Flutter代码层识别环境并适配逻辑
通过编译参数或平台标识判断当前环境,实现业务逻辑的环境隔离:
方式一:通过--dart-define传递环境变量
构建时携带环境参数:
# 测试环境 flutter run --dart-define=ENV=dev # 生产环境 flutter run --dart-define=ENV=prod
在Flutter代码中读取并使用:
enum Env { dev, prod } final currentEnv = String.fromEnvironment('ENV', defaultValue: 'prod') == 'dev' ? Env.dev : Env.prod; // 示例:根据环境初始化不同配置 void initFirebase() async { await Firebase.initializeApp(); // 可根据currentEnv添加环境专属逻辑,比如测试环境启用调试日志 if (currentEnv == Env.dev) { FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); // 可选:连接本地模拟器 } }
方式二:根据平台编译标识判断(无需额外参数)
针对Android的Product Flavors和iOS的Configuration,通过平台通道读取当前环境:
import 'package:flutter/services.dart'; Future<Env> getCurrentEnv() async { try { final String env = await MethodChannel('com.example/env').invokeMethod('getEnv'); return env == 'dev' ? Env.dev : Env.prod; } catch (_) { return Env.prod; } }
(需在iOS/Android原生代码中实现getEnv方法返回当前环境标识)
注意事项
- 将
ios/Runner/GoogleService-Info.plist和android/app/google-services.json添加到.gitignore,避免提交自动生成的文件,仅提交firebase_configs下的配置文件 - iOS测试包和生产包的Bundle ID需保持一致或通过Application ID后缀区分,避免App Store审核冲突
- Android通过Product Flavors生成的测试包与生产包可共存于同一设备,无需卸载
内容的提问来源于stack exchange,提问作者Jaden Watt
相关产品推荐
相关产品推荐

