iOS 下APNS推送處理函數詳解
相比起Android,iOS在推送方面無疑慣例得更好。APNS(Apple Push Notification Service)是蘋果公司提供的訊息推送服務。其原理就是,第三方應用將要推送給使用者的資訊推送到蘋果伺服器,蘋果伺服器再通過統一的系統介面將這些資訊推送到使用者的手機上。如果對此不舍瞭解的朋友可以參見這篇文章:一步一步教你做ios 推送
本文著重叫在App端如何處理推送資訊。主要涉及一下幾個比較重要的函數,而這些函數都是AppDelegate類中:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
做過iOS 開發的人對這個函數都會很熟悉,這是在程式結束啟動,並即將運行時調用的,通常一些初始化的工作可以在這個函數中處理。同樣的,推送的相關初始化操作也需要在這個部分完成。這一部分的工作主要分為兩部分:推送類型的註冊:
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationAlert];
這行代碼告訴了系統,該程式註冊的推送訊息類型,通常包括badge、聲音以及alert通知。處理常式沒有啟動時的推送訊息:如果是程式正在運行或者說程式正在後台,那麼這個時候處理推送訊息的工作都是在:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 或者:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
中完成。但是如果使用者點擊推播通知的時候程式還沒有被啟動,這個時候以上兩個函數都是接收不到使用者的推播通知的,這個時候需要在application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*) launchOptions 函數裡面進行處理。而推送訊息的相關資訊就儲存在launchOptions這個字典裡。具體參照如下代碼:
NSDictionary* pushInfo = [launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"]; if (pushInfo) { NSDictionary *apsInfo = [pushInfo objectForKey:@"aps"]; if(apsInfo) { //your code here } }
- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken & - (void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error為了讓device端可以接收到推送訊息,需要將裝置的token傳送到蘋果的伺服器,這個token就相當於裝置的識別碼,每一台蘋果裝置都有唯一的token,蘋果的伺服器就是通過這個token找到對應的裝置,並傳送相應地訊息。這兩個函數就是在傳送token成功或者失敗後調用的,使用者在對應的函數裡面做一些相應地處理。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo和
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
都是程式在運行過程中(無論當前程式處於前台還是後台)接收到推送訊息的處理函數。根據蘋果的官方文檔,建議大家使用
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
因為前者在程式處於背景時候是無法接收到推送資訊的(經實測-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo其實可以接收到,不知道是怎麼回事,希望大蝦解疑)。另外就是-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 還有一個作用。根據蘋果給出的文檔,系統給出30s的時間對推送的訊息進行處理,此後就會運行CompletionHandler程式塊。
在處理這類推送訊息(即程式被啟動後接收到推送訊息)的時候,通常會遇到這樣的問題,就是當前的推送訊息是當前程式正在前台運行時接收到的還是說是程式在後台運行,使用者點擊系統訊息通知欄對應項進入程式時而接收到的?這個其實很簡單,用下面的代碼就可以解決:
void application:(UIApplication*)application didReceiveRemoteNotification:NSDictionary)userInfo fetchCompletionHandler:((^)UIBackgroundFetchResult)completionHandler{if (application.applicationState == UIApplicationStateActive) { NSLog(@"active"); //程式當前正處於前台 } else if(application.applicationState == UIApplicationStateInactive) { NSLog(@"inactive"); //程式處於後台 }}
關於userInfo的結構,參照蘋果的官方結構:
{ |
"aps" : { |
"alert" : "You got your emails.", |
"badge" : 9, |
"sound" : "bingbong.aiff" |
}, |
"acme1" : "bar", |
"acme2" : 42 |
} |
即key aps對應了有一個字典,裡面是該次推送訊息的具體資訊。具體跟我們註冊的推送類型有關。另外剩下的一些key就是使用者自訂的了。