[iOS] 通知详解: iOS 10 UserNotifications -- 附加包Media Attachments
通知相關(guān)系列文章
iOS10 之前通知使用介紹
[iOS] 通知詳解: UIUserNotification
iOS10 相關(guān)API
[iOS] 通知詳解:iOS 10 UserNotifications API
iOS10 本地/遠程通知
[iOS] 通知詳解: iOS 10 UserNotifications
iOS10 通知附加包
[iOS] 通知詳解: iOS 10 UserNotifications – 附加包Media Attachments
iOS10 自定義UI
[iOS] 通知詳解: iOS 10 UserNotifications – 自定義通知UI
無論是遠程通知還是本地通知,都可以添加附加包,自己根據(jù)文件URL來創(chuàng)建UNNotificationAttachment實例,然后添加到相應(yīng)的通知請求的UNMutableNotificationContent實例中。區(qū)別是獲取附件的方式,一般本地通知的附件是放在本地的Bundle中的,只需要在創(chuàng)建本地通知的時候,根據(jù)附件的URL創(chuàng)建相應(yīng)的UNNotificationAttachment即可;遠程通知,需要根據(jù)遠程的通知攜帶的URL地址,去初始化UNNotificationAttachment,接著就會通過Service Extensions服務(wù)來下載這些附件數(shù)據(jù),在通知中進行顯示。
本地通知添加附加包
上面說了,本地通知的附加包數(shù)據(jù)是放在本地的,直接根據(jù)其文件的URL地址創(chuàng)建即可,下面給出一個示例:
// 創(chuàng)建通知內(nèi)容let content = UNMutableNotificationContent()content.title = "ios 10 local push test"content.subtitle = "local push subtitle"content.body = "這是一個iOS 10 之后的本地通知測試文本,這里顯示的是消息的詳細內(nèi)容,另外這是一個添加的附件圖片的通知"content.sound = .defaultcontent.userInfo = ["info": "這里的信息是傳遞給app的payload內(nèi)容"]// 加載本地的一張圖片作為附件if let url = Bundle.main.url(forResource: "111", withExtension: "png") {if let attch = try? UNNotificationAttachment(identifier: "identifierAttachment", url: url, options: nil) {content.attachments = [attch]}}// 創(chuàng)建觸發(fā)方式,10s后觸發(fā)let timer = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)// 創(chuàng)建通知請求let req = UNNotificationRequest(identifier: "reqid", content: content, trigger: timer)// 添加請求到通知中心UNUserNotificationCenter.current().add(req) { (error) inprint(error)print("prepare for local push")}通知執(zhí)行后,在鎖屏狀態(tài)通知中心顯示為:
彈框的顯示效果
彈框下拉后會顯示一個大圖
也可以加載一段音樂,例如加載一首歌,只需要把上面的加載附件的部分代碼修改為:
// 加載本地的一張圖片作為附件if let url = Bundle.main.url(forResource: "music", withExtension: "mp3") {if let attch = try? UNNotificationAttachment(identifier: "identifierAttachment", url: url, options: nil) {content.attachments = [attch]}}彈框下拉后如下圖效果:
可以看到,這里可以直接播放,視頻的加載方式類似,只要不超過大小限制即可!
遠程通知攜帶附加包
遠程通知的附件數(shù)據(jù)是存放在服務(wù)端的,所以我們發(fā)送的Payload需要添加mutable-content字段,并設(shè)置其值為1 ,告訴系統(tǒng)此通知是可變的,然后再通過Service Extensions服務(wù)來下載對應(yīng)的數(shù)據(jù)創(chuàng)建attachments,添加到相應(yīng)的通知里面,顯示在通知里。
Payload 模板:
添加 Service Extension 服務(wù)
首先,添加一個擴展服務(wù)Target
選擇:導(dǎo)航欄 File -> New -> Target
在彈出的頁面中選擇Notification Service Extension,下一步,起一個名稱,完成即可!可以看到,項目中多了一個Target,以及幾個相關(guān)的文件:
我需要在生成的NotificationService文件里處理我們發(fā)送的通知,添加相應(yīng)的附件,可以看到NotificationService是繼承自UNNotificationContentExtension的,并重寫了他的兩個方法,定義了兩個屬性:
import UserNotificationsclass NotificationService: UNNotificationServiceExtension {var contentHandler: ((UNNotificationContent) -> Void)?var bestAttemptContent: UNMutableNotificationContent?override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {self.contentHandler = contentHandlerbestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)if let bestAttemptContent = bestAttemptContent {// Modify the notification content here...bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"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)}}如果我們什么都不更改,使用上面的Payload模版發(fā)送一個遠程通知試試,會發(fā)現(xiàn)我們設(shè)置的標題后面多了個**[modified]**,這是因為修改了標題。可見,通知調(diào)用了這個方法,但是,當我們在這個文件內(nèi)添加打印log的print,或者斷點,log信息并沒有輸出,斷點也沒有停,雖然這個方法確實是被系統(tǒng)調(diào)用了,這給我們的調(diào)試帶來了一些不方便。
我們主要是在didReceive方法里添加相應(yīng)的處理:下載附件的數(shù)據(jù),保存到本地,然后根據(jù)本地的文件URL創(chuàng)建UNNotificationAttachment實例對象,添加到通知里,并回調(diào)給系統(tǒng)。
以攜帶一張圖為例:
if let bestAttemptContent = bestAttemptContent {// Modify the notification content here...bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"print(bestAttemptContent.userInfo)// 1. 獲取payload內(nèi)容// 此處的 userInfo 即我們發(fā)送的Payload內(nèi)容if let aps = bestAttemptContent.userInfo["aps"] as? [String: Any] {// 2. 獲取到payload內(nèi)的圖片地址if let imagePath = aps["image"] as? String {// bestAttemptContent.body = "\(bestAttemptContent.body) +imagePath \(imagePath)"if let url = URL(string: imagePath) {// bestAttemptContent.body = "\(bestAttemptContent.body) +url \(url)"// 3. 根據(jù)URL地址獲取圖片數(shù)據(jù)if let data = try? Data.init(contentsOf: url) {let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first// 4. 創(chuàng)建本地文件地址,最好在payload中添加一個文件名稱,或者文件格式,在這里使用文件原名稱/格式進行存儲;這里直接寫死let fileUrl = URL.init(fileURLWithPath: path! + "/image.jpg")// bestAttemptContent.body = "\(bestAttemptContent.body) +file \(fileUrl)"// 5. 保存圖片數(shù)據(jù)到本地try? data.write(to: fileUrl)// 6. 根據(jù)本地URL地址創(chuàng)建UNNotificationAttachmentif let att = try? UNNotificationAttachment(identifier: "imageattac", url: fileUrl, options: nil) {bestAttemptContent.attachments = [att]}} /* if let data = end*/} /* if let url = end*/}/* if ler imagePath = end*/}/* if let aps = end*/// 7. 回調(diào)contentHandler(bestAttemptContent)}實例代碼中的1.–7.是相關(guān)需要操作的步驟,還有注釋掉的bestAttemptContent.body = 部分代碼,因為無法打印log,為了能看到相關(guān)的信息,我就把這些信息添加到body里面,然后顯示在通知里了。
這時,再去發(fā)送一個通知:
在鎖屏頁面,或者彈框,是這樣的
點擊查看,或者下拉彈框,會顯示大圖
如果是其他的文件,例如視頻、音頻文件,都可以按此步驟來操作,下載的方式可以使用自己項目中使用的網(wǎng)絡(luò)框架進行。需要注意的是,此處下載的時間只有30s,所以附件一定要控制大小,如果在此時間內(nèi)沒有下載完成,或者下載失敗,將會以原通知的內(nèi)容進行推送,不含有附件。
PS: 這里需要注意,使用到這個功能的時候,一定要有訪問網(wǎng)絡(luò)的權(quán)限,也就是要在彈出那個網(wǎng)絡(luò)權(quán)限的選擇框之后。我在寫demo的時候,因為沒有用到網(wǎng)絡(luò),在此之前沒有申請網(wǎng)絡(luò)的授權(quán)訪問,所以一直沒有出現(xiàn)圖片!
總結(jié)
以上是生活随笔為你收集整理的[iOS] 通知详解: iOS 10 UserNotifications -- 附加包Media Attachments的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库系统-数据库设计
- 下一篇: 图论及其应用:第二次作业