[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 = .default
        content.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) in
            print(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 模板:

{
"aps":
    {
        "alert":
        {
            "title":"iOS10遠程推送標(biāo)題",
            "subtitle" : "iOS10 遠程推送副標(biāo)題",
            "body":"這是在iOS10以上版本的推送內(nèi)容次舌,并且攜帶來一個圖片附件"
        },

        "badge":1,
        "mutable-content":1,
        "sound":"default",
        "image":"http://pic29.nipic.com/20130511/9252150_174018365301_2.jpg"
    }
}


添加 Service Extension 服務(wù)

首先,添加一個擴展服務(wù)Target
選擇:導(dǎo)航欄 File -> New -> Target

在彈出的頁面中選擇Notification Service Extension兽愤,下一步彼念,起一個名稱挪圾,完成即可!可以看到逐沙,項目中多了一個Target哲思,以及幾個相關(guān)的文件:

我需要在生成的NotificationService文件里處理我們發(fā)送的通知,添加相應(yīng)的附件吩案,可以看到NotificationService是繼承自UNNotificationContentExtension的棚赔,并重寫了他的兩個方法,定義了兩個屬性:

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 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è)置的標(biāo)題后面多了個[modified],這是因為修改了標(biāo)題崎岂±粒可見,通知調(diào)用了這個方法冲甘,但是绩卤,當(dāng)我們在這個文件內(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)建UNNotificationAttachment
                            if 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)圖片灾票!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末峡谊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子刊苍,更是在濱河造成了極大的恐慌靖苇,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件班缰,死亡現(xiàn)場離奇詭異,居然都是意外死亡悼枢,警方通過查閱死者的電腦和手機埠忘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馒索,“玉大人莹妒,你說我怎么就攤上這事〈律希” “怎么了旨怠?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蜈块。 經(jīng)常有香客問我鉴腻,道長迷扇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任爽哎,我火速辦了婚禮蜓席,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘课锌。我一直安慰自己厨内,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布渺贤。 她就那樣靜靜地躺著雏胃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪志鞍。 梳的紋絲不亂的頭發(fā)上瞭亮,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機與錄音述雾,去河邊找鬼街州。 笑死,一個胖子當(dāng)著我的面吹牛玻孟,可吹牛的內(nèi)容都是我干的唆缴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼黍翎,長吁一口氣:“原來是場噩夢啊……” “哼面徽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起匣掸,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤趟紊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碰酝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霎匈,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年送爸,在試婚紗的時候發(fā)現(xiàn)自己被綠了铛嘱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡袭厂,死狀恐怖墨吓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纹磺,我是刑警寧澤帖烘,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站橄杨,受9級特大地震影響秘症,放射性物質(zhì)發(fā)生泄漏照卦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一历极、第九天 我趴在偏房一處隱蔽的房頂上張望窄瘟。 院中可真熱鬧,春花似錦趟卸、人聲如沸蹄葱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽图云。三九已至,卻和暖如春邻邮,著一層夾襖步出監(jiān)牢的瞬間竣况,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工筒严, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丹泉,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓鸭蛙,卻偏偏與公主長得像摹恨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子娶视,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理晒哄,服務(wù)發(fā)現(xiàn),斷路器肪获,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 介紹一下iOS10的通知新功能寝凌,用戶體驗的提升和開發(fā)者能夠發(fā)揮的地方非常多,使得iOS更具有競爭力孝赫。 1.iOS ...
    F麥子閱讀 3,818評論 3 4
  • 2017年12月30日 星期六 陰天有雨 今天是十分充實的一天较木。上午我去“艾美顏”做完養(yǎng)生保健后...
    羅木禾閱讀 213評論 0 0
  • 我最喜歡的季節(jié)是春季,最害怕的季節(jié)也是春季青柄。 喜歡它的原因是春風(fēng)是暖的劫映,這是一種被人關(guān)懷的感覺,害怕它...
    話梅小姐閱讀 413評論 0 0
  • 陪孩子游學(xué)西安刹前,原本20年前就頗具感情的一個地方,好吃的釀皮雌桑,神秘的古城墻喇喉,高深莫測的兵馬俑,閉眼就隱約...
    天天開心_cf6b閱讀 169評論 0 0