איך מתחילים להשתמש ב-Firebase Cloud Messaging באפליקציות C++‎

בחירת פלטפורמה: iOS+‎ Android אינטרנט Flutter Unity C++‎


במדריך הזה מוסבר איך להתחיל להשתמש ב-Firebase Cloud Messaging באפליקציות לקוח ב-C++‎ כדי לשלוח הודעות באופן מהימן.

כדי לכתוב את אפליקציית הלקוח של Firebase Cloud Messaging בפלטפורמות שונות באמצעות C++‎, צריך להשתמש ב-API של Firebase Cloud Messaging. ערכת ה-SDK ל-C++‎ פועלת גם בפלטפורמות של Android וגם בפלטפורמות של Apple, וצריך לבצע הגדרות נוספות לכל פלטפורמה. במאמר הסבר על Firebase ל-C++‎ מוסבר איך ה-SDK ל-C++‎ ל-iOS ול-Android פועל עם FCM.

הגדרת Firebase ו-FCM SDK

Android

  1. אם עדיין לא עשיתם זאת, הוסיפו את Firebase לפרויקט C++‎.

    • בהוראות ההגדרה המקושרות, בודקים את דרישות המכשיר והאפליקציה לשימוש ב-SDK של Firebase C++, כולל ההמלצה להשתמש ב-CMake כדי ליצור את האפליקציה.

    • בקובץ build.gradle ברמת הפרויקט, צריך לכלול את מאגר ה-Maven של Google בקטעים buildscript ו-allprojects.

  2. יוצרים אובייקט של אפליקציית Firebase ומעבירים את סביבת ה-JNI וה-Activity:

    app = ::firebase::App::Create(::firebase::AppOptions(), jni_env, activity);

  3. מגדירים מחלקה שמטמיעה את הממשק של firebase::messaging::Listener.

  4. מאתחלים את FCM, מעבירים את האפליקציה ומאזין מובנה:

    ::firebase::messaging::Initialize(app, listener);

  5. באפליקציות שמסתמכות על Google Play Services SDK, צריך לבדוק אם במכשיר יש קובץ APK תואם של Google Play Services לפני שניגשים לתכונות. איך בודקים אם יש APK של Google Play Services

iOS+‎

  1. אם עדיין לא עשיתם זאת, הוסיפו את Firebase לפרויקט C++‎. כדי להגדיר את הפרויקט ל-FCM:
    1. בקובץ Podfile של הפרויקט, מוסיפים את התלות ב-FCM:
      pod 'FirebaseMessaging'
    2. גוררים את המסגרות firebase.framework ו-firebase_messaging.framework לפרויקט Xcode מ-Firebase C++ SDK.
  2. מעלים את מפתח האימות של APNs ל-Firebase. אם עדיין אין לכם מפתח אימות של APNs, הקפידו ליצור מפתח כזה ב-Apple Developer Member Center.

    1. במסוף Firebase, נכנסים אל הגדרות > כללי. לוחצים על הכרטיסייה העברת הודעות בענן.
    2. ‫בקטע APNs authentication key (מפתח אימות של APNs) שמופיע בקטע iOS app configuration (הגדרת אפליקציה ל-iOS), לוחצים על Upload (העלאה) כדי להעלות את מפתח האימות של סביבת הפיתוח, את מפתח האימות של סביבת הייצור או את שניהם. צריך להוסיף לפחות אחד.
    3. עוברים למיקום שבו שמרתם את המפתח, בוחרים אותו ולוחצים על Open. מוסיפים את מזהה המפתח (זמין ב-Apple Developer Member Center) ולוחצים על Upload.
  3. מגדירים את פרויקט Xcode כדי להפעיל התראות:

    1. בוחרים את הפרויקט באזור הניווט.
    2. בוחרים את יעד הפרויקט מאזור העריכה.
    3. באזור העריכה, לוחצים על הכרטיסייה כללי.

      1. גוללים אל Linked Frameworks and Libraries (ספריות וסביבות עבודה מקושרות) ולוחצים על הכפתור + כדי להוסיף סביבות עבודה.
      2. בחלון שמופיע, גוללים אל UserNotifications.framework, לוחצים על הרשומה ואז על Add.

        ה-framework הזה מופיע רק ב-Xcode מגרסה 8 ואילך, והוא נדרש על ידי הספרייה הזו.

    4. באזור העריכה, לוחצים על הכרטיסייה יכולות.

      1. מעבירים את המתג התראות למצב מופעל.
      2. גוללים אל מצבי רקע ומעבירים את המתג למצב מופעל.
      3. בוחרים באפשרות התראות מרחוק בקטע מצבי רקע.
  4. יוצרים אובייקט של אפליקציית Firebase:

    app = ::firebase::App::Create(::firebase::AppOptions());

  5. מגדירים מחלקה שמטמיעה את הממשק של firebase::messaging::Listener.

  6. מאתחלים את העברת ההודעות בענן ב-Firebase, ומעבירים את האפליקציה ואת המאזין (listener) שנוצר:

    ::firebase::messaging::Initialize(app, listener);

גישה למזהה ההתקנה של Firebase

הפעלת הרישום באמצעות מזהה ההתקנה של Firebase

כדי לאפשר רישום של מופע האפליקציה ב-FCM באמצעות מזהה ההתקנה של Firebase‏ (FID), צריך קודם להפעיל את מזהי ה-FID בהגדרות של האפליקציה גם בפלטפורמות של Android וגם בפלטפורמות של Apple:

Android

מוסיפים את הרכיב <meta-data> הבא בתוך הרכיב <application> של AndroidManifest.xml:

<meta-data android:name="firebase_messaging_installation_id_enabled"
           android:value="true" />

Swift

מוסיפים את המפתח FirebaseMessagingInstallationIdEnabled ל-Info.plist ומגדירים אותו ל-YES:

FirebaseMessagingInstallationIdEnabled = YES

הטמעה של ה-Listener של onRegistrationReceived

כשמאתחלים את הספרייה Firebase Cloud Messaging, היא רושמת את המופע של אפליקציית הלקוח כדי לקבל הודעות באמצעות מזהה ההתקנה של Firebase‏ (FID). האפליקציה תקבל את ה-FID באמצעות פונקציית ה-callback‏ OnRegistrationReceived, שצריך להגדיר בהטמעה של firebase::messaging::Listener:

class MyListener : public firebase::messaging::Listener {
 public:
  void OnRegistrationReceived(const char* installation_id) override {
    LogMessage("Received Firebase Installation ID: %s", installation_id);
    // TODO: Send the Firebase Installation ID (FID) to your app server to
    // target this device for messages.
  }
};

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

רישום ידני כשההפעלה האוטומטית מושבתת

אפשר גם להפעיל את הרישום באופן ידני באמצעות FCM בזמן הריצה, באמצעות Register():

// Manually register with FCM
firebase::Future<void> register_future = firebase::messaging::Register();
register_future.OnCompletion([](const firebase::Future<void>& future) {
  if (future.status() == firebase::kFutureStatusComplete &&
      future.error() == 0) {
    // Note: The registered Firebase Installation ID is delivered to the
    // OnRegistrationReceived callback.
    LogMessage("Registered with FCM");
  }
});

גישה לטוקן הרישום של FCM (הוצא משימוש)

כשמפעילים את הספרייה Firebase Cloud Messaging, נשלחת בקשה לטוקן רישום בשביל המכונה של אפליקציית הלקוח. האפליקציה תקבל את האסימון באמצעות הקריאה החוזרת (callback) של OnTokenReceived, שצריכה להיות מוגדרת במחלקה שמטמיעה את firebase::messaging::Listener.

אם אתם רוצים לטרגט את המופע הספציפי הזה של האפליקציה, אתם צריכים גישה לאסימון הזה.

הערה לגבי מסירת הודעות ב-Android

כשהאפליקציה לא פועלת בכלל ומשתמש מקיש על התראה, כברירת מחדל ההודעה לא מנותבת דרך פונקציות ה-callback המובנות של FCM. במקרה כזה, המטענים הייעודיים של ההודעות מתקבלים דרך Intent שמשמש להפעלת האפליקציה. כדי ש-FCM תעביר את ההודעות הנכנסות האלה לקריאה החוזרת (callback) של ספריית C++‎, צריך לשנות את השיטה onNewIntent ב-Activity ולהעביר את ה-Intent אל MessageForwardingService.

import com.google.firebase.messaging.MessageForwardingService;

class MyActivity extends Activity {
  private static final String TAG = "MyActvity";

  @Override
  protected void onNewIntent(Intent intent) {
    Log.d(TAG, "A message was sent to this app while it was in the background.");
    Intent message = new Intent(this, MessageForwardingService.class);
    message.setAction(MessageForwardingService.ACTION_REMOTE_INTENT);
    message.putExtras(intent);
    message.setData(intent.getData());
    // For older versions of Firebase C++ SDK (< 7.1.0), use `startService`.
    // startService(message);
    MessageForwardingService.enqueueWork(this, message);
  }
}

הודעות שמתקבלות כשהאפליקציה פועלת ברקע משתמשות בתוכן של שדה ההתראה כדי לאכלס את ההתראה במגש המערכת, אבל תוכן ההתראה לא יועבר אל FCM. כלומר, הערך של Message::notification יהיה null.

בקצרה:

מצב האפליקציה התראה נתונים שניהם
חזית OnMessageReceived OnMessageReceived OnMessageReceived
רקע מגש המערכת OnMessageReceived התראה: מגש המערכת
נתונים: בתוספות של ה-intent.

טיפול בהודעות בהתאמה אישית ב-Android

כברירת מחדל, התראות שנשלחות לאפליקציה מועברות אל ::firebase::messaging::Listener::OnMessageReceived, אבל במקרים מסוימים יכול להיות שתרצו לשנות את פעולת ברירת המחדל. כדי לעשות את זה ב-Android, צריך לכתוב מחלקות בהתאמה אישית שמרחיבות את com.google.firebase.messaging.cpp.ListenerService ולעדכן את קובץ ה-AndroidManifest.xml של הפרויקט.

שינוי ListenerService methods

‫ListenerService היא מחלקת Java שמיירטת הודעות נכנסות שנשלחות לאפליקציה ומנתבת אותן לספריית C++‎. כשהאפליקציה פועלת בחזית (או כשהאפליקציה פועלת ברקע והיא מקבלת מטען ייעודי (payload) של נתונים בלבד), ההודעות יעברו דרך אחד מהקריאות החוזרות (callbacks) שסופקו במחלקה הזו. כדי להוסיף התנהגות מותאמת אישית לטיפול בהודעות, צריך להרחיב את ברירת המחדל של ListenerService ב-FCM:

import com.google.firebase.messaging.cpp.ListenerService;

class MyListenerService extends ListenerService {

כדי לבצע פעולות על סמך אובייקט RemoteMessage שהתקבל ולקבל את נתוני ההודעה, אפשר לשנות את השיטה ListenerService.onMessageReceived:

@Override
public void onMessageReceived(RemoteMessage message) {
  Log.d(TAG, "A message has been received.");
  // Do additional logic...
  super.onMessageReceived(message);
}

ל-ListenerService יש גם כמה שיטות אחרות שמשתמשים בהן פחות. אפשר גם לשנות את ברירת המחדל הזו. מידע נוסף זמין במאמר העזר בנושא FirebaseMessagingService.

@Override
public void onDeletedMessages() {
  Log.d(TAG, "Messages have been deleted on the server.");
  // Do additional logic...
  super.onDeletedMessages();
}

@Override
public void onMessageSent(String messageId) {
  Log.d(TAG, "An outgoing message has been sent.");
  // Do additional logic...
  super.onMessageSent(messageId);
}

@Override
public void onSendError(String messageId, Exception exception) {
  Log.d(TAG, "An outgoing message encountered an error.");
  // Do additional logic...
  super.onSendError(messageId, exception);
}

עדכון של AndroidManifest.xml

אחרי שכותבים את המחלקות בהתאמה אישית, צריך לכלול אותן ב-AndroidManifest.xml כדי שהן ייכנסו לתוקף. חשוב לוודא שהמניפסט כולל את כלי המיזוג על ידי הצהרה על המאפיין המתאים בתוך התג <manifest>, כך:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.firebase.messaging.cpp.samples"
    xmlns:tools="http://schemas.android.com/tools">

בארכיון firebase_messaging_cpp.aar יש קובץ AndroidManifest.xml שמצהיר על ברירת המחדל של ListenerService ב-FCM. המניפסט הזה בדרך כלל מתמזג עם המניפסט הספציפי לפרויקט, וכך ListenerService יכול לפעול. צריך להחליף את ListenerService בשירות המאזין בהתאמה אישית. כדי לעשות את זה, מסירים את ברירת המחדל של ListenerService ומוסיפים את השירות בהתאמה אישית. אפשר לעשות את זה באמצעות השורות הבאות בקובץ AndroidManifest.xml של הפרויקט:

<service android:name="com.google.firebase.messaging.cpp.ListenerService"
         tools:node="remove" />
<service android:name="com.google.firebase.messaging.cpp.samples.MyListenerService"
         android:exported="false">
  <intent-filter>
    <action android:name="com.google.firebase.MESSAGING_EVENT"/>
  </intent-filter>
</service>

גרסאות חדשות של Firebase C++ SDK (מגרסה 7.1.0 ואילך) משתמשות ב-JobIntentService, וצריך לבצע שינויים נוספים בקובץ AndroidManifest.xml.

<service android:name="com.google.firebase.messaging.MessageForwardingService"
     android:permission="android.permission.BIND_JOB_SERVICE"
     android:exported="false" >
</service>

מניעת הפעלה אוטומטית

‫FCM יוצר אסימון רישום לטירגוט של מופע אפליקציה. כשנוצר אסימון, הספרייה מעלה את המזהה ואת נתוני ההגדרות ל-Firebase. אם אתם רוצים לקבל הסכמה מפורשת לפני השימוש בטוקן, אתם יכולים למנוע את היצירה שלו בזמן ההגדרה על ידי השבתת FCM (וב-Android, השבתת Analytics). כדי לעשות את זה, מוסיפים ערך של מטא-נתונים ל-Info.plist (לא ל-GoogleService-Info.plist) בפלטפורמות של אפל, או ל-AndroidManifest.xml ב-Android:

Android

<?xml version="1.0" encoding="utf-8"?>
<application>
  <meta-data android:name="firebase_messaging_auto_init_enabled"
             android:value="false" />
  <meta-data android:name="firebase_analytics_collection_enabled"
             android:value="false" />
</application>

Swift

FirebaseMessagingAutoInitEnabled = NO

כדי להפעיל מחדש את FCM, אפשר לבצע קריאה בזמן ריצה:

::firebase::messaging::SetRegistrationOnInitEnabled(true);

אחרי שמגדירים את הערך הזה, הוא נשמר גם כשמפעילים מחדש את האפליקציה.

‫FCM מאפשר לשלוח הודעות שמכילות קישור עומק לאפליקציה. כדי לקבל הודעות שמכילות קישור עומק, צריך להוסיף מסנן Intent חדש לפעילות שמטפלת בקישורי עומק באפליקציה. מסנן ה-Intent צריך לתפוס קישורי עומק של הדומיין. אם ההודעות שלכם לא מכילות קישור עומק, אין צורך בהגדרה הזו. בקובץ AndroidManifest.xml:

<intent-filter>
  <action android:name="android.intent.action.VIEW"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.BROWSABLE"/>
  <data android:host="CHANGE_THIS_DOMAIN.example.com" android:scheme="http"/>
  <data android:host="CHANGE_THIS_DOMAIN.example.com" android:scheme="https"/>
</intent-filter>

אפשר גם לציין תו כללי לחיפוש כדי להגמיש את מסנן ה-Intent. לדוגמה:

<intent-filter>
  <action android:name="android.intent.action.VIEW"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.BROWSABLE"/>
  <data android:host="*.example.com" android:scheme="http"/>
  <data android:host="*.example.com" android:scheme="https"/>
</intent-filter>

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

השלבים הבאים

אחרי שתסיימו את שלבי ההגדרה, תוכלו להמשיך עם FCM ל-C++‎ בכמה דרכים: