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

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

הגדרת Firebase ו-FCM SDK

Android

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

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

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

  2. יוצרים אובייקט Firebase App, ומעבירים את הסביבה ו-Activity של 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.

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.

    1. בתוך הפרויקט במסוף Firebase, לוחצים על סמל גלגל השיניים, בוחרים באפשרות Project Settings (הגדרות הפרויקט) ואז בוחרים בכרטיסייה Cloud Messaging (Cloud Messaging).

    2. בקטע APNs authentication key בקטע iOS app configuration, לוחצים על הלחצן Upload.

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

  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 Cloud Messaging ומעבירים את האפליקציה ואת ה-Listener שנוצר:

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

גישה לטוקן הרישום של המכשיר

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

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

הערה לגבי שליחת הודעות ב-Android

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

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

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

שינוי שיטות ListenerService.

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

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

class MyListenerService extends ListenerService {

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

@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) בפלטפורמות של Apple, או ל-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::SetTokenRegistrationOnInitEnabled(true);

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

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

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

השלבים הבאים

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

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

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