iOS Rich Media Notifications

iOS 10 introduces the ability to send push notifications with images, gifs, and video. To enable this functionality, clients must create a Service Extension, a new type of extension that enables modification of a push payload before it is displayed.

Creating a service extension

To create a Notification Service Extension, navigate to File > New > Target and select Notification Service Extension.


Ensure that Embed In Application is set to embed the extension in your application.

Setting up the Service Extension 

A Notification Service Extension is its own binary that is bundled with your app. As such, it must be set up in the Apple Developer Portal with its own App ID and Provisioning Profile. Extensions are generally named with a suffix on the main application’s ID (e.g., com.xtremepush.test.testwatchnotificationservice). Details of supported file types and sizes for rich media in Apple's Docs here:

Finally be sure that notifications are enabled for you service extension. In Targets > Capabilities select your service extension and make sure Push Notifications are on.


Some examples of adding rich media below.


Adding a Picture 

This is the most common rich Media use case and as such has a dedicated media button on the iOS push content page for uploading a picture. iOS supports JPG, GIF and PNG formats up to 10 MB in size.


 If you want to add a picture via API you can use the "push_picture"  param in campaign methods. Details in API docs  here:


Simple example of a broadcast iOS push with a picture hosted on your CMS or elsewhere being loaded and sent via API below:

curl -X POST -d '{ "apptoken":"YOURAPPTOKEN", 
"text":"Just Testing My Service Extension", "ios": {"active":1}, 
"send_type":0, "broadcast":1}' 


To display the picture on the app side you will need to handle it in your service extension, below you will see some sample screenshots and code for a service extension that handles a picture on the client side:

La-caffetteria-02.png        La-caffetteria-01.png

//  NotificationService.m
//  notification
//  Copyright © 2017 xtremepush. All rights reserved.

#import "NotificationService.h"

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;


@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    NSDictionary *userInfo = request.content.userInfo;
    if (userInfo == nil || userInfo[@"picture"] == nil) {
    NSURL *pictureURL = [NSURL URLWithString:userInfo[@"picture"]];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    [[session downloadTaskWithURL:pictureURL
                completionHandler:^(NSURL *temporaryFileLocation, NSURLResponse *response, NSError *error) {
                    if (error != nil) {
                    NSFileManager *fileManager = [NSFileManager defaultManager];
                    NSURL *attachmentURL = [NSURL fileURLWithPath:[temporaryFileLocation.path stringByAppendingString:[response.URL.absoluteString lastPathComponent]]];
                    [fileManager moveItemAtURL:temporaryFileLocation toURL:attachmentURL error:&error];
                    NSError *attachError = nil;
                    UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:attachmentURL options:nil error:&attachError];
                    if (attachment == nil) {
                    NSArray *attachments = [NSArray arrayWithObjects:attachment, nil];
                    self.bestAttemptContent.attachments = attachments;
                }] resume];

- (void)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.



Have more questions? Submit a request


Article is closed for comments.