Advertisement
  1. Code
  2. Mobile Development
  3. iOS Development

Send Push Notifications to Your iOS App With Firebase Cloud Messaging

Scroll to top

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
  • configuring your environment for FCM
  • receiving and handling messages
  • sending a message to your device
  • topic and group messaging
  • targeting 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's 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.

Firebase logoFirebase logoFirebase logo

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.

Set Up 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:

1
$ git@github.com:doronkatz/get-started-with-fcm-for-ios.git
2
...
3
$ git fetch --all --tags
4
...
5
$ git checkout tags/START

Opening up the Podfile in the root directory, you notice that we have imported the necessary Firebase modules:

1
# Uncomment the next line to define a global platform for your project

2
platform :ios, '10.0'
3
4
target 'Firebase-FCM' do
5
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks

6
  use_frameworks!
7
8
  # Pods for Firebase-FCM

9
  pod 'Firebase/Core'
10
  pod 'Firebase/Messaging'  
11
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:

Create a project in the Firebase panelCreate a project in the Firebase panelCreate a project in the Firebase panel

Next, click on Add Firebase to your iOS app, which walks you step by step through the process of registering your app on Firebase.

Add Firebase to your iOS appAdd Firebase to your iOS appAdd Firebase to your iOS app

At some point, it asks you to add the GoogleService-info.plist file into your Xcode project:

add the GoogleService-infoplist file into your Xcode projectadd the GoogleService-infoplist file into your Xcode projectadd the GoogleService-infoplist 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():

1
import UIKit
2
import Firebase
3
4
@UIApplicationMain
5
class AppDelegate: UIResponder, UIApplicationDelegate {
6
7
    *var* window: UIWindow?
8
9
10
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
11
        /// Override point for customization after application launch./
12
        FirebaseApp.configure()
13
        return true
14
    }
15
16
...

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:

Create a new key in Apple Developer PortalCreate a new key in Apple Developer PortalCreate a new key in Apple Developer Portal

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.

Register App ID in Developer PortalRegister App ID in Developer PortalRegister App ID in Developer Portal

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.

Upload APN Auth KeyUpload APN Auth KeyUpload APN Auth Key

Authorize Push Notifications in the App

In your AppDelegate.swift, add the following code:

1
import UserNotifications
2
3
@UIApplicationMain
4
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
5
6
    var window: UIWindow?
7
8
9
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
10
        /// Override point for customization after application launch.
11
        FirebaseApp.configure()
12
        
13
        UNUserNotificationCenter.current().delegate = self
14
        
15
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
16
        
17
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (_, error) in
18
            guard error == nil else{
19
                print(error!.localizedDescription)
20
                return
21
            }
22
        }
23
        
24
        application.registerForRemoteNotifications()
25
        return true
26
    }

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:

1
class AppDelegate: UIResponder, UIApplicationDelegate {
2
3
    var window: UIWindow?
4
    let gcmMessageIDKey = "gcm.message_id"
5
    
6
7
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
8
        // Override point for customization after application launch.
9
        FirebaseApp.configure()
10
        Messaging.messaging().delegate = self
11
        
12
        UNUserNotificationCenter.current().delegate = self
13
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
14
...

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:

1
//Solicit permission from the user to receive notifications
2
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (_, error) in
3
            guard error == nil else{
4
                print(error!.localizedDescription)
5
                return
6
            }
7
        }
8
        
9
        //get application instance ID
10
        InstanceID.instanceID().instanceID { (result, error) in
11
            if let error = error {
12
                print("Error fetching remote instance ID: \(error)")
13
            } else if let result = result {
14
                print("Remote instance ID token: \(result.token)")
15
            }
16
        }
17
        
18
        application.registerForRemoteNotifications()
19
        return true
20
    }

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:

1
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
2
        if let messageID = userInfo[gcmMessageIDKey] {
3
            print("Message ID: \(messageID)")
4
        }
5
        
6
        // Print full message.
7
        print(userInfo)
8
    }
9
10
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
11
        print("Unable to register for remote notifications: \(error.localizedDescription)")
12
    }

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:

1
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
2
        print("Firebase registration token: \(fcmToken)")
3
        
4
        let dataDict:[String: String] = ["token": fcmToken]
5
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
6
        // TODO: If necessary send token to application server.
7
        // Note: This callback is fired at each app startup and whenever a new token is generated.
8
    }
9
    
10
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
11
        print("Received data message: \(remoteMessage.appData)")
12
    }

Test That the Firebase Registration Token Is Received

Build and 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:

Console confirming Firebase registration token IDConsole confirming Firebase registration token IDConsole confirming 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 and 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 some sample text. Make sure you select a single device for your message target. 

Compose message with Notifications ComposerCompose message with Notifications ComposerCompose message with Notifications Composer

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.

Push notification appearing on your devicePush notification appearing on your devicePush notification appearing on your device

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, but you would most likely be targeting devices subscribing to particular groups or 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 in 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 appropriate. Device group messaging enables you to send a single message to multiple instances of an app running on devices belonging to a group, where the group usually means a single user with a set of related devices, sharing a common FCM notification key. For more on this, see the Device Group Messaging on iOS section of the Firebase documentation.

For either type of messaging, rather than using 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 code 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 a 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, but it provides a level of sophistication and extensibility unmatched in the marketplace.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.