iOS rich push notifications with media attachments

Dimitri James Tsiflitzis
4 min readOct 23, 2017

--

iOS 10 brings us push notifications that have new functionality compared to the ones in older operating system versions. Improvements include viewing photos, videos or gifs, right there, within the notification.

Having these media attachments as part of your notification is achieved with the use of the new Notification Service Extension. You can also have richer view controller level content within the media attachment view of the notification with the use of the, also new, Notification Content Extension. We’ll go through some code just below.

Getting started

Make sure you have:

  • Xcode 8.0+
  • OS X El Capitan 10.11
  • Import UserNotifications.framework to your project.

Server Side

The apple push notification service sends remote notifications for your apps to each user’s device. A notification and a device token are sent the the APNS servers. In turn, they handle the routing of that notification to the correct user device. At that point, iOS takes over and makes sure the notification is delivered to your app. Push notifications have a maximum payload size of 4KB and they support development & production environments.

In order for you Notification Extension code to be executed the push notifications payload must be modified slightly (compared to iOS 9 for instance).

{
"aps": {
"alert": {
"body": "Push notification body",
"title": "Push notification title"
},
"mutable-content": 1,
category: "rich-apns"
},
"media-url": "https://i.imgur.com/t4WGJQx.jpg"
}

The media-url key contains the url of your media attachment which you’ll be using in your code. The payload also tells iOS which notifications will cause your Notification Extension to run by including the mutable-content with a value of 1. The time you have to execute your code is limited and as far as I can tell it’s several seconds which is an adequate amount of time to download an image.

You can either use your own backend to send the above payload or you can use a tool called Pusher you can find on GitHub. It is a Mac app for sending push notifications directly to the Apple Push Notification Service. All you need your SSL certificate and a device token to start pushing directly from your Mac.

**Update**: You can now easily test your push notifications on your devices with this simple command line tool I wrote. More information here.

Client Side

Create a new target and add it to your project.

In short, to display an image in your push notification you have to

  • Download the image
  • Save the image
  • Add the disk path of the image to a UNNotificationAttachment

Setting up push notifications in your app

Before we get there though there are several things we have to do first. Initially, we have to register to receive push notifications in our app.

let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in  
/* were we authorised or not? */
}
application.registerForRemoteNotifications()

Next, we have to obtain the device token.

func application(_ application: UIApplication,                   didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data) {      
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print(deviceTokenString)
/* send the device token to your server */
}

In case of an error.

func application(_ application: UIApplication,                   didFailToRegisterForRemoteNotificationsWithError error: Error) {          print("i am not available in simulator \(error)")  
}

And in the case you would like to know which permissions have been granted, you can:

UNUserNotificationCenter.current().getNotificationSettings() { (setttings) in              
switch setttings.soundSetting {
case .enabled:
print("enabled sound setting")

case .disabled:
print("setting has been disabled")

case .notSupported:
print("something vital went wrong here")
}
}

All of the above can be in your applications delegate.

In your Notification extension

In the following code, we are locating the value for the key media-url. If it exists, we download the image from the URL which is the key’s value.

The URLSession downloads the media to temporary storage using a FileManager.

In addition, there is also some reachability (ReachabilitySwift pod) work performed here. If the device is on wifi, the image is downloaded. If it’s on cellular, it’s not. Just throwing that in there in case you have a high frequency of notifications sent along with large images 😀

Adding a custom UI to your notification

Create a new target and add it to your project.

In your Notification extension

  • The Notification Content Extension uses a NotificationViewController, which is a subclass of UIViewController.
  • When you created the Content Extension, Xcode created the NotificationViewController.swift file, a MainInterface.storyboard and a plist file.
  • The UNNotificationExtensionCategory key value is the same as the category value set previously in the payload above. This tells iOS that the push notification you’re triggering is handled with a Content Extension.
  • In MainInterface.storyboard, create the UI that your push notifications will display, just like a regular UIViewController.
  • In NotificationViewController.swift, declare any IBOutlets and connect them to the Storyboard file.

--

--

Dimitri James Tsiflitzis

Developer, scrum enthusiast, @sequeapp building productivity apps; formerly @nimber, @peopleperhour, @taxibeat; game dev @sprimp and orgniser @cocoaheadsgr