I'm trying to display rich notifications on my app with an expanded image like this. I have used Notification Service extension to implement this in the app.
But I'm only getting a thumbnail when I receive a notification, which looks something like this. The expanded image appears when when I long press on a 3D-touch capable phone, otherwise it just displays a thumbnail on phones which doesn't have 3D-touch.
I wasn't able to find any documentation or any questions on SO which explains how to do this if it is possible. I would like to know if it is possible to do this on iOS, if not is there any possible workaround to accomplish this? Here is my NotificationSerivce
extension. Any help is much appreciated! Thanks!
class NotificationService: UNNotificationServiceExtension {
let fileManager = FileManager()
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...
guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
return self.contentHandler = contentHandler
}
bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
guard let attachmentURL = content.userInfo["attachment-url"] as? String else {
return self.contentHandler = contentHandler
}
guard let fileName = attachmentURL.components(separatedBy: "/").last else {
return self.contentHandler = contentHandler
}
guard let imageData = try? Data(contentsOf: URL(string: attachmentURL)!) else {
return self.contentHandler = contentHandler
}
if let thumbnailAttachment = UNNotificationAttachment.create(imageFileIdentifier: fileName, data: imageData, options: nil) {
bestAttemptContent.attachments = [thumbnailAttachment]
}
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)
}
}
}
extension UNNotificationAttachment {
/// Save the image to disk
static func create(imageFileIdentifier: String, data: Data, options: [AnyHashable: Any]?) -> UNNotificationAttachment? {
let fileManager = FileManager.default
let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
let tmpSubFolderURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true)
do {
try fileManager.createDirectory(at: tmpSubFolderURL!, withIntermediateDirectories: true, attributes: nil)
let fileURL = tmpSubFolderURL?.appendingPathComponent(imageFileIdentifier)
try data.write(to: fileURL!, options: [])
let imageAttachment = try UNNotificationAttachment(identifier: imageFileIdentifier, url: fileURL!, options: options)
return imageAttachment
} catch let error {
print("error \(error)")
}
return nil
}
}