Add push notifications to an iOS app

1. Introduction

Last Updated: 2020-1-6

Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost.

Using FCM, you can notify a client app that new email or other data is available to sync. You can send notification messages to drive user re-engagement and retention. For use cases such as instant messaging, a message can transfer a payload of up to 4KB to a client app.

How does it work?

A FCM implementation includes two main components for sending and receiving:

  1. A trusted environment such as Cloud Functions for Firebase or an app server on which to build, target, and send messages.
  2. An iOS, Android, or web (JavaScript) client app that receives messages via the corresponding platform-specific transport service.

FCM Architectural Overview

6636933bbe959ef2.png

FCM relies on the following set of components that build, transport, and receive messages:

  1. Tooling to compose or build message requests. The Notifications composer provides a GUI-based option for creating notification requests. For full automation and support for all message types, you must build message requests in a trusted server environment that supports the Firebase Admin SDK or the FCM server protocols. This environment could be Cloud Functions for Firebase, Google App Engine, or your own app server.
  2. The FCM backend, which (among other functions) accepts message requests, performs fanout of messages via topics, and generates message metadata such as the message ID.
  3. A platform-level transport layer, which routes the message to the targeted device, handles message delivery, and applies platform-specific configuration where appropriate. This transport layer includes:
  • Android transport layer (ATL) for Android devices with Google Play services
  • Apple Push Notification service (APNs) for iOS devices
  • Web push protocol for web apps
  1. The FCM SDK on the user's device, where the notification is displayed or the message is handled according to the app's foreground/background state and any relevant application logic.

What you'll build

In this codelab, you're going to add push notification to a sample iOS app with FCM.

What you'll learn

  • How to subscribe and unsubscribe a user for push messaging
  • How to handle incoming push messages
  • How to display a notification
  • How to respond to notification clicks

What you'll need

  • Xcode 11.0 or later
  • CocoaPods 1.9.0 or later
  • Apple Developer Account
  • A physical iOS device to run your app
  • Basic knowledge of Swift

2. Getting set up

Download the sample code

In this codelab, you will build your own test app, but if you want to see and run the existing sample app, you can download the quickstart sample code.

There are two ways to get the sample:

  • Clone the Git repository:
$ git clone https://github.com/firebase/quickstart-ios.git
  • Download the ZIP file:

If you download the source as a ZIP file, unpacking it gives you a root folder quickstart-ios.

Create a new app

Create your own test app by the following steps (the steps below are in XCode 12.3):

  1. Open XCode and select Create a new Xcode project.
  2. Select App and click Next.

e56c631b086c6d8.png

  1. Input Product Name (eg. MessagingExample)
  2. Select Team (If you have not created Team, configure it in Apple Developer Account).
  3. Input Organization Identifier (eg. com.your-name)
  4. Input Bundle Identifier (eg. com.your-name.MessagingExample, it should be unique among all iOS apps).
  5. Select Storyboard in the Interface pulldown.
  6. Select UIKit App Delegate in the Life Cycle pulldown.
  7. Select Swift in the Language.
  8. Click Next.

fb860c0fa4a02818.png

You will need the Bundle Identifier when you create an APN key and register your app to your Firebase project.

3. Configuring APNs

Create the authentication key

This section describes how to generate an authentication key for an App ID enabled for Push Notifications. If you have an existing key, you can use that key instead of generating a new one.

To create an authentication key:

  1. In your developer account, go to Certificates, Identifiers & Profiles, and navigate to Keys.

19ae87d0f00402b1.png

  1. Click the Add button (+) in the upper-right corner.

c4acd10dbc4f721f.png

  1. Enter a description for the APNs Auth Key
  2. Under Key Services, select the APNs checkbox, and click Continue.

6a3e8ff7457a8251.png

  1. Click Register and then Download. Save your key in a secure place. This is a one-time download, and the key cannot be retrieved later.

42c205e072fbd622.png

Create an App ID

An App ID is an identifier that uniquely identifies an app. As a convention it is represented by a reversed domain.

  1. Navigate to the Apple Developer Member Center and sign in.
  2. Navigate to Certificates, Identifiers and Profiles.
  3. Navigate to Identifiers.
  4. Click the + button to create a new App ID. e04fc394c52a866f.png
  5. Select the App IDs radio button, and click Continue.

d454fd5df3b8d93d.png

  1. Select App, and click Continue.

3bd2e836be5e0291.png

  1. To create the new App ID:
  2. Input a Name for your App ID.
  3. Input a Team ID. This value must match the Team ID in the Membership tab.
  4. In the App ID Suffix section, select Explicit App ID, then input your Bundle ID. 7363c4d1962b486d.png
  5. In the App Services section, make sure that Push Notifications is checked. 552ea08703f7e323.png
  6. Click Continue and check that your input is correct:
  7. The value of Identifier should match the concatenation of the values of the Team ID and of the Bundle ID
  8. Push Notifications should be Configurable
  9. Click Register to create the App ID.

Create the Profile

To test your app while under development, you need a Profile for development to authorize your devices to run an app that is not yet published on the App Store.

  1. Navigate to the Apple Developer Member Center and sign in.
  2. Navigate to Certificates, Identifiers and Profiles.
  3. In the drop down menu on the top left corner, select iOS, tvOS, watchOS if it's not already selected, then navigate to Profiles.
  4. Click the + button to create a new Profile. 1fa2342cfe45a925.png
  5. Select iOS App Development as provisioning profile type, then click Continue.

507434a466220dfe.png

  1. In the drop down menu, select the App ID you want to use, then click Continue.
  2. Select the iOS Development certificate of the App ID you have chosen in the previous step, then click Continue.
  3. Select the iOS devices that you want to include in the Provisioning Profile, then click Continue. Make sure to select all the devices you want to use for your testing.
  4. Input a name for this provisioning profile (e.g. MessagingExampleProfile), then click Generate.

4395f04647afa997.png

  1. Click Download to save the Provisioning Profile to your Mac.

106761fa786ba580.png

  1. Double-click the Provisioning Profile file to install it.

4. Adding Firebase to your iOS project

Create a Firebase project

Before you can add Firebase to your iOS app, you need to create a Firebase project to connect to your iOS app. Visit Understand Firebase Projects to learn more about Firebase projects.

  1. In the Firebase console, click Add project, then select or enter a Project name. e462afd91c149238.png

If you have an existing Google Cloud Platform (GCP) project, you can select the project from the dropdown menu to add Firebase resources to that project.

  1. (Optional) If you are creating a new project, you can edit the Project ID.

Firebase automatically assigns a unique ID to your Firebase project. Visit Understand Firebase Projects to learn about how Firebase uses the project ID.

  1. Click Continue.
  2. Set up Google Analytics for your project, which enables you to have an optimal experience using any of the following Firebase products:
  • Firebase Crashlytics
  • Firebase Predictions
  • Firebase Cloud Messaging
  • Firebase In-App Messaging
  • Firebase Remote Config
  • Firebase A/B Testing

When prompted, select to use an existing Google Analytics account or to create a new account. If you choose to create a new account, select your Analytics reporting location, then accept the data sharing settings and Google Analytics terms for your project.

1282a798556779ab.png

48ade68c8de27d2.png

  1. Click Create project (or Add Firebase, if you're using an existing GCP project).

Firebase automatically provisions resources for your Firebase project. When the process completes, you'll be taken to the overview page for your Firebase project in the Firebase console.

Register your app with Firebase

After you have a Firebase project, you can add your iOS app to it.

Visit Understand Firebase Projects to learn more about best practices and considerations for adding apps to a Firebase project, including how to handle multiple build variants.

  1. Go to the Firebase console.
  2. In the center of the project overview page, click the iOS icon to launch the setup workflow.

If you've already added an app to your Firebase project, click Add app to display the platform options.

93462beb642e8987.png

  1. Enter your app's bundle ID in the iOS bundle ID field.
  2. (Optional) Enter other app information: App nickname and App Store ID.
  3. Click Register app.

2e7a00b0008344c1.png

Add a Firebase configuration file

  1. Click Download GoogleService-Info.plist to obtain your Firebase iOS config file (GoogleService-Info.plist). 69004caf7d448989.png
  2. Move your config file into the root of your Xcode project. If prompted, select to add the config file to all targets.

7c5e0a46d07fa9c7.png

If you have multiple bundle IDs in your project, you must associate each bundle ID with a registered app in the Firebase console so that each app can have its own GoogleService-Info.plist file.

Close XCode.

Add Firebase SDKs to your app

We recommend using CocoaPods to install the Firebase libraries. However, if you'd rather not use CocoaPods, you can integrate the SDK frameworks directly or use the Swift Package Manager beta.

  1. Create a Podfile if you don't already have one. If you are using the quickstart sample, the Xcode project and Podfile (with pods) are already present.
$ cd MessagingExample
$ pod init
  1. To your Podfile, add the Firebase pods that you want to use in your app.

You can add any of the supported Firebase products to your iOS app.

In the quickstart sample, Google Analytics and Firebase Cloud Messaging SDKs have been added.

# Add the Firebase pod for Google Analytics
pod 'Firebase/Analytics'

# Add the pod for Firebase Cloud Messaging
pod 'Firebase/Messaging'
  1. Install the pods, then open your .xcworkspace file to see the project in Xcode:
$ pod install
  1. Open MessagingExample.xcworkspace, and click Next in the Firebase console. 6d1f8230d16693e6.png

Initialize Firebase in your app

You'll need to add Firebase initialization code to your application.

Import the Firebase module and configure a shared instance (In the quickstart sample, Firebase module is already imported).

  1. Import the Firebase module in your UIApplicationDelegate:

AppDelegate.swift

import UIKit
import Firebase // Add this line
  1. Configure a FirebaseApp shared instance, typically in your app's application:didFinishLaunchingWithOptions: method:

AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  FirebaseApp.configure() // Add this line
  return true
}
  1. Click Next in the Firebase console. f9d37423d346ff0.png
  2. Firebase SDKs are added to your app. Click Continue to console. d1b1309cd3790f66.png

5. Configuring FCM client

Upload your APNs authentication key

Upload your APNs authentication key to Firebase.

  1. Inside your project in the Firebase console, select the gear icon, select Project Settings, and then select the Cloud Messaging tab. ba8b5f95241327fe.png
  2. In APNs authentication key under iOS app configuration, click the Upload button. 357ddc0d4b182492.png
  3. Browse to the location where you saved your key, select it, and click Open. Add the key ID for the key (available in Certificates, Identifiers & Profiles in the Apple Developer Member Center) and click Upload. 3dae27f2327daf9e.png

Register for remote notifications

Either at startup, or at the desired point in your application flow, register your app for remote notifications.

In the quickstart sample, registerForRemoteNotifications is already added.

AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  FirebaseApp.configure()
  // [START register for remote notifications]
  if #available(iOS 10.0, *) {
    // For iOS 10 display notification (sent via APNS)
    UNUserNotificationCenter.current().delegate = self
        
    let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: {_, _ in })
  } else {
    let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
    application.registerUserNotificationSettings(settings)
  }

  application.registerForRemoteNotifications()
  // [END register for remote notifications]
  return true
}

Assign UNUserNotificationCenter's delegate property by adding these lines at the end of AppDelegate.swift.

AppDelegate.swift

@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

    // Print full message.
    print(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

    // Print full message.
    print(userInfo)

    completionHandler()
  }
}

Set the messaging delegate

To receive registration tokens, implement the messaging delegate protocol and set FIRMessaging's delegate property after calling [FIRApp configure]. For example, if your application delegate conforms to the messaging delegate protocol, you can set the delegate on application:didFinishLaunchingWithOptions: to itself (In the quickstart sample, it's already set).

AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  FirebaseApp.configure()
  Messaging.messaging().delegate = self // Add this line
  // [START register for remote notifications]
  if #available(iOS 10.0, *) {
    // For iOS 10 display notification (sent via APNS)
    UNUserNotificationCenter.current().delegate = self
        
    let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: {_, _ in })
  } else {
    let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
    application.registerUserNotificationSettings(settings)
  }

  application.registerForRemoteNotifications()
  // [END register for remote notifications]
  return true
}

Assign FIRMessaging's delegate property by adding these lines at the end of AppDelegate.swift.

AppDelegate.swift

extension AppDelegate : MessagingDelegate {
  func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    print("Firebase registration token: \(String(describing: fcmToken))")
    
    let dataDict:[String: String] = ["token": fcmToken ?? ""]
    NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
  }
}

Add Capabilities

You added the Push Notifications capability in the Create an App ID section, but you have to also add this capability on XCode by the following steps (the steps below are in XCode 12.3):

  1. Click the project name in the Navigator Area.
  2. Click Signing & Capabilities.
  3. Click + Capability.

eaf41aefb3bf2c9e.png

  1. Double-click Background Modes.
  2. Click + Capability again.
  3. Double-click Push Notifications.
  4. Check Remote notifications in the Background Modes sections.

e5d0fc08651e04a9.png

6. Send a notification message

You can send a test message by the following steps:

  1. Install and run the app on the target device. You'll need to accept the request for permission to receive remote notifications.
  2. Obtain the registration token in the XCode log.

a2e49a92f9807d34.png

  1. Make sure the app is in the background on the device.
  2. Open the Notifications composer and select New notification.
  3. Enter the message text. f485d7fbd2456ae0.png
  4. Select Send test message.
  5. In the field labeled Add an FCM registration token, enter the registration token that you obtained in step 2.
  6. Click Test.

After you click Test, the targeted client device (with the app in the background) should receive the notification in the notification center.

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.

6570eea7b5228513.png

7. Congratulations

Congratulations, you've successfully sent a test message!

There are many more functions and configurations in FCM such as topic subscription.

Check out the official developer document if you're interested in them.

What's next?

Check out some of these codelabs.

Further reading