Once your client app is installed on a device, it can receive messages through the FCM APNs interface. You can immediately start sending notifications to user segments with the Notifications composer, or your application server can send messages with a notification payload through the APNs interface.
Handling messages received through the FCM APNs interface is likely to cover most typical use cases. For special use cases demanding very high reliability, you can handle direct FCM channel message in your app. You can also send upstream messages.
Handle messages received through the FCM APNs interface
When your app is in the background, iOS
directs messages with the notification
key to the system tray.
A tap on a notification
opens the app, and the content of the notification is passed to the
didReceiveRemoteNotification
callback in the
AppDelegate
.
Implement AppDelegate application:didReceiveRemoteNotification:
as shown:
Swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { // 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 message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print(userInfo) } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // 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 message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print(userInfo) completionHandler(UIBackgroundFetchResult.newData) }
Objective-C
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // 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 // [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; // Print message ID. if (userInfo[kGCMMessageIDKey]) { NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]); } // Print full message. NSLog(@"%@", userInfo); } - (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 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 // [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; // Print message ID. if (userInfo[kGCMMessageIDKey]) { NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]); } // Print full message. NSLog(@"%@", userInfo); completionHandler(UIBackgroundFetchResultNewData); }
If you want to open your app and perform
a specific action, set click_action
in the
notification payload. Use the value that you would use for the
category
key in the APNs payload.
Interpreting notification message payload
The payload of notification messages is a dictionary of keys and values. Notification messages sent through APNs follow the APNs payload format as below:
{ "aps" : { "alert" : { "body" : "great match!", "title" : "Portugal vs. Denmark", }, "badge" : 1, }, "customKey" : "customValue" }
Handle messages with method swizzling disabled
If you disable method swizzling, you'll need to call a method to let FCM track message delivery and analytics. This is performed automatically with method swizzling enabled.
In iOS 10 and above, you can set the
UNUserNotificationCenter delegate
to receive display notifications from Apple and
FIRMessaging
's delegate
property to receive data messages from FCM. If you do not set these two
delegates with AppDelegate, method swizzling for message handling is disabled.
You'll need to call
appDidReceiveMessage:
to track message delivery and analytics.
Objective-C: iOS 10
// 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 message ID. if (userInfo[kGCMMessageIDKey]) { NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]); } // Print full message. NSLog(@"%@", userInfo); // Change this to your preferred presentation option completionHandler(UNNotificationPresentationOptionNone); } // Handle notification messages after display notification is tapped by the user. - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler { NSDictionary *userInfo = response.notification.request.content.userInfo; if (userInfo[kGCMMessageIDKey]) { NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]); } // Print full message. NSLog(@"%@", userInfo); completionHandler(); }
Objective-C: iOS 9 and below
// With "FirebaseAppDelegateProxyEnabled": NO - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler: (void (^)(UIBackgroundFetchResult))completionHandler { // Let FCM know about the message for analytics etc. [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; // handle your message. }
Swift: iOS 10
@available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { // Receive displayed notifications for iOS 10 devices. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo // With swizzling disabled you must let Messaging know about the message, for Analytics // Messaging.messaging().appDidReceiveMessage(userInfo) // Print message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print(userInfo) // Change this to your preferred presentation option completionHandler([]) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo // Print message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print(userInfo) completionHandler() } }
Swift: iOS 9 and below
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { // Let FCM know about the message for analytics etc. FIRMessaging.messaging().appDidReceiveMessage(userInfo) // handle your message }
Handle direct FCM channel messages
To reliably receive silent, data-only messages directly from FCM,
bypassing APNs when the app is in the foreground,
you'll need to connect to the FCM service and
handle messages with FIRMessagingDelegate
's
messaging:didReceiveMessage:
method. With the direct channel
enabled,the FCM backend uses a reliable message queue to keep track of pending
messages when the app is in the background or closed. When the app goes to the
foreground and the connection is re-established, the channel will automatically
send pending messages to the client until it gets an acknowledgement from the
client.
To connect, set the shouldEstablishDirectChannel
flag to
YES
in the AppDelegate
. FCM manages the
connection, closing it when your app goes into the background and reopening it
whenever the app is foregrounded.
Interpreting data message payload
The payload of data messages is a dictionary of keys and values. Data messages sent to the devices directly by FCM server are expressed in the format of a dictionary as below:
{ "body" : "great match!", "title" : "Portugal vs. Denmark", "icon" : "myicon" }
Handle queued and deleted messages
Apps that connect to FCM to receive data messages should handle
FIRMessagingMessagesDeletedNotification
. You may receive this
callback when there are too many messages (>100) pending for
your app on a particular device at the time it connects, or if the device hasn't
connected to FCM for more than one month. When the
app instance receives this callback,
it should perform a full sync with your app server.
For insight into message delivery to your app, see the FCM reporting dashboard, which records the number of messages sent and opened on iOS and Android devices, along with data for "impressions" (notifications seen by users) for Android apps.