? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?iOS推送
????????在IOS推送服務(wù)中也搓,Apple提供了兩種不同方式的推送形式,一種是在通知欄上面顯示的推送涵紊;另一種則是不帶消息提醒的推送傍妒,俗稱“靜默消息”。
1. 普通推送和靜默推送的區(qū)別
????????普通推送:收到推送后(有文字有聲音)摸柄,點開通知颤练,進(jìn)入APP后,才執(zhí)行
- (void)application:(UIApplication didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void result))handler *)application *)userInfo (^)(UIBackgroundFetchResult
????????靜默推送:(Silent Push)并不是必須要“靜默”(通常是沒有文字沒有聲音)驱负,只要推送payload中aps字典里包含了"content-available": 1的鍵值對嗦玖,都具有靜默推送的特性,不用點開通知跃脊,不用打開APP宇挫,就能執(zhí)行
-(void)application:(UIApplication )application)userInfo didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void (^)(UIBackgroundFetchResultresult))handler
用戶完全感覺不到所以靜默推送又被我們稱做 Background Remote Notification(后臺遠(yuǎn)程推送)。
????????靜默推送是在iOS7之后推出的一種推送方式酪术。它與其他推送的區(qū)別在于允許應(yīng)用收到通知后在后臺(background)狀態(tài)下運行一段代碼器瘪,可用于從服務(wù)器獲取內(nèi)容更新翠储。
PS:注冊消息通知時通常的彈窗詢問權(quán)限有什么用呢?其實只是請求用戶允許在推送通知到來時能夠有alert, badge和sound橡疼,而并不是在請求注冊推送本身的權(quán)限援所。靜默推送即使用戶不允許應(yīng)用的推送,靜默推送依然會送達(dá)用戶設(shè)備欣除,只是不會有alert, badge和sound住拭。這也符合靜默推送的正常使用場景。
2. 遠(yuǎn)程推送時 , 應(yīng)用的幾種狀態(tài)及對應(yīng)回調(diào)方法
? ? ?(1) . 應(yīng)用開啟時 , 應(yīng)用在前臺
??? ?(2) . 應(yīng)用開啟時 , 應(yīng)用在后臺
?? ? (3) . 應(yīng)用未啟動(應(yīng)用被殺死)
從蘋果APNS服務(wù)器遠(yuǎn)程推送時:
不使用<UserNotifications/UserNotifications.h>時(iOS10以后可用)
1 . 如果應(yīng)用處于 (1) 狀態(tài) , 則不會發(fā)出聲音 , 會直接調(diào)用appDelegate的代理方法didReceiveRemoteNotification(didReceiveRemoteNotification:fetchCompletionHandler:)
2 . 如果應(yīng)用處于 (2) 狀態(tài) , 則會發(fā)出提示音, 點擊推送消息 , 則會調(diào)用appDelegate的代理方法didReceiveRemoteNotification
3 . 如果應(yīng)用處于 (3) 狀態(tài),則會發(fā)出提示音 , 點擊推送消息 , 則會開啟應(yīng)用 , 在下面這個方法中會帶上launchOptions這個參數(shù),如果實現(xiàn)了application:didReceiveRemoteNotification:fetchCompletionHandler:這個方法,則還會調(diào)用這個方法
注:didReceiveRemoteNotification指以下兩個方法历帚。兩個方法互斥滔岳。在兩方法都實現(xiàn)的情況下方法2優(yōu)先級高
1. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
2. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
iOS10使用<UserNotifications/UserNotifications.h>時
1 . 如果應(yīng)用處于 (1) 狀態(tài) , 會發(fā)出聲音 , 會直接調(diào)用appDelegate的代理方法userNotificationCenter:willPresentNotification:withCompletionHandler
2 . 如果應(yīng)用處于 (2) 狀態(tài) , 則會發(fā)出提示音, 點擊推送消息 , 則會調(diào)用appDelegate的代理方法
userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler
3 . 如果應(yīng)用處于 (3) 狀態(tài),則會發(fā)出提示音 , 點擊推送消息 , 則會開啟應(yīng)用 , 在下面這個方法中會帶上launchOptions這個參數(shù),如果實現(xiàn)了userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler這個方法,則還會調(diào)用這個方法
2. 靜默推送及app的狀態(tài)切換
????????在大多數(shù)情況下,啟動一個app后都是進(jìn)入前臺抹缕,比如我們點擊應(yīng)用圖標(biāo)或點推送通知來啟動應(yīng)用澈蟆。其實app在某些后臺事件和特定條件下是可以直接啟動到后臺(launch into the background)的。
? ??2.1 應(yīng)用狀態(tài)之一Suspended
????????這種狀態(tài)其實和Background類似卓研,而且從用戶角度講應(yīng)用現(xiàn)在看起來確實是在“后臺”趴俘,但它和Background狀態(tài)不同的是Suspended下已經(jīng)不能執(zhí)行代碼了。應(yīng)用何時會進(jìn)Suspended就是玄學(xué)了奏赘,這是由iOS系統(tǒng)自動控制的寥闪,而且不會有任何回調(diào),可以看到UIApplicationDelegate里并沒有像applicationWillBecomeSuspended:這種東西磨淌。這種狀態(tài)下的應(yīng)用雖然還在內(nèi)存中疲憋,但是一旦設(shè)備內(nèi)存吃盡,比如開了爐石傳說的游戲梁只,那么系統(tǒng)就會優(yōu)先干掉(文檔上用的是purge這個詞)處于Suspended狀態(tài)的應(yīng)用缚柳,而且也不會有回調(diào)。
????2.2 應(yīng)用啟動到前臺的生命周期(以點擊應(yīng)用圖標(biāo)開始)
????AppDelegate中走的回調(diào)方法?
????????· application:willFinishLaunchingWithOptions:
????????· application:didFinishLaunchingWithOptions:
????????· applicationDidBecomeActive:
? ??靜默推送可以使應(yīng)用啟動到后臺
????????前提是應(yīng)用先被退到后臺搪锣,過一段時間被系統(tǒng)移入Suspended狀態(tài)秋忙,然后又被系統(tǒng)在內(nèi)存吃緊時回收了內(nèi)存(相當(dāng)于應(yīng)用已經(jīng)被系統(tǒng)正當(dāng)殺掉,而非用戶雙擊Home鍵殺掉)构舟,在這以后灰追,該應(yīng)用收到靜默推送即會啟動應(yīng)用到后臺。
????AppDelegate中走的回調(diào)方法變?yōu)?/p>
????????· application:willFinishLaunchingWithOptions:
????????· application:didFinishLaunchingWithOptions:
????????· applicationDidEnterBackground:
????????這個過程中狗超,系統(tǒng)不會顯示應(yīng)用的window弹澎,就是說我們不會看到手機(jī)屏幕上突然鬼畜一下應(yīng)用啟動,但是應(yīng)用的第一屏?xí)患虞d和渲染努咐,比如你的window.rootViewController是一個TabBarController苦蒿,那么它及其默認(rèn)選中的selectedViewController都會被加載和渲染。這是因為系統(tǒng)認(rèn)為在后臺執(zhí)行完任務(wù)后可能會有UI上的更新渗稍,所以在applicationDidEnterBackground:方法執(zhí)行結(jié)束后便會有個快速的截圖刽肠,來更新用戶雙擊Home時看到的那個應(yīng)用截圖溃肪。
3. 收到靜默推送時的后續(xù)該如何處理免胃。
? ??????application:didReceiveRemoteNotification:fetchCompletionHandler:
????????這是應(yīng)用收到靜默推送的回調(diào)方法音五,我們最多有30s的時間來處理數(shù)據(jù),比如靜默推送表示某個列表或資源有更新羔沙,你可以在此處下載數(shù)據(jù)躺涝,在下載處理完數(shù)據(jù)后需要盡快調(diào)用completionHandler(...)告訴系統(tǒng)處理完畢。
-?(void)application:(UIApplication?*)application?didReceiveRemoteNotification:(NSDictionary?*)userInfo?fetchCompletionHandler:(void?(^)(UIBackgroundFetchResult))completionHandler?{
????[Downloader?fetchData:^(id?x){????????//?處理數(shù)據(jù)扼雏,更新UI?等
????????completionHandler(UIBackgroundFetchResultNewData);
????}];
}
????????如果這次是啟動到后臺的情況坚嗜,調(diào)用completionHandler(...)后會使應(yīng)用馬上進(jìn)入之前的狀態(tài)。那就有可能遇到這樣的問題:很多時候我們需要在啟動時發(fā)送一堆業(yè)務(wù)上的API請求诗充,如果這次靜默推送沒有數(shù)據(jù)需要下載和處理苍蔬,就會剛把啟動處的API請求發(fā)出,就調(diào)用了completionHandler(...)蝴蜓,導(dǎo)致發(fā)出的這些請求在下次打開應(yīng)用時顯示超時碟绑。這種情況下我們可以強行延時下completionHandler(...)的調(diào)用,來保證能在這次收到那些API的返回茎匠。
???dispatch_after(dispatch_time(DISPATCH_TIME_NOW,?(int64_t)(5?*?NSEC_PER_SEC)),?dispatch_get_main_queue(),?^{
????????completionHandler(UIBackgroundFetchResultNoData);
????});
4. 靜默推送
應(yīng)用想收到靜默推送需要滿足的條件:
1.應(yīng)用在前臺/后臺 (應(yīng)用被殺死就收不到了)
2.應(yīng)用實現(xiàn)了
application:didReceiveRemoteNotification:fetchCompletionHandler:/application:didReceiveRemoteNotification:
3. 消息定義時需設(shè)置:"content-available" = 1
流程:
? 1. 移動端注冊消息格仲,向APNs服務(wù)器獲取deviceToken,并提交給后臺保存诵冒;
? 2. 后臺定義消息凯肋,并推送給APNs服務(wù)器。APNs根據(jù)deviceToken做分發(fā)汽馋。
? 3. 移動端收到推送消息后的邏輯處理侮东。
消息定義示例:
特殊說明:
1. APNS去掉alert、badge豹芯、sound字段實現(xiàn)靜默推送悄雅,增加增加字段"content-available":1,也可以在后臺做一些事情告组。
//靜默推送消息格式
{
"aps":{
"alert":"",
"content-available":1
},
"userInfo":"test"
}
*/
小結(jié):
1.應(yīng)用在后臺/前臺/被殺死,都可以收到普通的遠(yuǎn)程推送
2.應(yīng)用在后臺/前臺時,可以通過靜默推送,修改一些數(shù)據(jù)
3.應(yīng)用被殺死時(相當(dāng)于應(yīng)用已經(jīng)被系統(tǒng)正當(dāng)殺掉煤伟,而非用戶雙擊Home鍵殺掉),可以通過Background Fetch短時間喚醒應(yīng)用
參考資料:
http://www.cocoachina.com/articles/23672
http://www.reibang.com/p/f326987c737e
https://www.jb51.net/article/145654.htm
https://blog.csdn.net/ws_752958369/article/details/79732961