Đị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 và quy trình thiết lập mặc định được mô tả trong hướng dẫn Bắt đầu. Dưới đây là ví dụ về những trường hợp bạn có thể cần sử dụng nhiều dự án Firebase:

  • Thiết lập môi trường phát triển để sử dụng các dự án Firebase khác nhau 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 môi trường phát triển và môi trường chính thức.

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

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

Đố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 dưới dạng 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 từng môi trường.

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

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 chính thức được định cấu hình dưới dạng 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
  • Lưu trữ hai tệp trong các thư mục khác nhau
  • Thêm cả hai tệp vào dự án Xcode
  • Liên kết các tệp khác nhau với các mục tiêu khác nhau bằng bảng điều khiển Target Membership (Tư cách thành viên mục tiêu):

Bảng Target Membership

Nếu các bản dựng thuộc một mục tiêu duy nhất, thì cách tốt nhất là đặt tên riêng cho cả hai tệp cấu hình (ví dụ: GoogleService-Info-Free.plistGoogleService-Info-Paid.plist). Sau đó, chọn plist cần tải tại thời gian chạy. Ví dụ sau đây minh hoạ cách thực hiện việc này:

// Load a named file.
guard 
  let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist"),
  let fileOptions = FirebaseOptions(contentsOfFile: filePath)
else { fatalError("Couldn't load config file.") }
FirebaseApp.configure(options: fileOptions)

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

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

Bạn có thể có nhiều tệp google-services.json cho các biến thể bản dựng khác nhau bằng cách đặt các tệp google-services.json trong các thư mục dành riêng được đặt tên cho từng biến thể trong thư mục gốc của mô-đun ứng dụng. Ví dụ: nếu bạn có các phiên bản bản dựng "development" (phát triển) và "release" (phát hành), thì 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ợ Dịch vụ Google trong phần Thêm tệp JSON.

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

Vì nhà cung cấp này chỉ đọc các tài nguyên có tên đã biết, nên bạn có thể thêm trực tiếp các tài nguyên chuỗi vào ứng dụng thay vì sử dụng trình bổ trợ gradle Dịch vụ 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
  • Xoá google-services.json khỏi dự án
  • Thêm trực tiếp các tài nguyên chuỗi
  • Xoá apply plugin: 'com.google.gms.google-services' khỏi build.gradle của ứng dụng

Sử dụng nhiều dự án trong ứng dụng

Đô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 vào nhiều thực thể cơ sở dữ liệu. Trong hầu hết các trường hợp, có một đối tượng ứng dụng Firebase trung tâm quản lý cấu hình cho tất cả các API Firebase. Đối tượng này được khởi chạy trong quá trình thiết lập thông thường. Tuy nhiên, khi muốn truy cập vào nhiều dự án từ một ứng dụng, bạn cần có một đối tượng ứng dụng Firebase riêng biệt để tham chiếu từng dự án. Bạn phải tự khởi chạy các thực thể khác này.

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

Cách sử dụng các lớp này để hỗ trợ nhiều dự án trong một ứng dụng được minh hoạ 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.clientID = "27992087142-ola6qe637ulk8780vl8mo5vogegkm23n.apps.googleusercontent.com"
secondaryOptions.databaseURL = "https://myproject.firebaseio.com"
secondaryOptions.storageBucket = "myproject.appspot.com"
secondaryOptions.deepLinkURLScheme = "myapp://"
secondaryOptions.storageBucket = "projectid-12345.appspot.com"
secondaryOptions.appGroupID = nil

Kotlin

// 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 đó để định cấu hình một thực thể ứng dụng Firebase bổ sung. Xin lưu ý rằng trong tất cả các ví dụ bên dưới, chúng tôi sử dụng chuỗi secondary. Tên này được dùng để truy xuất thực thể ứng dụng và phân biệt thực thể đó với các thực thể khác, bao gồm cả thực thể mặc định (có tên là [DEFAULT]). Bạn nên chọn một chuỗi phù hợp với mục đích sử dụng dự án Firebase khác.

Các đoạn mã sau đây minh hoạ cách kết nối với Cơ sở dữ liệu thời gian thực thay thế Realtime Database (các API cho các tính năng khác của Firebase 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 { fatalError("Could not retrieve secondary app") }


// Retrieve a Real Time Database client configured against a specific app.
let secondaryDb = Database.database(app: secondary)

Kotlin

// 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 rất sớm trong quy trình khởi động ứng dụng, trong một số trường hợp là trước khi thực thể ứng dụng Firebase chính được định cấu hình. Trong những trường hợp này, Firebase sẽ tham chiếu đến tài nguyên Android hoặc GoogleService-Info.plist trên nền tảng Apple để tra cứu mã ứng dụng chính xác của Google nhằm lưu trữ các sự kiện. Vì lý do này, bạn nên sử dụng các phương thức cấu hình mặc định bất cứ khi nào có thể.

Nếu bạn cần cấu hình thời gian chạy, hãy lưu ý những điều sau:

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