本页将介绍如何在应用中使用多个 Firebase 项目。
许多应用只需要一个 Firebase 项目并采用“使用入门”指南中描述的默认设置。下面列举了几种适合使用多个 Firebase 项目的情况:
- 您将开发环境设置为根据 build 类型或目标使用不同的 Firebase 项目。
- 在您的应用中访问多个 Firebase 项目的内容。
支持不同环境
一种常见的使用场景是为开发和生产环境设置不同的 Firebase 项目。
Web SDK 和 Admin SDK 的配置方式为直接将值传递到其初始化函数。对于这些 SDK,您可以使用运行时检查来选择开发或生产配置变量。
Android 和 Apple 平台(及其 Unity 和 C++ 封装容器)通常从配置文件(Apple 平台上的 GoogleService-Info.plist
和 Android 上的 google-services.json
)加载配置。这些文件将被读入一个选项对象(FIROption
或 FirebaseOptions
),并由 Firebase 应用对象(FIRApp
或 FirebaseApp
)引用。
对于这些平台,通常可以通过为每种环境使用不同的配置文件,在构建时就决定要采用哪种环境,从而实现在各种环境之间切换。
在您的 Apple 应用中支持多种环境
默认情况下,FirebaseApp.configure()
将加载与应用捆绑在一起的 GoogleService-Info.plist
文件。如果您的开发和生产环境在 XCode 中被配置为不同的目标,您可以:
- 两个
GoogleService-Info.plist
文件都下载 - 将两个文件存储在不同目录中
- 将两个文件都添加到您的 XCode 项目中
- 使用“Target Membership”(目标成员资格)面板将不同文件与不同目标相关联:
如果这些 build 同属于一个目标,最好为两个配置文件指定独一无二的名称(例如 GoogleService-Info-Free.plist
和 GoogleService-Info-Paid.plist
)。然后在运行时选择要加载的 plist 文件。
具体可见以下示例:
// Load a named file. let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist") guard let fileopts = FirebaseOptions(contentsOfFile: filePath!) else { assert(false, "Couldn't load config file") } FirebaseApp.configure(options: fileopts)
在您的 Android 应用中支持多种环境
在 Android 中,Google 服务 Gradle 插件会将 google-services.json
文件处理为 Android 字符串资源。您可以在关于处理 JSON 文件的 Google 服务插件文档中查看会创建哪些资源。
您可以配置多个用于不同 build 变体的 google-services.json
文件,方法是将 google-services.json
文件放在应用模块根目录下为每个变体指定的专用目录中。例如,如果您有“开发”和“发布”两个 build 变体,可以按如下方式组织您的配置:
app/
google-services.json
src/development/google-services.json
src/release/google-services.json
...
如需了解详情,请参阅关于添加 JSON 文件的 Google 服务插件文档。
随后,FirebaseInitProvider 将加载这些资源。该提供程序在应用代码运行前运行,并会使用相应值初始化 Firebase API。
由于此提供程序只会读取名称已知的资源,因此另一种做法是直接在您的应用中添加字符串资源,而不是使用 Google 服务 Gradle 插件。为此,您可以执行以下操作:
- 从根目录
build.gradle
中移除google-services
插件 - 从项目中删除
google-services.json
- 直接添加字符串资源
- 从您的应用的
build.gradle
中删除apply plugin: 'com.google.gms.google-services'
在您的应用中使用多个项目
有时候,您需要使用相同的 API 访问不同项目,例如,访问多个数据库实例。在大多数情况下,您可以通过一个统一的 Firebase 应用对象管理所有 Firebase API 的配置。此对象是在您的正常设置过程中进行初始化的。但是,如果您要从单个应用访问多个项目,则需要不同的 Firebase 应用对象来分别引用各个项目。初始化其他这些实例的工作需要由您自己完成。
在这两种情况下,您都需要先创建一个 Firebase 选项对象,来存放 Firebase 应用的配置数据。相关选项的完整文档可在以下各类对应的 API 参考文档中找到:
- Swift:
FirebaseOptions(googleAppID:gcmSenderID:)
- Android:
FirebaseOptions.Builder
- Web:
initializeApp()
- C++:
firebase::App::Create
- Unity:
FirebaseApp.Create
- Node.js:
initializeApp
- Java:
FirebaseOptions.Builder
下面的示例显示了如何使用这些类来在一个应用中支持多个项目:
Swift
// Configure with manual options. Note that projectID and apiKey, though not // required by the initializer, are mandatory. let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a", gcmSenderID: "27992087142") secondaryOptions.apiKey = "AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk" secondaryOptions.projectID = "projectid-12345" // The other options are not mandatory, but may be required // for specific Firebase products. secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration" secondaryOptions.trackingID = "UA-12345678-1" secondaryOptions.clientID = "27992087142-ola6qe637ulk8780vl8mo5vogegkm23n.apps.googleusercontent.com" secondaryOptions.databaseURL = "https://myproject.firebaseio.com" secondaryOptions.storageBucket = "myproject.appspot.com" secondaryOptions.androidClientID = "12345.apps.googleusercontent.com" secondaryOptions.deepLinkURLScheme = "myapp://" secondaryOptions.storageBucket = "projectid-12345.appspot.com" secondaryOptions.appGroupID = nil
Kotlin+KTX
// Manually configure Firebase Options. The following fields are REQUIRED: // - Project ID // - App ID // - API Key val options = FirebaseOptions.Builder() .setProjectId("my-firebase-project") .setApplicationId("1:27992087142:android:ce3b6448250083d1") .setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw") // .setDatabaseUrl(...) // .setStorageBucket(...) .build()
Java
// Manually configure Firebase Options. The following fields are REQUIRED: // - Project ID // - App ID // - API Key FirebaseOptions options = new FirebaseOptions.Builder() .setProjectId("my-firebase-project") .setApplicationId("1:27992087142:android:ce3b6448250083d1") .setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw") // setDatabaseURL(...) // setStorageBucket(...) .build();
Web
// The following fields are REQUIRED: // - Project ID // - App ID // - API Key const secondaryAppConfig = { projectId: "<PROJECT_ID>", appId: "<APP_ID>", apiKey: "<API_KEY>", // databaseURL: "...", // storageBucket: "...", };
C++
firebase::AppOptions secondary_app_options;
// API key, app ID, and project ID are always required.
secondary_app_options.set_api_key("<API_KEY>");
secondary_app_options.set_app_id("<GOOGLE_APP_ID>");
secondary_app_options.set_project_id("<PROJECT_ID>");
// The following options are specific to individual Firebase products
// and may not always be required.
secondary_app_options.set_database_url("<DATABASE_URL>");
secondary_app_options.set_messaging_sender_id("<SENDER_ID>");
secondary_app_options.set_storage_bucket("<STORAGE_BUCKET>");
Unity
Firebase.AppOptions secondaryAppOptions = new Firebase.AppOptions {
ApiKey = "<API_KEY>",
AppId = "<GOOGLE_APP_ID>",
ProjectId = "<PROJECT_ID>"
};
Node.js
const secondaryServiceAccount = require('./path/to/serviceAccountKey.json'); // All required options are specified by the service account, // add service-specific configuration like databaseURL as needed. const secondaryAppConfig = { credential: cert(secondaryServiceAccount), // databaseURL: 'https://<DATABASE_NAME>.firebaseio.com' };
Java
FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");
FirebaseOptions secondaryAppConfig = new FirebaseOptions.Builder()
.setCredential(FirebaseCredentials.fromCertificate(serviceAccount))
.setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
.build();
初始化此选项对象后,您可以用它来配置其他 Firebase 应用实例。请注意,在下文显示的所有示例中,我们都使用了“secondary”字符串。此名称用于检索该应用实例,并将其与其他实例(包括名为 [DEFAULT] 的默认实例)区分开。您选择的字符串应该适合另一个 Firebase 项目的预期用途。
下面的代码段演示了如何连接到备用 Realtime Database(其他 Firebase 功能的 API 遵循同一模式)。
Swift
// Configure an alternative FIRApp. FirebaseApp.configure(name: "secondary", options: secondaryOptions) // Retrieve a previous created named app. guard let secondary = FirebaseApp.app(name: "secondary") else { assert(false, "Could not retrieve secondary app") } // Retrieve a Real Time Database client configured against a specific app. let secondaryDb = Database.database(app: secondary)
Kotlin+KTX
// Initialize secondary FirebaseApp. Firebase.initialize(context = this, options, "secondary") // Retrieve secondary FirebaseApp. val secondary = Firebase.app("secondary") // Get the database for the other app. val secondaryDatabase = Firebase.database(secondary)
Java
// Initialize with secondary app FirebaseApp.initializeApp(this /* Context */, options, "secondary"); // Retrieve secondary FirebaseApp FirebaseApp secondary = FirebaseApp.getInstance("secondary");
Web
// Initialize another app with a different config const secondaryApp = firebase.initializeApp(secondaryAppConfig, "secondary"); // Access services, such as the Realtime Database // secondaryApp.database();
C++
firebase::App* secondary_app = firebase::App::Create(secondary_app_options, "Secondary");
firebase::database::Database* secondary_database = firebase::database::Database::GetInstance(secondary_app);
Unity
var secondaryApp = Firebase.FirebaseApp.Create(secondaryAppOptions, "Secondary"));
var secondaryDatabase = Firebase.Database.FirebaseDatabase.getInstance(secondaryApp);
Node.js
// Initialize another app with a different config const secondary = initializeApp(secondaryAppConfig, 'secondary'); // Access services, such as the Realtime Database // const secondaryDatabase = secondary.database();
Java
// Initialize another app with a different config
FirebaseApp secondaryApp = FirebaseApp.initializeApp(secondaryAppConfig, "secondary");
// Retrieve the database.
FirebaseDatabase secondaryDatabase = FirebaseDatabase.getInstance(secondaryApp);
确保生成可靠的 Analytics 报告
在应用启动流程中,Google Analytics(分析)很早就会收集事件;在某些情况下,甚至会在 Firebase 应用主实例配置完之前就开始收集。在此类情况下,Firebase 会引用 Android 资源或 Apple 平台的 GoogleService-Info.plist
,以查询正确的 Google 应用 ID 来存储事件。出于这个原因,我们建议您尽可能使用默认配置方法。
如果必须使用运行时配置,请注意以下事项:
- 如果您使用 AdMob 并在启动时按照建议发出了广告请求,并且未使用基于资源的配置方法,那么您可能会错失与移动广告相关的一些 Analytics 数据。
- 请在应用的每个分发变体中提供相同的 Google 应用 ID。例如,如果您发布已配置为使用某一
GOOGLE_APP_ID
的应用版本 1,然后上传使用不同 ID 的版本 2,则可能会导致 Analytics 数据被丢弃。 - 在 Apple 平台上,如果您在运行时提供不同的配置,请勿将 GoogleService-Info.plist 添加到您的项目中,否则可能会导致
GOOGLE_APP_ID
出现明显变化并丢失 Analytics 数据。