標籤:
我的個人項目《丁丁印記》中加入了遠程推送功能,按照操作說明去做還是比較容易實現的,但是學的不夠不系統,因此這篇文章希望總結一下最新的iOS推送功能,因為iOS8之後的推送和致之前的版本是有所不同的,也希望想能協助到需要的朋友。這篇文章將從零開始,向大家介紹遠程推送功能的原理和使用。
什麼是遠程推播通知
顧名思義,就是從遠程伺服器推送給用戶端的通知(需要連網)遠程推送服務,又稱為APNs(Apple Push Notification Services)。
為什麼程式中需要遠程推送功能
1.傳統擷取資料的局限性 只要使用者關閉了app,就無法跟app的伺服器溝通,無法從伺服器上獲得最新的資料內容
2.遠程推播通知可以解決以上問題 不管使用者開啟還是關閉app,只要連網了,都能接收到伺服器推送的遠程通知
遠程推送的注意點
1.所有的蘋果裝置,在連網狀態下,都會與蘋果的伺服器建立長串連 什麼是長串連 只要連網了,就一直建立串連
2.長串連的作用。比如:時間校準、系統升級、尋找我的iPhone
3.長串連的好處 資料轉送速度快 資料保持最新狀態
iOS的推送機制
圖中的各個部分的說明如下:
1.Provider:手機應用發出推送訊息的伺服器。
2.APNS:APNS(Apple Push Notification Service)則是蘋果訊息推送伺服器
3.Client App:我們開發的應用。
你本地的伺服器當需要給應用推送一條訊息的時候,先要將訊息發出到蘋果推送伺服器,然後再由蘋果推送伺服器將訊息發到安裝了該應用的手機。
用下面這張圖更能清晰的說明推送的機制:
根據的邏輯我來給大家解釋一下:
1.你的IOS應用需要去註冊APNS訊息推送功能。
2.當蘋果APNS推送服收到來自你應用的註冊訊息就會返回一串device token給你(很重要)
3.將應用收到的device Token傳給你本地的Push伺服器。
4.當你需要為應用推送訊息的時候,你本地的推送伺服器會將訊息,以及Device Token打包發送到蘋果的APNS服
5.APNS再將訊息推送給目的iphone然後推送給App
遠程推送的具體實現:
我們公司的伺服器,經過蘋果的APNs伺服器找到我們的裝置,給我們裝置上的用戶端應用推送訊息。那APNs伺服器是如何找到我們的裝置和裝置上的應用呢,答案就是DeviceToken,DeviceToken需要配置推送認證才可以獲得,推送認證需要知道我們的APP ID(應用的BundleID,應用唯一標識)和UDID(裝置唯一標識),還有自己伺服器的UDID,我們先來打一個推送認證,登入開發人員中心,點擊認證模組:
點擊iOS Apps的認證(certificates )
進入這樣的介面
點擊App IDs,然後點右上方的加號
箭頭所指為應用ID描述,我們假設寫了一個很牛逼的應用,ExcitedApp,接下來我們填入App ID,注意這裡的App ID是固定的,不能有星號
接下來我們添加App所需要的服務,然後點擊Continue
一直點擊下一步,完成,在App IDs 列表裡面找到我們的ExcitedApp,我們看到
發現Push服務是黃色警告,這時點擊Edit,找到推送模組,我們需要配置推送認證了,點擊紅色箭頭所指的位置
我們需要一個CSR檔案,CSR是一個簽章要求檔案,意思就是讓我們的MAC具有調試推送的許可權,點擊繼續
點擊了繼續我們看到
然後我們開啟Mac上的鑰匙串,從憑證授權單位請求認證
前兩個隨便寫,最後選擇存到磁碟
完成之後,接下來我們就可以添加CSR檔案了
添加完,選擇產生
認證配好了,下載下來
配好了!
順帶著我們把發布的認證也給配了,步驟都一樣
開啟我們剛剛下載的認證,添加到鑰匙串中
終於能開始整我們的項目了,快哭了都
不要忘記修改bundle id 這裡還要搞一個真機調試的認證才可以
真機調試的東西這裡不累述,搞了這麼多東西,我們終於可以拿到DeviceToken了
在AppDelegate.m中註冊推送
#import "AppDelegate.h" @implementation AppDelegate @synthesize mainView = _mainView; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
//由於ios8的推送跟ios7及以下的不一樣,所以需要加判斷來註冊訊息推送。
//IOS8 //建立UIUserNotificationSettings,並設定訊息的顯示類類型 UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil]; [application registerUserNotificationSettings:notiSettings]; } else{ // ios7 [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)]; } self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; self.mainView = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil]; self.window.rootViewController = self.mainView; return YES; } - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{ NSLog(@"---Token--%@", pToken); } //會接收來自蘋果伺服器給你返回的deviceToken,然後你需要將它添加到你本地的推送伺服器上。(很重要,決定你的裝置能不能接收到推送訊息)。- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ NSLog(@"userInfo == %@",userInfo); NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil nil]; [alert show]; } //這個函數則是當裝置接收到來自蘋果推送伺服器的訊息時觸發的,用來顯示推送訊息。- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{ NSLog(@"Regist fail%@",error); } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end
將我們的推送認證添加到項目目錄
接下來我們用PushMebaby來測試一下我們的推送。PushMebaby:https://github.com/stefanhafeneger/PushMeBaby/
如果您的操作正確,那恭喜你,接下來手機上就可以收到推送了。
如果沒有收到,很遺憾的通知您,請好好檢查是否各個環節配置正確。
iOS開發中的遠程推送實現(最新,支援iOS9)