User Notifications
前言
為什么是[通知]而不是[推送]
先來看一下iOS10通知相關(guān)的第一個更新點就是新加了一個框架User Notification Framework,從字面翻譯來看應(yīng)該翻譯成“用戶通知框架”狐粱,而通常大家所了解的“推送”翻譯成英文應(yīng)該是“Push”,“Push”其實只是[通知]觸發(fā)的一種方式沈贝,而[通知]其實是操作系統(tǒng)層面的一種UI展示履腋。
在蘋果的官方文檔中Notification分為兩類:
Remote(遠程薇缅,也就是之前所說的Push的方式)
Local(本地,通知由本地的事件觸發(fā)评也,iOS10中有三種不同的觸發(fā)‘Trigger’方式,稍后會進行詳細說明)
所以灭返,[推送]只是[通知]的一種觸發(fā)方式盗迟,而從iOS迭代更新的歷史特征中看,[通知]應(yīng)該是是被蘋果作為一個重點內(nèi)容來延展的熙含。(從最初的單純展示和簡單回調(diào)罚缕,到Backgroud的支持,再后來整體的Payload的長度由256字節(jié)擴展到2K再到4K怎静,再看這次的獨立框架還有豐富的特性更新)
更新點(概覽)
由User Notification Framework 整合通知相關(guān)方法看特性變化
通知相關(guān)的方法由之前一直存在在UIKit Framework中到獨立出來邮弹,官方確實做了很多黔衡,但是也盡量做到讓開發(fā)者可以平滑的過度。
原文:
1.Familiar API with feature parity
2.Expanded content
3.Same code path for local and remote notification handling
4.Simplified delegate methods
5.Better notification management
6.In-app presentation option
7.Schedule and handle notifications in extensions
8.Notification Extensions
釋義:
1.相同的特性使用類似的API(之前的功能API使用方法類似但是還是稍有改變)
2.內(nèi)容擴展(支持附件和展示更多內(nèi)容)
3.本地通知和遠程通知操作代碼在相同調(diào)用路徑(合并代理方法)
4.簡化代理方法
5.更好的通知管理(支持通知查腌乡、改盟劫、刪;增強本地通知管理与纽,增加日歷與地理位置事件的觸發(fā))
6.應(yīng)用內(nèi)通知展示(之前App在前臺的情況下收到通知不會UI展示)
7.在Extensions中規(guī)劃和操作通知(使更新通知內(nèi)容和刪除誤發(fā)或過期的通知內(nèi)容成為可能侣签,另一個重要場景為端到端加密)
8.引入通知Extensions
從產(chǎn)品&運營的角度來看更新點
增加Subtitle
Subtitle樣式和展示位置如下圖所示,Subtitle的加入給內(nèi)容類App帶來了福音急迂,交給優(yōu)秀編輯和策劃去使用應(yīng)該是一項利器影所。
增加Attachments
通過類似之前的content_available參數(shù)的mutable-content參數(shù)來控制是否增加Attachments,需要開發(fā)者實現(xiàn)NotificationServiceExtension來展示帶有Attachments的通知僚碎,需要注意的一點是猴娩,本地通知的話只能使用本地的資源,遠程通知需要服務(wù)端發(fā)送URL給NotificationServiceExtension去預先執(zhí)行下載操作勺阐,當然如果在網(wǎng)絡(luò)不太通暢的情況下蘋果也提供了超時時間和超時之后的后續(xù)操作讓開發(fā)者在這種情況下也能適當?shù)恼故就ㄖ湍纾瑥亩岣咄ㄖ换ンw驗。
Attachments的加入也可以讓你更好的對發(fā)給用戶的通知進行分類皆看。
新增本地通知Triggers
在本地通知新增了兩種新的Triggers仓坞,就是日歷和地理位置。日歷的話就是讓開發(fā)者可以根據(jù)指定的日期和時間來展示本地通知腰吟,并且支持循環(huán)條件无埃,比如“每周二上午十一點”這種條件。地理位置的話就是在進入或者離開指定區(qū)域來觸發(fā)這條本地通知毛雇,該特性讓iOS通知的地理圍欄觸發(fā)有了實現(xiàn)的可能嫉称,比如“某品牌App在你進入該品牌線下店鋪的范圍內(nèi)即展示最新優(yōu)惠信息”等。
典型場景:
循環(huán)提醒
地理圍欄
內(nèi)容擴展顯示
如果設(shè)備支持3DTouch的話用力按壓通知即可進入內(nèi)容擴展頁面灵疮,此頁面會可以由開發(fā)者自定義展示內(nèi)容织阅,可以是之前Attachments的內(nèi)容比如圖片視頻,也可以是開發(fā)者自己定義的布局內(nèi)容震捣,同時也支持在內(nèi)容擴展頁面增加更多的自定義ActionButton荔棉。但是,個人認為有一些遺憾的是擴展內(nèi)容幾乎不支持交互蒿赢,交互就只能放到ActionButton里面了润樱。
通知查、改羡棵、刪
實現(xiàn)該功能需要有一個必要參數(shù)就是構(gòu)建通知的identifer壹若,后續(xù)的查改刪操作都是根據(jù)此參數(shù)去執(zhí)行的。
典型的應(yīng)用場景:
賽事比分變更
通知撤回
增加Service Extension
讓App開發(fā)者可以在展示通知之前增加一層處理邏輯,從而使端到端加密成為可能店展,也就意味著經(jīng)由蘋果的服務(wù)器的通知內(nèi)容可以是完全的密文养篓,在這之前iOS上實現(xiàn)通知內(nèi)容加密是沒有任何可能的。
典型應(yīng)用場景:
端到端加密
添加Attachments
獲取通知相關(guān)設(shè)置信息API
可以通過API獲取到用戶設(shè)置該App相關(guān)于推送通知的設(shè)置的詳細列表赂蕴,該信息的統(tǒng)計可以讓App的開發(fā)者更好的根據(jù)用戶的通知使用習慣來改進通知的策略觉至。
增加應(yīng)用內(nèi)通知展示API
提供官方的應(yīng)用內(nèi)收到APNs通知并做UI展示的API,在此之前如果想做此類功能需要開發(fā)者自己開發(fā)功能睡腿,此API的優(yōu)勢在于讓開發(fā)者更簡單的實現(xiàn)應(yīng)用內(nèi)展示通知的功能并且統(tǒng)一點擊通知之后的事件语御。
從開發(fā)的角度來看更新點
UserNotifications framework詳解
首先介紹UserNotification的幾個主要類
[1]UNNotification主要是作為通知delegate方法的參數(shù)使用。包含UNNotificationRequest信息席怪。
[2]UNNotificationAction是通知中添加的action应闯,展示在通知欄的下方。默認以的button樣式展示挂捻。有一個文本輸入的子類UNTextInputNotificationAction碉纺。可以在點擊button之后彈出一個鍵盤刻撒,輸入信息骨田。用戶點擊信息和輸入的信息可以在UNNotificationResponse中獲取。
[3]UNNotificationAttachment是新增的通知內(nèi)容格式声怔,可以設(shè)置圖像和視頻态贤。
[4]UNNotificationCategory是通知樣式類型。在注冊通知之后醋火,展示通知之前悠汽,可以自定義通知樣式,并使用[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSetsetWithObject:categoryNotification]]設(shè)置到通知中心中芥驳。根據(jù)通知內(nèi)容中的categoryIdentifier使用不同的通知樣式柿冲。這里需要注意:使用自定義的通知操作按鈕和通知Content可以設(shè)置為同一個category。
[5]UNNotificationContent通知的主體內(nèi)容兆旬,原通知的title假抄,sound,badge和新的attachments丽猬,lacnchImageName都在這里進行設(shè)置宿饱,是創(chuàng)建一個通知的前提。
[6]UNNotificationRequest通知請求。當通知內(nèi)容,觸發(fā)條件都準備好之后格遭,需要包裝為一個通知請求傍妒,由通知中心來激活這個通知。
[7]UNNotificationResponse通知響應(yīng)。作為通知的action被用戶觸發(fā)之后沥寥,App可以拿到的信息碍舍。和action對應(yīng),有普通的UNNotificationResponse和子類UNTextInputNotificationResponse邑雅。其中包括action的identifier和完整的UNNotification片橡。子類UNTextInputNotificationResponse還包含userText,用戶輸入的內(nèi)容淮野。
[8]UNNotificationServiceExtension是一個extension捧书。用戶可以在收到特性的通知時,一般是遠程骤星,并且該遠程通知的apns中包含一個mutable-content字段经瓷,值為1。
你有30秒的時間處理這個通知洞难,可以同步下載圖像和視頻到本地舆吮,然后包裝為一個UNNotificationAttachment扔給通知,這樣就能展示用服務(wù)器獲取的圖像或者視頻了队贱。這里需要注意:如果數(shù)據(jù)處理失敗色冀,超時,extension會報一個崩潰信息柱嫌,但是通知會用默認的形式展示出來锋恬,app不會崩潰。
[9]UNNotificationSetting schedule notifications that involve user interactions such as displaying alerts, playing sounds, or badging the app’s icon.编丘。
[10]UNNotificationSound通知的聲音伶氢。可以直接使用聲音的name瘪吏,而不是文件路徑癣防。
[11]UNNotificationTrigger通知的觸發(fā)條件。
UNTimeIntervalNotificationTrigger
UNCalendarNotificationTrigger
UNLocationNotificationTrigger
[12]UNUserNotificationCenter通知中心掌眠。最主要的類蕾盯,通知的注冊,激活蓝丙,編輯级遭,刪除等功能都由該類完成。
Content
以前只能展示一條文字渺尘,現(xiàn)在可以有 title 挫鸽、subtitle 以及 body 了。
定制方法如下:
//Local NotificationUNMutableNotificationContent*content=[[UNMutableNotificationContent alloc]init];
content.title=@"Introduction to Notifications";
content.subtitle=@"Session 707";content.body=@"Woah! These new notifications look amazing! Don’t you agree?";
content.badge=@1;
//Remote Notification
{"aps":
? ? {"alert":{
? ? ? ? ? ? ? ? ? ? "title":"Introduction to Notifications",
? ? ? ? ? ? ? ? ? ? "subtitle":"Session 707",
? ? ? ? ? ? ? ? ? ? ?"body":"Woah! These new notifications look amazing! Don’t you agree?"},
? ? ? "badge":1},
}
新增本地通知Triggers
又是一個新的功能鸥跟,有三種
UNTimeIntervalNotificationTrigger
UNCalendarNotificationTrigger
UNLocationNotificationTrigger
//2 分鐘后提醒
UNTimeIntervalNotificationTrigger*trigger1=[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:120repeats:NO];
//每小時重復 1 次喊我喝水
UNTimeIntervalNotificationTrigger*trigger2=[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:3600repeats:YES];
//每周二早上 10:00 提醒我閃電購粉絲節(jié)抽獎
NSDateComponents*components=[[NSDateComponents alloc]init];components.weekday=2;
components.hour=8;
UNCalendarNotificationTrigger*trigger3=[UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];
//#import //一到公司就提醒我買閃電購
CLRegion*region=[[CLRegion alloc]init];UNLocationNotificationTrigger*trigger4=[UNLocationNotificationTrigger triggerWithRegion:region repeats:NO];
發(fā)送通知
NSString*requestIdentifier=@"sampleRequest";
UNNotificationRequest*request=[UNNotificationRequest requestWithIdentifier:requestIdentifier? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? content:content ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? trigger:trigger1];
[center addNotificationRequest:request withCompletionHandler:^(NSError*_Nullable error){}];
Notification Handling
設(shè)定了推送丢郊,然后就結(jié)束了盔沫?iOS 10 并沒有這么簡單! 通過實現(xiàn)協(xié)議枫匾,使 App 處于前臺時捕捉并處理即將觸發(fā)的推送:
@interfaceAppDelegate()<UNUserNotificationCenterDelegate>
-(void)userNotificationCenter:(UNUserNotificationCenter*)center willPresentNotification:(UNNotification*)notification withCompletionHandler:(void(^)(UNNotificationPresentationOptions))completionHandler{
completionHandler(UNNotificationPresentationOptionAlert|UNNotificationPresentationOptionSound);
}
讓它只顯示 alert 和 sound ,而忽略 badge 架诞。
Notification Management
徹底掌控整個推送周期:
Local Notification 通過更新 request
Remote Notification 通過新的字段 apns-collapse-id
通過之前的addNotificationRequest:方法,在 id 不變的情況下重新添加干茉,就可以刷新原有的推送谴忧。
NSString*requestIdentifier=@"sampleRequest";
UNNotificationRequest*request=[UNNotificationRequest requestWithIdentifier:requestIdentifier? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? content:newContent? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? trigger:newTrigger1];
[center addNotificationRequest:request withCompletionHandler:^(NSError*_Nullable error){
}];
刪除計劃的推送:
[center removePendingNotificationRequestsWithIdentifiers:@[requestIdentifier]];
此外 UNUserNotificationCenter.h 中還有諸如刪除所有推送、查看已經(jīng)發(fā)出的推送角虫、刪除已經(jīng)發(fā)出的推送等等強大的接口沾谓。
service extension詳細資料
從這張圖上,我們可以看到戳鹅,原先直接從APNs推送到用戶手機的消息均驶,中間添加了ServiceExtension處理的一個步驟(當然你也可以不處理),通過這個ServiceExtension粉楚,我們可以把即將給用戶展示的通知內(nèi)容辣恋,做各種自定義的處理,最終模软,給用戶呈現(xiàn)一個更為豐富的通知伟骨,當然,如果網(wǎng)絡(luò)不好燃异,或者附件過大携狭,可能在給定的時間內(nèi),我們沒能將通知重新編輯回俐,那么逛腿,則會顯示發(fā)過來的原版通知內(nèi)容。
那么ServiceExtension可以做什么呢仅颇?它的意義是什么呢单默?我總結(jié)了幾點:
1、 安全 安全總是擺在第一位的忘瓦,從iOS9開始搁廓,蘋果鼓勵我們使用更為安全的https協(xié)議可以看的出來,蘋果公司是對安全很重視的一家公司耕皮,為什么在這里我會提到安全呢境蜕?是因為之前我們的推送內(nèi)容,不管是通過第三方凌停,還是通過蘋果自帶的通知處理粱年,如果讓有心人對數(shù)據(jù)做一次攔截,抓個包啥的罚拟,我們推送的內(nèi)容就會完全暴露台诗,當然有的同學說完箩,我可以加密啊~但是不知道大家有沒有想過,如果數(shù)據(jù)加密拉庶,那通知欄會怎么展示呢嗜憔?(你千萬別跟我說你把所有的遠程推送變成本地通知秃励。氏仗。)通過此次這次增加的UNNotificationServiceExtension的類,便可以更好的幫助我們實現(xiàn)數(shù)據(jù)的加密夺鲜。 它的原理便是在收到通知后的最多30s內(nèi)皆尔,你可以把你的通知內(nèi)容,解密后币励,在重新展示在用戶的通知攔上慷蠕。
2、 內(nèi)容的豐富 之前的通知展示內(nèi)容比較少食呻,以至于被各種廣告提醒占據(jù)了流炕。這次蘋果新添加的附件通知,結(jié)合上通知拓展類仅胞,便可以給用戶展現(xiàn)出一個有著豐富內(nèi)容的通知每辟。比如,一個小短片的某一秒的畫面案删伞(這里要強烈鄙視各大平臺的某些電影預覽圖)渠欺,又或者是配上一些小圖片啊(通過服務(wù)器傳來的imaUrl)等方式來吸引用戶椎眯,誘導用戶點開你的通知挠将,促使用戶會使用你的App。其實推送這個功能编整,雖然有的人會關(guān)閉舔稀,但是大部分的人還是開啟的,所以說推送這個市場還是很大的喲~靈活利用推送掌测,會讓你的程序擁有無限的可能内贮。
添加 Service Extension
先在 Xcode 打開你的 App 工程,F(xiàn)ile - New - Target 然后添加notificationService
然后會自動創(chuàng)建一個 UNNotificationServiceExtension 的子類 NotificationService赏半,通過完善這個子類贺归,來實現(xiàn)你的需求。
點開 NotificationService.m 會看到 2 個方法:
-(void)didReceiveNotificationRequest:(UNNotificationRequest*)request withContentHandler:(void(^)(UNNotificationContent*_Nonnull))contentHandler{
self.contentHandler=contentHandler;self.bestAttemptContent=[request.content mutableCopy];
self.bestAttemptContent.title=[NSString stringWithFormat:@"%@ [modified]",self.bestAttemptContent.title];
self.contentHandler(self.bestAttemptContent);
}
-(void)serviceExtensionTimeWillExpire{
self.contentHandler(self.bestAttemptContent);
}
didReceiveNotificationRequest 讓你可以在后臺處理接收到的推送断箫,傳遞最終的內(nèi)容給 contentHandler
serviceExtensionTimeWillExpire 在你獲得的一小段運行代碼的時間即將結(jié)束的時候拂酣,如果仍然沒有成功的傳入內(nèi)容,會走到這個方法仲义,可以在這里傳肯定不會出錯的內(nèi)容婶熬,或者他會默認傳遞原始的推送內(nèi)容
獲取通知相關(guān)設(shè)置信息API
之前注冊推送服務(wù)剑勾,用戶點擊了同意還是不同意,以及用戶之后又做了怎樣的更改我們都無從得知赵颅,現(xiàn)在 apple 開放了這個 API虽另,我們可以直接獲取到用戶的設(shè)定信息了。
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings*_Nonnull settings){NSLog(@"%@",settings);}];
打印獲得如下信息:
<UNNotificationSettings: 0x16567310;
authorizationStatus: Authorized,
notificationCenterSetting: Enabled,
soundSetting: Enabled,
badgeSetting: Enabled,
lockScreenSetting: Enabled,
alertSetting: NotSupported,
carPlaySetting: Enabled,
alertStyle: Banner>
服務(wù)器payload 格式
加入title 和 subtitle
{
"aps":{
"alert":{
"title":"I am title",
"subtitle":"I am subtitle",
"body":"I am body"
},
"sound":"default",
"badge":1
}
}
可被serviceExtension攔截的格式 需要有 mutable-content 字段
{
"aps": {
"alert": "This is some fancy message.",
"badge": 1,
"sound": "default",
"mutable-content": "1",
"imageAbsoluteString": "http://upload.univs.cn/2012/0104/1325645511371.jpg"
}
}