הגדרת מספר פרויקטים

בדף הזה נסביר איך להשתמש ביותר מפרויקט אחד ב-Firebase באפליקציה.

בחלק גדול מהאפליקציות צריך רק פרויקט Firebase אחד והגדרות ברירת המחדל שמתוארות במדריכים לתחילת העבודה. דוגמאות למקרים שבהם כדאי להשתמש במספר פרויקטים ב-Firebase:

  • הגדרת סביבת הפיתוח לשימוש בפרויקטים שונים ב-Firebase בהתאם לסוג ה-build או ליעד.
  • גישה לתוכן מכמה פרויקטים של Firebase באפליקציה.

תמיכה בסביבות שונות

דוגמה נפוצה לשימוש היא תמיכה בפרויקטים נפרדים ב-Firebase לסביבות הפיתוח והייצור.

כדי להגדיר את Web SDK ו-Admin SDK, מעבירים ערכים ישירות לפונקציות האיניציאציה שלהם. ב-SDK האלה, אפשר להשתמש בבדיקת זמן ריצה כדי לבחור משתני תצורה לפי פיתוח או ייצור.

פלטפורמות Android ו-Apple (והעטיפות שלהן ל-Unity ול-C++) בדרך כלל טוענות את ההגדרות מקובץ תצורה: GoogleService-Info.plist בפלטפורמת Apple ו-google-services.json ב-Android. הקבצים האלה נקראים באובייקט אפשרויות (FIROption או FirebaseOptions) שאליו מפנה אובייקט האפליקציה ב-Firebase (FIRApp או FirebaseApp).

בפלטפורמות האלה, המעבר בין סביבות מיושם בדרך כלל כהחלטה בזמן ה-build, באמצעות שימוש בקובצי תצורה שונים לכל סביבה.

תמיכה בכמה סביבות באפליקציה ל-Apple

כברירת מחדל, FirebaseApp.configure() יטען את הקובץ GoogleService-Info.plist שמצורף לאפליקציה. אם סביבת הפיתוח וסביבת הייצור מוגדרות כיעדים נפרדים ב-Xcode, תוכלו:

  • מורידים את שני קובצי ה-GoogleService-Info.plist
  • שומרים את שני הקבצים בספריות שונות
  • מוסיפים את שניהם לפרויקט Xcode
  • משייכים את הקבצים השונים ליעדים השונים באמצעות החלונית Target Membership:

חלונית 'טירגוט תוכנית החברים'

אם הגרסאות הבנויות הן חלק מיעד יחיד, האפשרות הטובה ביותר היא לתת לשני קובצי התצורה שמות ייחודיים (למשל 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-services.json מעובד למשאבי מחרוזות של Android על ידי הפלאגין של Gradle לשירותי Google. אפשר לראות אילו משאבים נוצרים במסמכי העזרה של הפלאגין של שירותי Google בקטע עיבוד קובץ ה-JSON.

אפשר ליצור כמה קבצים מסוג google-services.json לגרסאות build שונות. לשם כך, צריך להציב את הקבצים מסוג google-services.json בתיקיות ייעודיות עם שם שמתאים לכל גרסה, מתחת לשורש של מודול האפליקציה. לדוגמה, אם יש לכם גרסאות build מסוג 'development' ו-'release', אפשר לארגן את ההגדרות כך:

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

מידע נוסף זמין במסמכי העזרה של הפלאגין של שירותי Google בקטע הוספת קובץ ה-JSON.

לאחר מכן, המשאבים האלה נטענים על ידי FirebaseInitProvider, שפועל לפני קוד האפליקציה ומפעיל את ממשקי ה-API של Firebase באמצעות הערכים האלה.

מכיוון שהספק הזה רק קורא משאבים עם שמות ידועים, אפשרות נוספת היא להוסיף את משאבי המחרוזות ישירות לאפליקציה במקום להשתמש בפלאגין של Google Services ל-Gradle. כדי לעשות זאת:

  • הסרת הפלאגין google-services מה-build.gradle ברמה הבסיסית
  • מחיקת google-services.json מהפרויקט
  • הוספה ישירה של משאבי המחרוזות
  • מחיקה של apply plugin: 'com.google.gms.google-services' מהאפליקציה build.gradle

שימוש במספר פרויקטים באפליקציה

לפעמים צריך לגשת לפרויקטים שונים באמצעות אותם ממשקי API – למשל, גישה למספר מכונות של מסדי נתונים. ברוב המקרים יש אובייקט אפליקציה מרכזי ב-Firebase שמנהל את ההגדרות של כל ממשקי ה-API של Firebase. האובייקט הזה מופעל כחלק מההגדרה הרגילה. עם זאת, אם רוצים לגשת לכמה פרויקטים מאפליקציה אחת, צריך אובייקט אפליקציה נפרד ב-Firebase כדי להפנות לכל אחד מהם בנפרד. אתם אחראים לאינטאליזציה של המכונות הנוספות האלה.

בשני המקרים, קודם צריך ליצור אובייקט של אפשרויות Firebase שיאחסן את נתוני התצורה של אפליקציית Firebase. תיעוד מלא של האפשרויות זמין במסמכי העזרה של ה-API לגבי הכיתות הבאות:

הדוגמאות הבאות ממחישות את השימוש בקטגוריות האלה כדי לתמוך בכמה פרויקטים באפליקציה:

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

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

אינטרנט

// 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 חלופי (ממשקי ה-API של תכונות אחרות של Firebase פועלים לפי אותו דפוס).

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

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

אינטרנט

// 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 או ל-GoogleService-Info.plist בפלטפורמות של Apple כדי לחפש את מזהה האפליקציה הנכון של Google לאחסון אירועים. לכן מומלץ להשתמש בשיטות ברירת המחדל של ההגדרה בכל מקום אפשרי.

אם אתם צריכים להגדיר את סביבת זמן הריצה, חשוב לשים לב לאזהרות הבאות:

  1. אם אתם משתמשים ב-AdMob ומבקשים להציג מודעות בזמן ההפעלה, כפי שמומלץ, יכול להיות שתפספסו חלק מהנתונים ב-Analytics שקשורים למודעות לנייד אם לא תשתמשו בגישה להגדרה שמבוססת על משאבים.
  2. צריך לספק מזהה אפליקציה של Google אחד בלבד בכל גרסה של האפליקציה שמופצת. לדוגמה, אם תשלחו את גרסת האפליקציה הראשונה עם GOOGLE_APP_ID מסוים בתצורה, ואז תעלו את גרסת האפליקציה השנייה עם מזהה אחר, יכול להיות שנתוני Analytics לא ייאספו.
  3. בפלטפורמות של Apple, אל תוסיפו את GoogleService-Info.plist לפרויקט אם אתם מספקים הגדרה שונה בזמן הריצה, כי זה עלול לגרום לשינוי לכאורה של GOOGLE_APP_ID ולהוביל לאובדן של Analytics.