Show image in UNNotificationServiceExtension 圖片推播實作方法1 -iOS Swift

Peggy Tsai 
彼得潘的 Swift iOS App 開發教室
10 min readAug 1, 2023

--

(UNNotificationServiceExtension, Notification, image)

推播時如果需要帶圖片
可以參考本文

新增Notification Service Extension

到專案設定檔,新增Target

選擇Notification Service Extension,按Next

設定target名稱與資訊

完成新增Notification Service Extension Target

專案會自動掛載Embed Foundation Extension

顯示圖片

在NotificationServiceExtension專案資料夾中,調整NotificationService檔

調整NotificationService檔案如下

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)

if let dictApps = request.content.userInfo["aps"] as? [AnyHashable: Any], let strContent = dictApps["alert"] as? [String: Any], let imagePath = strContent["launch-image"] as? String {
guard let url = URL(string: imagePath) else {
contentHandler(bestAttemptContent)
return
}
guard let imageData = NSData(contentsOf: url) else {
contentHandler(bestAttemptContent)
return
}
guard let attachment = UNNotificationAttachment.create(imageFileIdentifier: "image.jpg", data: imageData, options: nil) else {
print("error in UNNotificationAttachment.create()")
contentHandler(bestAttemptContent)
return
}
bestAttemptContent.attachments = [ attachment ]
}
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 {
static func create(imageFileIdentifier: String, data: NSData, options: [NSObject : AnyObject]?) -> UNNotificationAttachment? {
let fileManager = FileManager.default
let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString
guard let tmpSubFolderURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true) else { return nil }

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
}

}

*只需依照後端格式調整 imagePath即可

let dictApps = request.content.userInfo["aps"] as? [AnyHashable: Any], let strContent = dictApps["alert"] as? [String: Any], let imagePath = strContent["launch-image"] as? String

NotificationService 的 Target Membership只需要勾選NotificationServiceExtension

如果是透過Firebase Cloud Messaging with image- FCM推圖
可以參考下方

import UserNotifications
import FirebaseMessaging

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)

if let bestAttemptContent = bestAttemptContent {
FIRMessagingExtensionHelper().populateNotificationContent(bestAttemptContent, withContentHandler: contentHandler)
}
}
}

實機測試

切至NotificationServiceExtension專案,並選實體手機裝置

選擇執行的app,並按 Run開始測試

手機可以收到推播訊息

長按系統預設會展開圖片

*卡波圖片來源 https://img.rttt.net/2021/08/31/114cd755ecacb.gif

--

--