הגדרה של אפליקציית לקוח להעברת הודעות בענן ב-Firebase באמצעות C++

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

הגדרת Firebase ו-FCM SDK

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

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

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

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

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

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

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

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

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

  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, לוחצים על סמל גלגל השיניים, בוחרים באפשרות הגדרות הפרויקט ואז בוחרים בכרטיסייה Cloud Messaging.

    2. בקטע הגדרת אפליקציה ל-iOS, בשדה מפתח אימות של APNs, לוחצים על לחצן העלאה.

    3. מדפדפים למיקום שבו שמרתם את המפתח, בוחרים אותו ולוחצים על פתיחה. מוסיפים את מזהה המפתח (שזמין ב- Apple Developer Member Center) ולוחצים על העלאה.

  3. מגדירים את פרויקט Xcode כדי להפעיל התראות בדחיפה:

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

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

        המסגרת הזו מופיעה רק ב-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 Cloud Messaging, מתבצעת בקשה לקבלת אסימון רישום עבור מופע אפליקציית הלקוח. האפליקציה תקבל את האסימון באמצעות הקריאה החוזרת OnTokenReceived, שצריכה להיות מוגדרת במחלקה שמיישמת את firebase::messaging::Listener.

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

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

כשהאפליקציה לא פועלת בכלל ומשתמש מקיש על התראה, ההודעה לא מנותבת כברירת מחדל דרך הקריאות החוזרות המובנות של FCM. במקרה כזה, מטעני הודעות מתקבלים דרך Intent שמשמש להפעלת האפליקציה. כדי ש-FCM יעביר את ההודעות הנכנסות האלה לקריאה החוזרת של ספריית 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 התראה: מגש המערכת
נתונים: בתוספות של הכוונה.

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

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

שינוי מברירת המחדל של ListenerService אמצעי תשלום.

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

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:

AndroidSwift
<?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>
FirebaseMessagingAutoInitEnabled = NO

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

::firebase::messaging::SetTokenRegistrationOnInitEnabled(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-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>

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

השלבים הבאים

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

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

חשוב לזכור: כדי להשתמש בתכונות האלה, צריך להטמיע הטמעה בצד השרת.