Định cấu hình nhiều dự án

Trang này mô tả cách sử dụng nhiều dự án Firebase trong ứng dụng của bạn.

Nhiều ứng dụng chỉ cần một dự án Firebase duy nhất và chế độ thiết lập mặc định được mô tả trong hướng dẫn Bắt đầu. Ví dụ về trường hợp thông tin hữu ích để sử dụng nhiều dự án Firebase, hãy bao gồm:

  • Thiết lập môi trường phát triển để sử dụng nhiều dự án Firebase dựa trên loại bản dựng hoặc mục tiêu.
  • Truy cập vào nội dung từ nhiều dự án Firebase trong ứng dụng của bạn.

Hỗ trợ nhiều môi trường

Một trường hợp sử dụng phổ biến là hỗ trợ các dự án Firebase riêng biệt cho quá trình phát triển của bạn và môi trường thực tế.

SDK Web và SDK quản trị được định cấu hình bằng cách trực tiếp chuyển các giá trị vào hàm khởi tạo của chúng. Đối với những SDK này, bạn có thể sử dụng kiểm tra thời gian chạy để chọn biến cấu hình phát triển hoặc phát hành chính thức.

Các nền tảng Android và Apple (cũng như trình bao bọc Unity và C++ của chúng) thường tải cấu hình từ một tệp cấu hình: GoogleService-Info.plist trên Apple và google-services.json trên Android. Những tệp này được đọc thành một đối tượng options (FIROption hoặc FirebaseOptions) được tham chiếu bởi Đối tượng ứng dụng Firebase (FIRApp hoặc FirebaseApp).

Đối với các nền tảng này, việc chuyển đổi giữa các môi trường thường được triển khai như một quyết định về thời gian xây dựng, thông qua việc sử dụng các tệp cấu hình khác nhau cho mỗi môi trường.

Hỗ trợ nhiều môi trường trong ứng dụng Apple của bạn

Theo mặc định, FirebaseApp.configure() sẽ tải tệp GoogleService-Info.plist đi kèm với ứng dụng. Nếu môi trường phát triển và môi trường sản xuất được định cấu hình thành các mục tiêu riêng biệt trong Xcode, bạn có thể:

  • Tải cả hai tệp GoogleService-Info.plist xuống
  • Lưu trữ 2 tệp trong các thư mục khác nhau
  • Thêm cả hai mục này vào dự án Xcode của bạn
  • Liên kết các tệp khác nhau với các mục tiêu khác nhau bằng cách sử dụng Mục tiêu Bảng điều khiển thành viên:

Bảng điều khiển Gói thành viên mục tiêu

Nếu bản dựng là một phần của một mục tiêu duy nhất, phương án tốt nhất là cung cấp cả hai tên duy nhất của tệp cấu hình (ví dụ: GoogleService-Info-Free.plistGoogleService-Info-Paid.plist). Sau đó, chọn tệp plist để tải trong thời gian chạy. Điều này được thể hiện trong ví dụ sau:

// 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)

Hỗ trợ nhiều môi trường trong ứng dụng Android

Trong Android, tệp google-services.json được xử lý thành chuỗi Android bằng trình bổ trợ Gradle cho Dịch vụ của Google. Bạn có thể thấy những tài nguyên nào được tạo trong tài liệu về Trình bổ trợ Google Services trên Xử lý tệp JSON.

Bạn có thể có nhiều tệp google-services.json cho các mục khác nhau biến thể bản dựng bằng cách đặt google-services.json tệp vào các thư mục riêng được đặt tên cho mỗi tệp biến thể trong thư mục gốc của mô-đun ứng dụng. Ví dụ: nếu bạn thuộc danh mục "phát triển" và "release" phiên bản bản dựng, cấu hình của bạn có thể được sắp xếp như sau:

app/
    google-services.json
    src/development/google-services.json
    src/release/google-services.json
    ...

Để tìm hiểu thêm, hãy xem tài liệu về Trình bổ trợ Google Services trên Thêm tệp JSON.

Sau đó, các tài nguyên này được tải FirebaseInitProvider, Mã này chạy trước mã xử lý ứng dụng và khởi chạy API Firebase bằng cách sử dụng các giá trị đó.

Vì trình cung cấp này chỉ đọc các tài nguyên có tên đã biết, nên một là thêm trực tiếp tài nguyên chuỗi vào ứng dụng thay vì sử dụng Trình bổ trợ Gradle cho Dịch vụ của Google. Bạn có thể thực hiện việc này bằng cách:

  • Xoá trình bổ trợ google-services khỏi build.gradle gốc của bạn
  • Đang xoá google-services.json khỏi dự án của bạn
  • Thêm trực tiếp tài nguyên chuỗi
  • Đang xoá apply plugin: 'com.google.gms.google-services' khỏi ứng dụng build.gradle của bạn

Dùng nhiều dự án trong ứng dụng của bạn

Đôi khi, bạn cần truy cập vào các dự án khác nhau bằng cùng một API, để ví dụ: truy cập nhiều thực thể cơ sở dữ liệu. Trong hầu hết các trường hợp, Đối tượng ứng dụng Firebase quản lý cấu hình cho tất cả Firebase API. Đối tượng này được khởi tạo trong quá trình thiết lập thông thường của bạn. Tuy nhiên, khi bạn muốn truy cập nhiều dự án từ một ứng dụng, bạn sẽ cần có đối tượng ứng dụng Firebase riêng biệt để tham chiếu riêng từng đối tượng. Đó là bạn có thể khởi tạo các phiên bản khác này.

Trong cả hai trường hợp, trước tiên, bạn cần phải tạo một đối tượng tùy chọn Firebase để lưu giữ dữ liệu cấu hình cho ứng dụng Firebase. Tài liệu đầy đủ cho các tuỳ chọn có trong tài liệu tham khảo API cho các lớp sau:

Thông tin cho thấy việc sử dụng các lớp này để hỗ trợ nhiều dự án trong một ứng dụng trong các ví dụ sau:

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();

Sau khi khởi chạy đối tượng tuỳ chọn này, bạn có thể sử dụng đối tượng này để định cấu hình phiên bản bổ sung của ứng dụng Firebase. Xin lưu ý rằng trong tất cả các ví dụ được trình bày bên dưới, chúng tôi sử dụng chuỗi secondary. Tên này được sử dụng để truy xuất phiên bản của ứng dụng và để phân biệt nó với các phiên bản khác, bao gồm bản sao mặc định (có tên là [DEFAULT]). Bạn nên chọn một chuỗi thích hợp để mục đích sử dụng dự án Firebase khác.

Các đoạn mã sau đây minh hoạ việc kết nối với một Cơ sở dữ liệu theo thời gian thực thay thế (API cho các tính năng khác của Firebase cũng tuân theo cùng một mẫu).

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);

Đảm bảo báo cáo đáng tin cậy cho Analytics

Google Analytics thu thập các sự kiện từ rất sớm trong quá trình khởi động ứng dụng, ở một số trường hợp trước khi phiên bản ứng dụng Firebase chính được định cấu hình. Ngang bằng những trường hợp này, Firebase tham chiếu đến tài nguyên Android hoặc GoogleService-Info.plist trên các nền tảng của Apple để tra cứu đúng ứng dụng Google Mã nhận dạng cho các sự kiện lưu trữ. Vì lý do này, bạn nên sử dụng chế độ cài đặt mặc định bất cứ khi nào có thể.

Nếu bắt buộc phải định cấu hình thời gian chạy, xin lưu ý các lưu ý sau:

  1. Nếu đang sử dụng AdMob và yêu cầu quảng cáo khi khởi động theo đề xuất, bạn có thể bỏ lỡ một số dữ liệu Analytics liên quan đến quảng cáo trên thiết bị di động khi không sử dụng tài nguyên dựa trên cấu hình.
  2. Bạn chỉ được cung cấp một mã ứng dụng Google duy nhất trong mỗi biến thể được phân phối của ứng dụng. Ví dụ: nếu bạn giao phiên bản 1 của ứng dụng kèm theo một GOOGLE_APP_ID nhất định theo cấu hình này, sau đó tải phiên bản 2 lên với một mã nhận dạng khác. Điều này có thể gây ra dữ liệu phân tích cần xoá.
  3. Trên các nền tảng của Apple, đừng thêm GoogleService-Info.plist vào dự án của bạn nếu bạn đang cung cấp cấu hình khác nhau vào thời gian chạy, vì điều này có thể dẫn đến việc thay đổi rõ ràng của GOOGLE_APP_ID và dẫn đến việc mất Analytics.