Now you are a few steps ahead of being able to send images, videos, and GIFS in your iOS app notifications! Enabling this functionality is quite straight forward, Let's take a look! 

Technically speaking, rich media in iOS means you can attach media to your notifications and embed custom action buttons (content extensions). 

In the tutorial below, we will cover the two functionalities, attaching media and providing custom buttons through content extensions. 

We will be able to do this in 3 easy steps. First, we will create the notification service extension, second, we will allow non-secure attachments then finally we are going to send some key/value pair in the payload.

1. Creating Notification Service Extension

The UNNotificationServiceExtension class provides the entry point for a Notification Service app extension, which lets you customize the content of a remote notification before it is delivered to the user. A Notification Service app extension does not present any UI of its own. MORE!

Add a new Notification Service Extension target by going to. File > New > Target

NOTE : 

The notification extension has its own Bundle Id (ex: com.pushbots.demo.notificationService) as well as its own Apple App ID and Provisioning profile which must be setup in Apple Developer Portal separately

2. Handle media attached:

All the code needed in your Xcode project to display rich notifications in your application.
You will find notificaiton service class in notification group in xcode.
just copy the lines below to  didReceiveRequestWithContentHandler    in NotificationService class .

Objective C :

self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
NSString *attachmentUrlString = [request.content.userInfo objectForKey:@"attachment-url"];
if (![attachmentUrlString isKindOfClass:[NSString class]])
return;

NSURL *url = [NSURL URLWithString:attachmentUrlString];

if (!url)
return;


[[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

if (!error) {
NSString *tempDict = NSTemporaryDirectory();
NSString *attachmentID = [[[NSUUID UUID] UUIDString] stringByAppendingString:[response.URL.absoluteString lastPathComponent]];

if(response.suggestedFilename)
attachmentID = [[[NSUUID UUID] UUIDString] stringByAppendingString:response.suggestedFilename];

NSString *tempFilePath = [tempDict stringByAppendingPathComponent:attachmentID];

if ([[NSFileManager defaultManager] moveItemAtPath:location.path toPath:tempFilePath error:&error]) {
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:attachmentID URL:[NSURL fileURLWithPath:tempFilePath] options:nil error:&error];
if (!attachment) {
NSLog(@"Create attachment error: %@", error);
} else {
_bestAttemptContent.attachments = [_bestAttemptContent.attachments arrayByAddingObject:attachment];
}

} else {
NSLog(@"Move file error: %@", error);
}
} else {
NSLog(@"Download file error: %@", error);
}

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.contentHandler(self.bestAttemptContent);
}];

}] resume];

Swift :

self.contentHandler = contentHandler

bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

       

//        (request.content.userInfo["aps"] as! NSDictionary)["mutable-content"]!

// Get the custom data from the notification payload

// Grab the attachment

if let urlString = request.content.userInfo["attachment-url"], let fileUrl = URL(string: urlString as! String) {

// Download the attachment

URLSession.shared.downloadTask(with: fileUrl) { (location, response, error) in

if let location = location {

// Move temporary file to remove .tmp extension

let tmpDirectory = NSTemporaryDirectory()

let tmpFile = "file://".appending(tmpDirectory).appending(fileUrl.lastPathComponent)

let tmpUrl = URL(string: tmpFile)!

try! FileManager.default.moveItem(at: location, to: tmpUrl)

                       

// Add the attachment to the notification content

if let attachment = try? UNNotificationAttachment(identifier: "", url: tmpUrl) {

self.bestAttemptContent?.attachments = [attachment]

}

}

// Serve the notification content

self.contentHandler!(self.bestAttemptContent!)

}.resume()

}

The URLSession downloads the media and makes sure it is ready to be attached to the notification content, and successfully served to the user.

2. Allowing non-secure attachment URL's

 Notification Service Extension is a separate binary and has its own Info.plist file.
You have to add App Transport Security Settings with Allow Arbitrary Loads flag set to YES to extension's Info.plist file.

Or via XML :

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

3. APNs Payload :

All you need to do is just to add a mutable-content tag to your payload and set it to true.this will inform Service Extension to intercept this notification

Then you need to add the media attachment URL to the payload in its own . Make sure the key  ("attachment-url") you’ve used in your Service Extension is the same as the key here.

Here's an example of adding video to the notifications using PushBots API:

{
  "platform": [
    0
  ],
  "msg":"Check our new video 🦋🦋",
  "payload": {
    "mutableContent": true,
    "attachment-url": "https://www.w3schools.com/html/mov_bbb.mp4"
  }
}

If you are using the our dashboard and push composer, all you need to do is to fill in the rich media URL, we will do the rest 

How do I add custom actions to my push notifications in iOS 10?

In your AppDelegate file, add this new function and call it in
didFinishLaunchingWithOptions :

Objective C :

- (void)setNotificationsCategories {

    UNNotificationAction *readAction = [UNNotificationAction actionWithIdentifier:@"ReadNow"

                                                                              title:@"Read Now 📰 " options:UNNotificationActionOptionNone];

    UNNotificationAction *laterAction = [UNNotificationAction actionWithIdentifier:@"Later"

                                                                              title:@"Later" options:UNNotificationActionOptionDestructive];

   

    UNNotificationCategory *newsCategory = [UNNotificationCategory categoryWithIdentifier:@"News"

                                                                              actions:@[readAction,laterAction] intentIdentifiers:@[]

                                                                              options:UNNotificationCategoryOptionNone];

   

    UNNotificationAction *shopAction = [UNNotificationAction actionWithIdentifier:@"ShopNow"

                                                                            title:@"Shop Now 🛍️" options:UNNotificationActionOptionNone];

    UNNotificationAction *dismissAction = [UNNotificationAction actionWithIdentifier:@"Dismiss"

                                                                             title:@"Dismiss" options:UNNotificationActionOptionDestructive];

   

    UNNotificationCategory *shopCategory = [UNNotificationCategory categoryWithIdentifier:@"Shopping"

                                                                              actions:@[shopAction,dismissAction] intentIdentifiers:@[]

                                                                              options:UNNotificationCategoryOptionNone];

    NSSet *categories = [NSSet setWithObjects:newsCategory,shopCategory, nil];

    [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories];

   
 }

Swift : 

 func setNotificationsCategories() {

        if #available(iOS 10.0, *) {

        let readNow = UNNotificationAction(

            identifier: "ReadNow",

            title: "Read Now 📰 "

        )

        let later = UNNotificationAction(

            identifier: "Later",

            title: "Later",

            options: [.destructive]

        )

        let newscategory = UNNotificationCategory(

            identifier: "News",

            actions: [readNow, later],

            intentIdentifiers: []

        )

       

        let shop = UNNotificationAction(

            identifier: "Shop",

            title: "Go Shopping 🛍️"

        )

        let dismiss = UNNotificationAction(

            identifier: "dismiss",

            title: "Dismiss",

            options: [.destructive]

        )

        let categoryz = UNNotificationCategory(

            identifier: "Shopping",

            actions: [shop, dismiss],

            intentIdentifiers: []

        )        UNUserNotificationCenter.current().setNotificationCategories([newscategory,categoryz])

        UNUserNotificationCenter.current().delegate = self

        }else{

   
        }

    }

Respond to actions 

If you want to respond to actionable notifications or receive notifications while your app is in the foreground you need to implement the UNUserNotificationCenterDelegate. This protocol defines two optional methods:

  • userNotificationCenter(_:willPresent:withCompletionHandler:) is called when a notification is delivered to a foreground app. You receive the UNNotification object which contains the original UNNotificationRequest. You call the completion handler with the UNNotificationPresentationOptions you want to present (use .none to ignore the alert).
  • userNotificationCenter(_:didReceive:withCompletionHandler:) is called when a user selects an action in a delivered notification. You receive the UNNotificationResponse object which includes the actionIdentifier for the user action and the UNNotification object. The system defined identifiers UNNotificationDefaultActionIdentifierand UNNotificationDismissActionIdentifier are used when the user taps the notification to open the app or swipes to dismiss the notification.

Add UNUserNotificationCenterDelegate to your appdelegate then implement methods :

Objective c :

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {

   

    if ([identifier isEqualToString:NotificationActionOneIdent]) {

       

        NSLog(@"You chose action 1.");

    }

    else if ([identifier isEqualToString:NotificationActionTwoIdent]) {

       

        NSLog(@"You chose action 2.");

    }

    if (completionHandler) {

       

        completionHandler();

    }

}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center

       willPresentNotification:(UNNotification *)notification

         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler

{

    completionHandler(UNNotificationPresentationOptionAlert);

    NSLog( @"Handle push from foreground" );

    // custom code to handle push while app is in the foreground

    NSLog(@"%@", notification.request.content.userInfo);

}

Swift :

  func userNotificationCenter(_ center: UNUserNotificationCenter,

                                willPresent notification: UNNotification,

                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

        // Play sound and show alert to the user

        completionHandler([.alert,.sound])

    }


    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter,

                                didReceive response: UNNotificationResponse,

                                withCompletionHandler completionHandler: @escaping () -> Void) {


        // Determine the user action

        switch response.actionIdentifier {

        case UNNotificationDismissActionIdentifier:

            print("Dismiss Action")

        case UNNotificationDefaultActionIdentifier:

            print("Default")

        case "Shop":

            print("Shop !!")

        case "ReadNow":

            print("Read Now")

        default:

            print("Unknown action")

        }

        completionHandler()

    }

Feel free to download the full source code examples here.

Did this answer your question?