קבלת הודעות באפליקציות של פלטפורמת Apple

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


אחרי שמתקינים את אפליקציית הלקוח במכשיר, היא יכולה לקבל הודעות דרך ממשק ה-APNs של FCM. אתם יכולים להתחיל לשלוח התראות לפלחי משתמשים באופן מיידי באמצעות הכלי ליצירת התראות במסוף Firebase, או הודעות שנוצרו בשרת האפליקציה שלכם.

טיפול בהתראות

‫FCM מעביר את כל ההודעות שמטרגטות אפליקציות של אפל דרך APNs. מידע נוסף על קבלת התראות APNs באמצעות UNUserNotificationCenter זמין במאמרי העזרה של אפל בנושא טיפול בהתראות ובפעולות שקשורות להתראות.

כדי לקבל התראות תצוגה מ-FCM, צריך להגדיר את הנציג של UNUserNotificationCenter ולהטמיע את השיטות המתאימות של הנציג.

Swift

// Receive displayed notifications for iOS 10+ devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification) async
  -> UNNotificationPresentationOptions {
  let userInfo = notification.request.content.userInfo

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // Messaging.messaging().appDidReceiveMessage(userInfo)

  // ...

  // Print full message.
  print(userInfo)

  // Change this to your preferred presentation option
  // Note: UNNotificationPresentationOptions.alert has been deprecated.
  return [.list, .banner, .sound]
}

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse) async {
  let userInfo = response.notification.request.content.userInfo

  // ...

  // Print full message.
  print(userInfo)
}

Objective-C

// Receive displayed notifications for iOS 10+ devices.
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
  NSDictionary *userInfo = notification.request.content.userInfo;

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  // Print full message.
  NSLog(@"%@", userInfo);

  // Change this to your preferred presentation option
  completionHandler(UNNotificationPresentationOptionList |
                    UNNotificationPresentationOptionBanner |
                    UNNotificationPresentationOptionSound);
}

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration token: %@", fcmToken);
    // Notify about received token.
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
    // TODO: If necessary send token to application server.
    // Note: This callback is fired at each app startup and whenever a new token is generated.
}

- (void)logFCMToken {
  NSString *fcmToken = [FIRMessaging messaging].FCMToken;
  NSLog(@"Local FCM registration token: %@", fcmToken);

  NSString* displayToken = [NSString stringWithFormat:@"Logged FCM token: %@", fcmToken];

  [[FIRMessaging messaging] tokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) {
    if (error != nil) {
      NSLog(@"Error fetching the remote FCM registration token: %@", error);
    } else {
      NSLog(@"Remote FCM registration token: %@", token);
      NSString* message =
        [NSString stringWithFormat:@"FCM registration token: %@", token];
      // display message
      NSLog(@"%@", message);
    }
  }];
  NSLog(@"%@", displayToken);
}

- (void)subsribeToTopic {
  [[FIRMessaging messaging] subscribeToTopic:@"weather"
                                  completion:^(NSError * _Nullable error) {
    NSLog(@"Subscribed to weather topic");
  }];
}

@end

אם רוצים להוסיף פעולות בהתאמה אישית להתראות, מגדירים את הפרמטר click_action במטען הייעודי (payload) של ההתראה. משתמשים בערך שבו הייתם משתמשים למפתח category במטען הייעודי (payload) של APNs. כדי להשתמש בפעולות בהתאמה אישית, צריך לרשום אותן. מידע נוסף זמין במאמר Local and Remote Notification Programming Guide של אפל.

כדי לקבל תובנות לגבי מסירת ההודעות לאפליקציה, נכנסים ללוח הבקרה DevOps & Engagement (DevOps ומעורבות) > Messaging (העברת הודעות) > Reports (דוחות) במסוף Firebase. בלוח הבקרה הזה מתועד מספר ההודעות שנשלחו ונפתחו במכשירי אפל ובמכשירי Android, וגם נתונים לגבי "חשיפות" (התראות שהמשתמשים ראו) באפליקציות ל-Android.

טיפול בהתראות שקטות

כששולחים הודעות עם המפתח content-available (המקביל ל-content-available של APNs), ההודעות נמסרות כהתראות שקטות, ומעירות את האפליקציה ברקע למשימות כמו רענון נתונים ברקע. בניגוד להתראות בחזית, צריך לטפל בהתראות האלה באמצעות השיטה application(_:didReceiveRemoteNotification:fetchCompletionHandler:).

מטמיעים את application(_:didReceiveRemoteNotification:fetchCompletionHandler:) כמו שמוצג:

Swift

@MainActor
func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
  -> UIBackgroundFetchResult {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // Messaging.messaging().appDidReceiveMessage(userInfo)

  // ...

  // Print full message.
  print(userInfo)
  print("Call exportDeliveryMetricsToBigQuery() from AppDelegate")
  Messaging.serviceExtension().exportDeliveryMetricsToBigQuery(withMessageInfo: userInfo)
  return UIBackgroundFetchResult.newData
}

Objective-C

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired until the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  // Print full message.
  NSLog(@"%@", userInfo);

  completionHandler(UIBackgroundFetchResultNewData);
}

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

פירוש המטען הייעודי (payload) של הודעת ההתראה

המטען הייעודי (payload) של הודעות ההתראה הוא מילון של מפתחות וערכים. הודעות התראה שנשלחות דרך APNs הן בפורמט המטען הייעודי (payload) הבא של APNs:

  {
    "aps" : {
      "alert" : {
        "body" : "great match!",
        "title" : "Portugal vs. Denmark",
      },
      "badge" : 1,
    },
    "customKey" : "customValue"
  }

טיפול בהודעות כשהתכונה "שינוי פונקציונליות של שיטה" מושבתת

כברירת מחדל, אם מקצים את מחלקת הנציג של האפליקציה למאפייני הנציג UNUserNotificationCenter ו-Messaging, FCM יבצע swizzling למחלקת הנציג של האפליקציה כדי לשייך באופן אוטומטי את טוקן FCM לטוקן APNs של המכשיר, ויעביר אירועים של קבלת התראות אל Analytics. אם אתם משביתים באופן מפורש את שינוי הפונקציונליות של השיטה, אם אתם מפתחים אפליקציית SwiftUI או אם אתם משתמשים במחלקה נפרדת לכל אחד מהנציגים, תצטרכו לבצע את שתי המשימות האלה באופן ידני.

כדי לשייך את הטוקן של FCM לטוקן של APNs במכשיר, מעבירים את הטוקן של APNs למחלקה Messaging ב-delegate של האפליקציה, ב-token refresh handler, באמצעות המאפיין apnsToken.

Swift

func application(_ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  Messaging.messaging().apnsToken = deviceToken;
}

Objective-C

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [FIRMessaging messaging].APNSToken = deviceToken;
}

כדי להעביר מידע על קבלת התראות אל Analytics, משתמשים ב-appDidReceiveMessage(_:) method.

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification,
  withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
  let userInfo = notification.request.content.userInfo

  Messaging.messaging().appDidReceiveMessage(userInfo)

  // Change this to your preferred presentation option
  completionHandler([[.alert, .sound]])
}

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {
  let userInfo = response.notification.request.content.userInfo

  Messaging.messaging().appDidReceiveMessage(userInfo)

  completionHandler()
}

func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
  fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  Messaging.messaging().appDidReceiveMessage(userInfo)
  completionHandler(.noData)
}

Objective-C

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
      willPresentNotification:(UNNotification *)notification
        withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
  NSDictionary *userInfo = notification.request.content.userInfo;

  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  // Change this to your preferred presentation option
  completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionAlert);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
        withCompletionHandler:(void(^)(void))completionHandler {
  NSDictionary *userInfo = response.notification.request.content.userInfo;

  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  completionHandler();
}

- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
  completionHandler(UIBackgroundFetchResultNoData);
}