Skip to content

How To Add Notification Service App Extention in iOS

What is the Notification Service App Extension

Notification service app extension let you customize the content of a remote notification before the system delivers it to the users.

When your app receives a remote notification for your app, the system loads your extension and calls its didReceive(_:withContentHandler:) method given the following coonditions:

  • You have added a notification service app extension to your project.
  • Your app has configured the remote notification to dispaly an alert.
  • The remote notification’s aps dictionary includes the mutable-coontent key with the value set to 1.

How to Add a Notificaion Service App Extension to Your App

A notification service app extension ships as a separate bundle inside your iOS app. To add this extention to your app:

  1. Select File -> New -> Target in Xcode.
  2. Select the Notification Service Extension target from the iOS -> Application Extension section.
  3. Click Next
  4. Specify a name and other configuration details for your app extention.
  5. Click Finish

After that, you can see the template code provided by xcode by default, and you can modify it.

swift
import UserNotifications

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            // Modify the notification content here...
            bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
            
            contentHandler(bestAttemptContent)
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

}

How to Implement Service Extensions’s Handler Methods

You need implement two methods in your extension code.

didReceive(_:withContentHandler:)

You can override this method to modify the UNNotificationContent object that the system delivers with notification.

You can modify any of the content from the original request. For example:

  • You might customize the content for the current user or replace it altogether.
  • You can download images or movies and add them as attachments to the content.
  • You may also modify the alert text as long as you don’t remove it. If the content object doesn’t contain any alert text, the system ignores your modifications and delivers the origianl notification content.

After you have finished the modification, you need call contentHandler block and pass it your modified cotent.

If you decide not to modify the content, call contentHandler block with the origianl content from the request parameter.

Your extension has a limited amount of time (no more than 30 seconds) to modify the content and execute the contentHandler block.

serviceExtensionTimeWillExpire()

If your didReceive(_:withContentHandler: methods takes too long to execute its contentHandler block, the system calls serviceExtensionTimeWillExpire() method on a separate thread to give you one last chance to execute the block.

Use this method to execute the block as quickly as possible. Doing so might mean providing some fallback content.

If you fail to execute the contentHandler from either method in time, the system present the notification’s original content to the user.

Configure the Payload for the Remote Notifcation

The system executes your notification service app extension only when a remote notification’s payload contains the folloing information:

  • The payload must include the mutable-content key with a value of 1.
  • The payload must include an alert dictionary with title, subtile, or body information.

It means you can’t modify silent notifications or those that only play a sound or badge the app’s icon.

For example:

json
{
   "aps" : {
      "mutable-content" : 1,
      "alert" : {
         "title" : "Push Message!",
         "body"  : "This message will be processed through notifcaiton server app extension"
     }
   }
}

Now, you can run NotificationService target on your app, send push notification to test.


Have any questions? Feel free to drop me a message on Twitter!

References