Continuing our series on Firebase, in this post we’ll take a look at Firebase Cloud Messaging—or FCM for short—Google’s low-latency message and notification orchestration service for mobile apps. For as long as iPhones have been around, push notifications have played a crucial role in notifying users at predetermined times of important events, whether a notification of a Skype message or call, a direct message on Twitter, or gaming alerts. Through carefully-crafted, segmented push notifications, marketers have boosted app engagement and user retention. You can do the same, by leveraging FCM to:
- target predefined or custom user segments, taking advantage of demographics and user behavior
- deliver immediate or scheduled push notifications
- integrate FCM into Google Analytics to provide detailed conversation monitoring, and perform A/B testing
- create a fully-immersing instant messaging application
Assumed Knowledge
This tutorial assumes you have a working knowledge of iOS and Swift, as well as some basic experience with CocoaPods. If you need to learn more, check out our Swift tutorials and CocoaPods tutorials.
Objectives of this article
In this article, you will learn all about FCM, as we will be covering the following topics:
- setup of an FCM project
- configure your environment for FCM
- receive and handle messages
- send a message to your device
- topic and group messaging
- target segments and analytics
What is Firebase Cloud Messaging (FCM)?
Concisely put, Firebase Cloud Messaging—or FCM for short—is a cross-platform cloud messaging and notification solution from Google, enabling developers to send push notifications to their app end users through the Firebase Notification Composer, or a Firebase-exposed set of APIs. FCM supports two types of messages: notification messages and data messages.
Notification messages are explicit push notification messages that display on the user’s device, to either inform or solicit engagement, such as a Facebook Messenger message notification. Data messages, by contrast, are directly processed by the application in the background and can be used to update a table view without the app in the foreground.
Through message targeting, FCM can deliver messages to single devices, groups of devices or devices subscribed to topics. The targeted groups directly integrate with Firebase Analytics, so that you can track engagement and conversions, crafting purposeful customer segments. Next, we are going to go through the process of setting up a Firebase project for iOS.
Setup the Project
In this series, we’re going to build a simple app that doesn’t do much, besides triggering and receiving messages from FCM. Let’s start by cloning the project from GitHub:
$ [email protected]:doronkatz/get-started-with-fcm-for-ios.git ... $ git fetch --all --tags ... $ git checkout tags/START
Opening up the Podfile
in the root directory, you notice that we have imported the necessary Firebase modules:
# Uncomment the next line to define a global platform for your project platform :ios, '10.0' target 'Firebase-FCM' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! # Pods for Firebase-FCM pod 'Firebase/Core' pod 'Firebase/Messaging' end
Enter the following to build the pods:
pod install
Open up the workspace Firebase-FCM.xcworkspace
, and in a browser, go to the Firebase panel and create a new project:
Next, click on Add Firebase to your iOS app, which walks you step by step through the process of registering your app on Firebase.
At some point, it asks you to add the GoogleService-info.plist file into your Xcode project:
You’ve already added the libraries via CocoaPods, so you can skip the remaining instructions and return to the Firebase console.
In Xcode, open up AppDelegate.swift and you will see we have initialized the project by importing Firebase and adding FirebaseApp.configure()
:
import UIKit import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { *var* window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { /// Override point for customization after application launch./ FirebaseApp.configure() return true } ...
Build and run the app to make sure there are no errors, and while the app doesn’t do anything, it kicks off the initial call to Firebase confirming that you can connect to the cloud. Next, we are going to configure our APNs.
Configuring your environment for FCM
FCM makes use of the Apple Push Notification service (APNs) to send and receive messages, so we need to enable Push Notifications through APNs. First, in the Apple Developer Portal, create an authentication key.
Create an APNs Authentication Key
First, go to Certificates > Identifiers & Profiles, and select All under Keys:
Now, enter a key description for the APNs Auth Key, making sure you select Apple Push Notifications service (APNs). Store this key somewhere safe, as this is a one-time download.
Next, you need to create an App ID, so that your app can be identifiable. Select Identifiers > App IDs from the navigation menu and click the + button to add a new iOS App ID. Enter a description and App ID suffix for your app, matching what you have in your Xcode project. Make sure you also select Push Notifications in the service check box.
Head back to your Firebase panel and under Project Settings select the Cloud Messaging tab. Under APNs Authentication Key within the iOS app configuration, click the Upload button. Now upload the APNs auth key you downloaded from the Apple Developer Portal.
Authorize Push Notifications in the App
In your AppDelegate.swift, add the following code:
import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { /// Override point for customization after application launch. FirebaseApp.configure() UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (_, error) in guard error == nil else{ print(error!.localizedDescription) return } } application.registerForRemoteNotifications() return true }
Here we are importing UserNotifications
, declaring our intent to implement UNUserNotificationCenterDelegate
and requesting user permission for notifications using UNUserNotificationCenter.current().requestAuthorization()
.
In addition to the APNs token we generated previously, FCM also generates a token that is used to target specific device application instances via messaging:didReceiveRegistrationToken:
. This is retrieved during application launch, and the token is updated whenever it expires or is somehow invalidated.
Still within our AppDelegate.swift file, add the following below the FirebaseApp.configure()
declaration:
class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? let gcmMessageIDKey = "gcm.message_id" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. FirebaseApp.configure() Messaging.messaging().delegate = self UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] ...
Note that we’ve also added MessagingDelegate
to our class declaration. The tokens are retrieved using messaging:didReceiveRegistrationToken:
and are called once at the start of your app launch, with the results sent to your application server. Add the following to the bottom of your didFinishLaunchingWithOptions:
method:
//Solicit permission from the user to receive notifications UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (_, error) in guard error == nil else{ print(error!.localizedDescription) return } } //get application instance ID InstanceID.instanceID().instanceID { (result, error) in if let error = error { print("Error fetching remote instance ID: (error)") } else if let result = result { print("Remote instance ID token: (result.token)") } } application.registerForRemoteNotifications() return true }
We need to explicitly ask the user to accept push notifications, before sending messages. The requestAuthorization(options: authOptions)
method does just that. When the token does get refreshed, your app gets notified via the following messaging delegate method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: (messageID)") } // Print full message. print(userInfo) } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("Unable to register for remote notifications: (error.localizedDescription)") }
The last method allows you to receive messages in the foreground, directly from FCM to bypass our APNs proxy. Next, we work on handling Push Notifications.
Receiving and Handling Messages
To receive notifications, we need to register for notifications. When your app is in background mode, your notifications are delivered to the system tray until your app opens, at which point the notification packet is then passed to the didReceiveRemoteNotification:
callback in the AppDelegate
. Let’s implement that next:
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { print("Firebase registration token: (fcmToken)") let dataDict:[String: String] = ["token": fcmToken] NotificationCenter.default.post(name: Notification.Name("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. } func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) { print("Received data message: (remoteMessage.appData)") }
Test the Firebase Registration Token is Received
Build & run your app, making sure you run it on your physical device, as you cannot receive push notifications on your Simulator. Right now the app does nothing visually, but if you take note of your Xcode console, you should see that you’ve successfully received a Firebase registration token ID:
We are now ready to move on to the final step, sending messages to our app.
Sending a Message to your Device
In the previous step, we should have successfully run our app without any errors reported in our console. Build & run your app again in Xcode, but make sure your app is in the background while the Xcode run process is still running by swiping up to get to your home screen.
We are going to create a message using Firebase’s Notifications composer, so head over there in your browser, and enter a sample text. Make sure you select single device for your message target.
You would have noticed throughout the Compose message wizard that you can also target other segments, and even schedule your message to go out at a future date. For this exercise, we are going to send a message now. Press Publish to send your message. Glance over to your phone and you should see your message appear.
Topic and Group Messaging
In this tutorial, you learned about how to receive push notifications using FCM, but we merely scratched the surface of what we can do with FCM. In our example, we targeted a single device, you would most likely be targeting devices subscribing to particular groups or are following particular topics.
Topic messaging lets you have your users subscribe to particular topics, such as live scores for your favorite college team, or weather updates to your user’s particular location of interest. Users can subscribe to an unlimited number of topics, with FCM optimizing messages for throughput rather than latency. For more information on working with topic messaging, please consult the Topic Messaging on iOS section of Firebase’s documentation.
If you are looking to send messages to multiple devices per user, such as a user’s iPhone and iPad, device group messaging would be more to your suiting. Device group messaging enables you to send a single message to multiple instances of an app running on devices belonging to a group. (Device Group Messaging on iOS), where the group usually means a single user with a set of related devices, sharing a common FCM notification key.
For either type of messaging, rather than use Notifications composer, you would employ a more automated and sophisticated form of message triggering using Firebase’s Admin SDKs.
Target Segments and Analytics
In addition to sending messages to topics and groups, you can also carefully target user segments based on various other marketing properties. That is, you can employ FCM to run A/B or other types of experiments to enable you to gauge and test hypotheses and observe key engagement metrics.
A/B Testing works with FCM so you can test different marketing messages, and with Remote Config so you can test changes within your app. (Firebase)
For more information, refer to Firebase’s documentation on Firebase A/B Testing
You can download the full source for for this project by cloning the Firebase iOS push notification demo app repo from our GitHub account.
Conclusion
In this tutorial, you learned about Firebase Cloud Messaging and how you can easily take your iOS app to the next level by employing push notifications as a means of engaging your users and increasing retention. FCM provides more than just a way for your app to communicate with its users—it also provides compelling way for you to employ sophisticated marketing strategies to send messages to the right users, at the right time, based on various algorithms that you can craft. FCM is extremely easy to implement at base, but it provides a level of sophistication and extensibility unmatched in the marketplace.
Powered by WPeMatico