You are currently viewing How to Send Silent Push Notifications

How to Send Silent Push Notifications

Tested working on iOS 14 device.

A silent push notification or some might call it background notification is a notification that does not trigger any alert or sound. It wakes up your app and allows you to perform any non-UI related operations in the background.

In most cases, silent push notifications are used in background content update. However, some app publishers might use it to remotely activate or deactivate certain app features for A/B testing purposes.

In this article, let’s look into how you can use an API client tool to send a silent push notification to your iOS device for testing purposes.


Prerequisite

The Setup

For this article, I will be using Firebase as the push notification server. If you have not set up your app for push notification, here’s a great guide by Firebase to get you started.

However, I do notice that the guide has missed out on one essential step — you need to add “Background Modes” and “Push Notifications” capabilities in Xcode in order for your app to be able to receive a silent push notification.

Adding "Background Modes" and "Push Notifications" capabilities in Xcode
Adding “Background Modes” and “Push Notifications” capabilities

The Limitations

Before we get started, there are a few limitations that everyone should be aware of:

  1. You can only test push notifications in a real iOS device. iOS simulator will not be able to receive any push notifications.
  2. Silent push notifications will not work when the device is in “Low Data Mode“.
  3. The method that I am going to show you only work on silent push notifications. Meaning you cannot use it to send an interactive push notification (push notification that displays an alert or plays a sound).

With all that in mind, let’s get started.


Sending a Silent Push Notification

In order to send a silent push notification, you must first obtain the Firebase cloud messaging server key and Firebase FCM token.

After that, you can make use of any API client tools out there to make a POST request to Google API, which will then send the notification payload to your testing device.

Let’s go through each step one by one.

#1. Obtain the Firebase Cloud Messaging Server Key

If you have properly set up your app in the Firebase Console, you can easily get the server key from the project settings page.

In the project settings page, go to the “Cloud Messaging” tab, you should be able to see the server key in the “Project credentials” section.

Open project settings page in Firebase Console
Open project settings page
Obtaining Firebase cloud messaging server key
Obtaining server key

Go ahead and copy the server key and paste it somewhere easy to access, we will need it when configuring the API client tool.

#2. Obtain the FCM Token

In the Firebase SDK, there is a delegate method that will be called once the FCM token is available, you can implement this delegate method in AppDelegate.swift and print out the FCM token.

extension AppDelegate: MessagingDelegate {
    
    func messaging(_ messaging: Messaging, 
                   didReceiveRegistrationToken fcmToken: String) {
        print("Received fcmToken: \(fcmToken)")
    }
}

Copy and paste the FCM token to somewhere easy to access, as we will need it very soon.

#3. Configure the API Client Tool

In this section, I will be using Talend API Tester (Google Chrome extension) to make the POST request. Other API client tools such as Postman and Advanced REST Client should do the job as well.

Now, let’s go ahead and create a POST request that target the following URL:

https://fcm.googleapis.com/fcm/send

Next up, you also need to configure the POST request headers.

Content-Type: application/json
Authorization: key=[your_server_key]

For the Authorization header, replace [your_server_key] with the actual server key that you obtained previously. Please note that the key= prefix must be included as part of the Authorization header.

Configure POST request URL and headers
POST request URL and headers

#4. Compile Notification Payload

The notification payload is a JSON formatted string that will be delivered alongside the silent push notification. Here’s a sample of the silent push notification payload.

{
  "to": "[your-fcm-token]",
  "content_available": true,
  "apns-priority": 5,
  "data": {
    "some-key": "some-value"
  }
}

Make sure you replace [your-fcm-token] with the FCM token that you obtained just now. This will help the Firebase server to identify the receiver of the silent push notification.

Do note that the "content_available": true key-value pair is compulsory. It is an identifier to show that this notification is a silent push notification. Without this, your device will not be able to receive the silent push notification.

According to Apple (in WWDC), the apns-priority key is compulsory as well. You must set the apns-priority to 5 or your app will not launch. While doing testing, I do find that my app is still able to launch even though I omitted the apns-priority key. But do note that I have not tested this in the production environment.

The data key in the payload is optional, however, you can use it to include any additional data that you want to deliver alongside the silent push notification.

After finish compiling the payload, go ahead and set it as the POST request body.

Push notification payload as POST request body
POST request body

With this, your POST request is ready and should be able to deliver a silent push notification to your iOS device.

In the next section, we will have a quick look at how to handle the received push notification payload.


Handling Silent Push Notification Payload

When iOS received a push notification, the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) delegate method will be called.

The code snippet below demonstrates how you can extract data from the notification payload.

func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
    // Perform background operation
    
    if let value = userInfo["some-key"] as? String {
       print(value) // output: "some-value"
    }
    
    // Inform the system after the background operation is completed.
    completionHandler(.newData)
}

Notice that you must call the completion handler in order to inform the system after the background operation is completed.

Pro Tip:

I found out that sometimes the app failed to receive the push notifications because application(_:didRegisterForRemoteNotificationsWithDeviceToken:) is not being called during app launch. In this kind of situation, restarting your device should do the trick.


Important Notes

If you plan to use silent push notification in your apps, there are a few points that are very important and I think all developers should know about it.

  1. The application(_:didReceiveRemoteNotification:fetchCompletionHandler:) delegate method will still trigger even though the app is in the foreground.
  2. The silent push notification will wake up a terminated app. As a result, the application(_:didFinishLaunchingWithOptions:) delegate method and the initial view controller’s viewDidLoad() method will be triggered as well.
  3. The background operation triggered by a silent push notification will have roughly 30 seconds of execution time.

Further Readings

If you would like to learn more about simulating push notifications in iOS simulator, you can check out this article.

🔗 Simulating Push Notifications in iOS Simulator


I hope you find this article helpful. Feel free to share your thoughts in the comment section below.

Follow me on Twitter for more articles related to iOS development.

Thanks for reading! 👨🏼‍💻


👋🏻 Hey!

While you’re still here, why not check out some of my favorite Mac tools on Setapp? They will definitely help improve your day-to-day productivity. Additionally, doing so will also help support my work.

  • Bartender: Superpower your menu bar and take full control over your menu bar items.
  • CleanShot X: The best screen capture app I’ve ever used.
  • PixelSnap: Measure on-screen elements with ease and precision.
  • iStat Menus: Track CPU, GPU, sensors, and more, all in one convenient tool.