Skip to content

Latest commit

 

History

History
94 lines (69 loc) · 4.21 KB

display-rich-push-notification.md

File metadata and controls

94 lines (69 loc) · 4.21 KB

Display rich push notifications

You must use a Notification Service app extension to download images or other media attachments for the notification before displaying it on user's iOS device.

Follow Apple's documentation to Add a Notification Service app extension to your project.

Notification Service Extension Implementation

Here is an example of how to implement the Notification Service Extension to download the media attachment for the notification from Adobe Journey Optimizer.

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)
        
        // defer this block to be executed to call the callback
        defer {
            contentHandler(bestAttemptContent ?? request.content)
        }
        
        guard let attachment = request.adobeAttachment else { return }
        bestAttemptContent?.attachments = [attachment]
        
    }
    
    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)
        }
    }

}


extension UNNotificationRequest {
    var adobeAttachment: UNNotificationAttachment? {
        // return nil if the notification does not contain a valid value for adb_media key
        guard let attachmentString = content.userInfo["adb_media"] as? String else {
            return nil
        }
        
        // do not attach anything if it is not a valid URL
        guard let attachmentURL = URL(string: attachmentString) else {
            return nil
        }
        
        // do not attach anything if the url does not contain downloadable data
        guard let attachmentData = try? Data(contentsOf: attachmentURL) else {
            return nil
        }
        
        return try? UNNotificationAttachment(data: attachmentData, options: nil, attachmentURL: attachmentURL)
    }
}

extension UNNotificationAttachment {

    /// Convenience initializer to create a UNNotificationAttachment from a URL
    /// - Parameters:
    ///  - data: the data to be displayed in the notification
    ///  - options : options for the attachment
    ///  - attachmentURL : the URL of the rich media to be displayed in the notification
    convenience init(data: Data, options: [NSObject: AnyObject]?, attachmentURL: URL) throws {
        let fileManager = FileManager.default
        let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString,
                                                                                                     isDirectory: true)
        try fileManager.createDirectory(at: temporaryFolderURL, withIntermediateDirectories: true, attributes: nil)
        var attachmentType : String
        
        // determine the attachment type from the url
        // common format are png, jpg, gif, mp3,  mpeg4, avi, mp4
        // Reference Apple documentation for supported file types and maximum size : https://developer.apple.com/documentation/usernotifications/unnotificationattachment
        /// NOTE : Please edit the below code according to the type of rich media notification that your app needs to support
        attachmentType = ".jpg"
        
        let attachmentName = UUID().uuidString + attachmentType
        let fileURL = temporaryFolderURL.appendingPathComponent(attachmentName)
        try data.write(to: fileURL)
        try self.init(identifier: attachmentName, url: fileURL, options: options)
    }
    
}