一、推送通知的基本原理:
蘋果的推送服務通知是由自己專門的推送服務器APNs (Apple Push Notification service)來完成的,其過程是 APNs 接收到我們自己的應用服務器發出的被推送的消息,將這條消息推送到指定的 iOS 的設備上,然后再由 iOS設備通知到我們的應用程序,我們將會以通知或者聲音的形式收到推送回來的消息。 iOS 遠程推送的前提是,裝有我們應用程序的 iOS 設備,需要向 APNs 服務器注冊,注冊成功后,APNs 服務器將會給我們返回一個 devicetoken,我們獲取到這個 token 后會將這個 token 發送給我們自己的應用服務器。當我們需要推送消息時,我們的應用服務器將消息按照指定的格式進行打包,然后結合 iOS 設備的 devicetoken 一起發給 APNs 服務器。我們的應用會和 APNs 服務器維持一個基于 TCP 的長連接,APNs 服務器將新消息推送到iOS 設備上,然后在設備屏幕上顯示出推送的消息。
設備注冊APNs的流程圖:
上圖完成了如下步驟:
1.Device(設備)連接APNs服務器并攜帶設備序列號(UUID)
2.連接成功,APNs經過打包和處理產生devicetoken并返回給注冊的Device(設備)
3.Device(設備)攜帶獲取的devicetoken發送到我們自己的應用服務器
4.完成需要被推送的Device(設備)在APNs服務器和我們自己的應用服務器的注冊
推送過程圖:
1.首先,我們的設備安裝了具有推送功能的應用(應用程序要用代碼注冊消息推動),我們的 iOS設備在有網絡的情況下會連接APNs推送服務器,連接過程中,APNS 服務器會驗證devicetoken,連接成功后維持一個基于TCP 的長連接;
2.Provider(我們自己的應用服務器)收到需要被推送的消息并結合被推送的 iOS設備的devicetoken一起打包發送給APNS服務器;
3.APNS服務器將推送信息推送給指定devicetoken的iOS設備;
4.iOS設備收到推送消息后通知我們的應用程序并顯示和提示用戶(聲音、彈出框)
信息包結構圖:
上圖顯示的這個消息體就是我們的應用服務器(Provider)發送給APNs服務器的消息結構,APNs驗證這個結構正確并提取其中的信息后,再將消息推送到指定的iOS設備。這個結構體包括五個部分,第一個部分是命令標示符,第二個部分是我們的devicetoken的長度,第三部分是我們的devicetoken字符串,第四部分是推送消 息體(Payload)的長度,最后一部分也就是真正的消息內容了,里面包含了推送消息的基本信息,比如消息內容,應用Icon右上角顯示多少數字以及推送消息到達時所播放的聲音等
Payload(消息體)的結構:
{?
?“aps”:{?
?“alert”:“send message”,?
?“badge”:1,
?“sound”:“default” }
}
這其實就是個JSON結構體,alert標簽的內容就是會顯示在用戶手機上的推送信息,badge顯示的數量(注意是整型)是會在應用Icon右上角顯示的數量,提示有多少條未讀消息等,sound就是當推送信息送達是手機播放的聲音,傳defalut就標明使用系統默認聲音。
二、配置證書
1.登錄Apple的Developer Member Center、
打開Safari瀏覽器,地址欄輸入并打開此網址:https://developer.apple.com/membercenter/index.action,然后用開發者賬號登錄.
選擇點擊Certificates, Identifiers & Profiles., 打開后在左側列表中選擇Certificates大類下面的All子類,出現如下界面:
2.選擇證書的類型,Sandbox或者Productuon
根據你的需求選擇Apple Push Notification service SSL (Sandbox) 或者 Apple Push Notification service SSL (Sandbox & Production)類型的證書.
然后點擊繼續.
這里要注意一點,選擇證書的正確類型非常重要:
一個用Development Provisioning Profile簽名的App生成的 Device Token只能和Sandbox APNS Server結合使用(開發環境測試用).
一個用AdHoc Provisioning Profile或者AppStore Provisioning Profile簽名的App生成的Device Token只能和Production APNS Server結合使用(生產環境發布使用).
提示:
有些用戶已經報告過關于使用二合一的推送證書(Apple Push Notification service SSL (Sandbox & Production),新出的 )在調試測試環境進行推送時會出問題.
3.選擇你對應的App ID
前提你要先已經創建了你App使用的App ID,并在App ID下拉選項中選擇你對應的App ID.
點擊繼續按鈕繼續.
4.查看創建證書簽名請求相關步驟信息
查看一下如何創建一個CSR文件的信息.
點擊繼續.
該頁面有關于如何一步一步創建CSR文件的詳細信息,下面我們就跟著一步一步來創建CSR文件.
5.打開鑰匙串訪問程序
打開Launchpad中的其他組的Keychain Access App,就是鑰匙串訪問程序.
6.創建證書簽名請求文件
點擊鑰匙串訪問程序的菜單欄
選擇證書助理子菜單
選擇從證書頒發機構請求證書...子子菜單
7.填寫證書簽名請求文件詳細信息
輸入email地址,為了安全和保險起見,最好填寫和你Apple開發者賬號對應的email地址.
接著輸入常用名稱.
最好選擇存儲到磁盤選項.
最后點擊繼續.
8.保存證書簽名請求文件到磁盤
選擇一個存儲位置以及輸入一個你喜歡的文件名稱
點擊保存
9.完成證書簽名請求文件制作
點擊完成
10.上傳正確簽名請求文件
繼續回到第四步后的瀏覽器界面
選擇 Choose File...來上傳
在彈出的文件打開對話框中定位到剛剛存儲的證書簽名請求文件所在目錄,并選擇打開該CSR文件.
點擊繼續
11.下載證書文件
上一步繼續之后,你的證書應該就已經生成好了.
點擊下載按鈕來下載證書.
打開下載的證書文件,一般會自動用鑰匙串訪問程序打開的.
三、代碼配置
打開AppDelegate.m 文件,在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中添加下面代碼,注冊消息推送
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
? ? // Override point for customization after application launch.
????if (IOSVersion >= 10.0) {
? ? ? ????? UNUserNotificationCenter *center = [UNUserNotificationCenter ????currentNotificationCenter];
? ? ? ? // 必須寫代理,不然無法監聽通知的接收與點擊
? ? ? ? center.delegate=self;
? ? ? ? [centerrequestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
? ? ? ? ? ? if(granted) {
? ? ? ? ? ? ? ? // 點擊允許
? ? ? ? ? ? ? ? NSLog(@"注冊成功");
? ? ? ? ? ? ? ? [centergetNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
? ? ? ? ? ? ? ? ? ? NSLog(@"%@", settings);
? ? ? ? ? ? ? ? }];
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? // 點擊不允許
? ? ? ? ? ? ? ? NSLog(@"注冊失敗");
? ? ? ? ? ? }
? ? ? ? }];
? ? }else{
? ? ? ???[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
? ? }
? ? [[UIApplication sharedApplication] registerForRemoteNotifications];
}
#pragma mark Push methodsIniOS9
- (void)application:(UIApplication*)application didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings
{
? ? [application registerForRemoteNotifications];
}
/** APP已經接收到“遠程”通知(推送) - 透傳推送消息? */
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void(^)(UIBackgroundFetchResultresult))completionHandler {
? ? NSLog(@"\n>>>[Receive RemoteNotification - Background Fetch]:%@\n\n",userInfo);
? ? completionHandler(UIBackgroundFetchResultNewData);
}
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userinfo
{
NSLog(@"userInfo == %@",userInfo);
}
#pragma mark Push methodsIniOS10
- (void)userNotificationCenter:(UNUserNotificationCenter*)center willPresentNotification:(UNNotification*)notification withCompletionHandler:(void(^)(UNNotificationPresentationOptionsoptions))completionHandler{
? ? completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);
}
//App通知的點擊事件
- (void)userNotificationCenter:(UNUserNotificationCenter*)center didReceiveNotificationResponse:(UNNotificationResponse*)response withCompletionHandler:(void(^)(void))completionHandler{
? ? //收到推送的請求
? ? UNNotificationRequest*request = response.notification.request;
? ? //收到推送的內容
? ? UNNotificationContent*content = request.content;
? ? //收到用戶的基本信息
? ? NSDictionary*userInfo = content.userInfo;
? ? completionHandler();// 系統要求執行這個方法
}
下面方法是返回 ANPs 蘋果推送服務器生成的唯一標識
/** 接收服務器傳回的設備唯一標識 token */
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
? ? NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
? ?? // 第一次運行獲取到DeviceToken時間會比較長!
? ? // 將deviceToken轉換成字符串,以便后續使用
? ? NSString *token = [deviceToken description];
? ? NSLog(@"description %@", token);
}
/** 注冊推送服務失敗 */
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@"注冊失敗 %@",error);
}
四、測試
測試推送鏈路是否通暢的工具有很多,大家自行選擇,比如個推等等。。。需要注意的是推送是有丟失率的,不是100%每推必達!!!