一兵琳、推送通知的基本原理:
蘋果的推送服務(wù)通知是由自己專門的推送服務(wù)器APNs (Apple Push Notification service)來完成的运翼,其過程是 APNs 接收到我們自己的應(yīng)用服務(wù)器發(fā)出的被推送的消息滔岳,將這條消息推送到指定的 iOS 的設(shè)備上,然后再由 iOS設(shè)備通知到我們的應(yīng)用程序,我們將會以通知或者聲音的形式收到推送回來的消息。 iOS 遠(yuǎn)程推送的前提是归苍,裝有我們應(yīng)用程序的 iOS 設(shè)備用狱,需要向 APNs 服務(wù)器注冊,注冊成功后拼弃,APNs 服務(wù)器將會給我們返回一個 devicetoken夏伊,我們獲取到這個 token 后會將這個 token 發(fā)送給我們自己的應(yīng)用服務(wù)器。當(dāng)我們需要推送消息時吻氧,我們的應(yīng)用服務(wù)器將消息按照指定的格式進(jìn)行打包溺忧,然后結(jié)合 iOS 設(shè)備的 devicetoken 一起發(fā)給 APNs 服務(wù)器。我們的應(yīng)用會和 APNs 服務(wù)器維持一個基于 TCP 的長連接盯孙,APNs 服務(wù)器將新消息推送到iOS 設(shè)備上砸狞,然后在設(shè)備屏幕上顯示出推送的消息。
設(shè)備注冊APNs的流程圖:
上圖完成了如下步驟:
1.Device(設(shè)備)連接APNs服務(wù)器并攜帶設(shè)備序列號(UUID)
2.連接成功镀梭,APNs經(jīng)過打包和處理產(chǎn)生devicetoken并返回給注冊的Device(設(shè)備)
3.Device(設(shè)備)攜帶獲取的devicetoken發(fā)送到我們自己的應(yīng)用服務(wù)器
4.完成需要被推送的Device(設(shè)備)在APNs服務(wù)器和我們自己的應(yīng)用服務(wù)器的注冊
推送過程圖:
1.首先,我們的設(shè)備安裝了具有推送功能的應(yīng)用(應(yīng)用程序要用代碼注冊消息推動)踱启,我們的 iOS設(shè)備在有網(wǎng)絡(luò)的情況下會連接APNs推送服務(wù)器报账,連接過程中,APNS 服務(wù)器會驗證devicetoken埠偿,連接成功后維持一個基于TCP 的長連接透罢;
2.Provider(我們自己的應(yīng)用服務(wù)器)收到需要被推送的消息并結(jié)合被推送的 iOS設(shè)備的devicetoken一起打包發(fā)送給APNS服務(wù)器;
3.APNS服務(wù)器將推送信息推送給指定devicetoken的iOS設(shè)備冠蒋;
4.iOS設(shè)備收到推送消息后通知我們的應(yīng)用程序并顯示和提示用戶(聲音羽圃、彈出框)
信息包結(jié)構(gòu)圖:
上圖顯示的這個消息體就是我們的應(yīng)用服務(wù)器(Provider)發(fā)送給APNs服務(wù)器的消息結(jié)構(gòu),APNs驗證這個結(jié)構(gòu)正確并提取其中的信息后抖剿,再將消息推送到指定的iOS設(shè)備朽寞。這個結(jié)構(gòu)體包括五個部分,第一個部分是命令標(biāo)示符斩郎,第二個部分是我們的devicetoken的長度脑融,第三部分是我們的devicetoken字符串,第四部分是推送消 息體(Payload)的長度缩宜,最后一部分也就是真正的消息內(nèi)容了肘迎,里面包含了推送消息的基本信息,比如消息內(nèi)容锻煌,應(yīng)用Icon右上角顯示多少數(shù)字以及推送消息到達(dá)時所播放的聲音等
Payload(消息體)的結(jié)構(gòu):
{?
?“aps”:{?
?“alert”:“send message”,?
?“badge”:1,
?“sound”:“default” }
}
這其實(shí)就是個JSON結(jié)構(gòu)體妓布,alert標(biāo)簽的內(nèi)容就是會顯示在用戶手機(jī)上的推送信息,badge顯示的數(shù)量(注意是整型)是會在應(yīng)用Icon右上角顯示的數(shù)量宋梧,提示有多少條未讀消息等匣沼,sound就是當(dāng)推送信息送達(dá)是手機(jī)播放的聲音,傳defalut就標(biāo)明使用系統(tǒng)默認(rèn)聲音乃秀。
二肛著、配置證書
1.登錄Apple的Developer Member Center圆兵、
打開Safari瀏覽器,地址欄輸入并打開此網(wǎng)址:https://developer.apple.com/membercenter/index.action,然后用開發(fā)者賬號登錄.
選擇點(diǎn)擊Certificates, Identifiers & Profiles., 打開后在左側(cè)列表中選擇Certificates大類下面的All子類,出現(xiàn)如下界面:
2.選擇證書的類型,Sandbox或者Productuon
根據(jù)你的需求選擇Apple Push Notification service SSL (Sandbox) 或者 Apple Push Notification service SSL (Sandbox & Production)類型的證書.
然后點(diǎn)擊繼續(xù).
這里要注意一點(diǎn),選擇證書的正確類型非常重要:
一個用Development Provisioning Profile簽名的App生成的 Device Token只能和Sandbox APNS Server結(jié)合使用(開發(fā)環(huán)境測試用).
一個用AdHoc Provisioning Profile或者AppStore Provisioning Profile簽名的App生成的Device Token只能和Production APNS Server結(jié)合使用(生產(chǎn)環(huán)境發(fā)布使用).
提示:
有些用戶已經(jīng)報告過關(guān)于使用二合一的推送證書(Apple Push Notification service SSL (Sandbox & Production),新出的 )在調(diào)試測試環(huán)境進(jìn)行推送時會出問題.
3.選擇你對應(yīng)的App ID
前提你要先已經(jīng)創(chuàng)建了你App使用的App ID,并在App ID下拉選項中選擇你對應(yīng)的App ID.
點(diǎn)擊繼續(xù)按鈕繼續(xù).
4.查看創(chuàng)建證書簽名請求相關(guān)步驟信息
查看一下如何創(chuàng)建一個CSR文件的信息.
點(diǎn)擊繼續(xù).
該頁面有關(guān)于如何一步一步創(chuàng)建CSR文件的詳細(xì)信息,下面我們就跟著一步一步來創(chuàng)建CSR文件.
5.打開鑰匙串訪問程序
打開Launchpad中的其他組的Keychain Access App,就是鑰匙串訪問程序.
6.創(chuàng)建證書簽名請求文件
點(diǎn)擊鑰匙串訪問程序的菜單欄
選擇證書助理子菜單
選擇從證書頒發(fā)機(jī)構(gòu)請求證書...子子菜單
7.填寫證書簽名請求文件詳細(xì)信息
輸入email地址,為了安全和保險起見,最好填寫和你Apple開發(fā)者賬號對應(yīng)的email地址.
接著輸入常用名稱.
最好選擇存儲到磁盤選項.
最后點(diǎn)擊繼續(xù).
8.保存證書簽名請求文件到磁盤
選擇一個存儲位置以及輸入一個你喜歡的文件名稱
點(diǎn)擊保存
9.完成證書簽名請求文件制作
點(diǎn)擊完成
10.上傳正確簽名請求文件
繼續(xù)回到第四步后的瀏覽器界面
選擇 Choose File...來上傳
在彈出的文件打開對話框中定位到剛剛存儲的證書簽名請求文件所在目錄,并選擇打開該CSR文件.
點(diǎn)擊繼續(xù)
11.下載證書文件
上一步繼續(xù)之后,你的證書應(yīng)該就已經(jīng)生成好了.
點(diǎn)擊下載按鈕來下載證書.
打開下載的證書文件,一般會自動用鑰匙串訪問程序打開的.
三、代碼配置
打開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];
? ? ? ? // 必須寫代理枢贿,不然無法監(jiān)聽通知的接收與點(diǎn)擊
? ? ? ? center.delegate=self;
? ? ? ? [centerrequestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
? ? ? ? ? ? if(granted) {
? ? ? ? ? ? ? ? // 點(diǎn)擊允許
? ? ? ? ? ? ? ? NSLog(@"注冊成功");
? ? ? ? ? ? ? ? [centergetNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
? ? ? ? ? ? ? ? ? ? NSLog(@"%@", settings);
? ? ? ? ? ? ? ? }];
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? // 點(diǎn)擊不允許
? ? ? ? ? ? ? ? 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已經(jīng)接收到“遠(yuǎn)程”通知(推送) - 透傳推送消息? */
- (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通知的點(diǎn)擊事件
- (void)userNotificationCenter:(UNUserNotificationCenter*)center didReceiveNotificationResponse:(UNNotificationResponse*)response withCompletionHandler:(void(^)(void))completionHandler{
? ? //收到推送的請求
? ? UNNotificationRequest*request = response.notification.request;
? ? //收到推送的內(nèi)容
? ? UNNotificationContent*content = request.content;
? ? //收到用戶的基本信息
? ? NSDictionary*userInfo = content.userInfo;
? ? completionHandler();// 系統(tǒng)要求執(zhí)行這個方法
}
下面方法是返回 ANPs 蘋果推送服務(wù)器生成的唯一標(biāo)識
/** 接收服務(wù)器傳回的設(shè)備唯一標(biāo)識 token */
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
? ? NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
? ?? // 第一次運(yùn)行獲取到DeviceToken時間會比較長殉农!
? ? // 將deviceToken轉(zhuǎn)換成字符串,以便后續(xù)使用
? ? NSString *token = [deviceToken description];
? ? NSLog(@"description %@", token);
}
/** 注冊推送服務(wù)失敗 */
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@"注冊失敗 %@",error);
}
四局荚、測試
測試推送鏈路是否通暢的工具有很多超凳,大家自行選擇,比如個推等等耀态。轮傍。。需要注意的是推送是有丟失率的首装,不是100%每推必達(dá)4匆埂!仙逻!