蘋果的推送通知從iOS3開始出現(xiàn), 每一年都會更新一些新的用法, 譬如:
- iOS 7 出現(xiàn)的Silent remote notifications(遠程靜默推送)
- iOS 8 出現(xiàn)的Category(分類, 也可稱之為快捷回復(fù))
- iOS 9 出現(xiàn)的Text Input action(文本框快捷回復(fù)).
隨著iOS10的到來 , 蘋果對遠程通知和本地通知進行了大范圍的更新.
iOS10推出了全新的UserNotifications框架(iOS10之前從屬于UIKit框架).
新的推送通知框架, 整合了本地推送和遠程推送的點擊處理方法, 使得以前專門處理推送點擊的方法只能處理靜默推送了.
遠程推送的實現(xiàn)原理:
1 打開App時: 發(fā)送UDID和BundleID給APNs加密后返回deviceToken
2 獲取Token后啦辐,App調(diào)用接口,將用戶身份信息和deviceToken發(fā)給服務(wù)器蜈项,服務(wù)器記錄
3 當推送消息時, 服務(wù)器按照用戶身份信息找到存儲的deviceToken紧卒,將消息和deviceToken發(fā)送給APNs
4 蘋果的APNs通過deviceToken, 找到指定設(shè)備的指定程序, 并將消息推送給用戶
實現(xiàn)遠程推送功能的前提:
1 真機
2 調(diào)試階段的證書
- iOS_development.cer 用于真機調(diào)試的證書
- aps_development.cer 用于真機推送調(diào)試能的證書
- xxx.mobileprovision 描述文件,記錄了能夠調(diào)試的手機轴总、電腦和程序
3 發(fā)布階段的證書
- iOS_distribution.cer 用于發(fā)布app的證書
- aps.cer 用于發(fā)布時,讓app有推送功能的證書
- xxx.mobileprovision 描述文件怀樟,記錄了能夠發(fā)布app的電腦
iOS10 全新遠程通知Demo:
一. 注冊遠程推送并獲取DeviceToken
1.創(chuàng)建iOS的項目盆佣,并輸入項目名字
2.在AppDelegate中導(dǎo)入頭文件:
#import <UserNotifications/UserNotifications.h>
3.在application:didFinishLaunchingWithOptions方法中, 注冊遠程通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//請求通知權(quán)限, 本地和遠程共用
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"請求成功");
} else {
NSLog(@"請求失敗");
}
}];
//注冊遠程通知
[[UIApplication sharedApplication] registerForRemoteNotifications];
//設(shè)置通知的代理
center.delegate = self;
return YES;
}
4.在接收遠程推送的DeviceToken方法中, 獲取Token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
//將來需要將此Token上傳給后臺服務(wù)器
NSLog(@"token:%@", deviceToken);
}
二. iOS10遠程推送通知的處理方法
當點擊了推送后, 如果你希望進行處理. 那么在iOS10中, 還需要設(shè)置UNUserNotificationCenter的delegate, 并遵守UNUserNotificationCenterDelegate協(xié)議.
以及實現(xiàn)下面實現(xiàn)3個方法, 用于處理點擊通知時的不同情況的處理
* userNotificationCenter:willPresentNotification:withCompletionHandler:
前臺運行
* userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
后臺運行時點擊橫幅投蝉、消息欄消息
* application:didReceiveRemoteNotification:fetchCompletionHandler:
靜默推送征堪、App殺死后橫幅和消息欄消息點擊喚起App
//設(shè)置通知的代理
center.delegate = self;
1.前臺運行 會調(diào)用的方法
前臺運行: 指的是程序正在運行中, 用戶能看見程序的界面.
iOS10會出現(xiàn)通知橫幅, 而在以前的框架中, 前臺運行時, 不會出現(xiàn)通知的橫幅.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;
//前臺運行推送 顯示紅色Label
[self showLabelWithUserInfo:userInfo color:[UIColor redColor]];
//可以設(shè)置當收到通知后, 有哪些效果呈現(xiàn)(聲音/提醒/數(shù)字角標)
completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}
2.后臺運行點擊消息會調(diào)用的方法
后臺運行: 指的是程序已經(jīng)打開, 用戶看不見程序的界面, 如鎖屏和按Home鍵.
程序退出: 指的是程序沒有運行, 或者通過雙擊Home鍵,關(guān)閉了程序.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler
{
NSDictionary *userInfo = response.notification.request.content.userInfo;
//后臺顯示綠色Label
[self showLabelWithUserInfo:userInfo color:[UIColor greenColor]];
completionHandler();
}
3.靜默推送通知 會調(diào)用的方法
靜默推送: iOS7以后出現(xiàn), 不會出現(xiàn)提醒及聲音.
要求:
- 推送的payload中不能包含alert及sound字段
- 需要添加content-available字段, 并設(shè)置值為1
- 例如: {"aps":{"content-available":"1"},"PageKey”":"2"}
//如果是以前的舊框架, 此方法 前臺/后臺/退出/靜默推送都可以處理
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
//靜默推送 顯示藍色Label
[self showLabelWithUserInfo:userInfo color:[UIColor blueColor]];
completionHandler(UIBackgroundFetchResultNewData);
}
4.處理通知的公用方法
開發(fā)中, 點擊通知的邏輯應(yīng)當看自己程序的需求.
這里為了方便演示, 簡單的將通知的值, 通過UILabel顯示在主界面上
- (void)showLabelWithUserInfo:(NSDictionary *)userInfo color:(UIColor *)color
{
UILabel *label = [UILabel new];
label.backgroundColor = color;
label.frame = CGRectMake(0, 250, [UIScreen mainScreen].bounds.size.width, 300);
label.text = userInfo.description;
label.numberOfLines = 0;
[[UIApplication sharedApplication].keyWindow addSubview:label];
}
三. 測試遠程推送
PushMeBaby是一個簡單的模擬服務(wù)器的Mac小程序, 可以將內(nèi)容提交給蘋果的APNs服務(wù)器.
為了測試遠程通知, 我們需要安裝此程序.
請前往www.github.com, 搜索并下載PushMeBaby
使用時:
- 編譯該項目, 如果報錯, 則注釋報錯的代碼, 不影響實際使用.
- 進入蘋果開發(fā)者網(wǎng)站, 獲取真機調(diào)試用的遠程推送證書, 導(dǎo)入到項目中
- 將之前獲取到的DeviceToken, 及測試的文字, 填入該項目中的AppDelegate中的init方法中.
- 運行此項目, 會出現(xiàn)一個Mac小程序, 點擊Push即可發(fā)送遠程通知.
- (id)init {
self = [super init];
if(self != nil) {
self.deviceToken = @"de20184c ef0461d5 12c76422 f5b78240 5f657e18 ebf91c9f 01d5560c e2913102";
self.payload = @"{\"aps\":{\"alert\":{\"title\":\"傳智播客\",\"subtitle\":\"黑馬程序員\",\"body\":\"iOS10遠程&本地推送教程\"},\"badge\":1,\"sound\":\"default\"},\"PageKey\":\"1\"}";
self.certificate = [[NSBundle mainBundle] pathForResource:@"aps_development" ofType:@"cer"];
}
return self;
}
四.補充
因為推送的回調(diào)Api方法過多, 初次接觸可能會有些頭大,雖然從iOS 10起,蘋果對于推送的授權(quán)(本地+遠程)方式有所調(diào)整, 而且采用了使用代理的方式. 而我們也可以采取的實現(xiàn)方式是:
1. 通過requestAuthorizationWithOptions:授權(quán)
2. 不設(shè)置UNUserNotificationCenter 的 delegate
3. 這樣還會走之前iOS 9的回調(diào)方法
五. 回調(diào)API
-
application: didReceiveRemoteNotification: fetchCompletionHandler:
前臺收到推送消息時,不會有彈框提醒 -
userNotificationCenter: willPresentNotification: withCompletionHandler:
可以通過設(shè)置回調(diào)參數(shù),根據(jù)回調(diào)參數(shù)內(nèi)是否傳入UNNotificationPresentationOptionAlert
,如果有,則在前臺收到推送時,也會有彈框提醒,在系統(tǒng)通知欄內(nèi)可見推送消息,如果不傳入,則不會有彈框提醒,系統(tǒng)通知欄不可見
completionHandler( UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound );
對于收到推送后, 通知消息的獲取與進入App的方式有關(guān):
- App未運行時:
1.1 點擊通知消息進入, 會執(zhí)行didFinishLaunchWithOptions:
方法,通過options獲取通知消息
1.2 點擊應(yīng)用圖標進入,會執(zhí)行didFinishLaunchWithOptions
方法,但options中不包含notification信息
- App未運行時:
2.App后臺運行:
2.1 點擊通知消息進入,會執(zhí)行didReceiveRemoteNotification:
方法(不同iOS版本的后臺方法),從而獲取推送消息
2.2 點擊應(yīng)用圖標進入,會執(zhí)行didReceiveRemoteNotification
方法不會被調(diào)用,無法獲取到推送消息對于1.2和2.2場景, 可以通過后臺協(xié)助, 每次點擊應(yīng)用圖標進入后,向后臺請求是否有新的未讀推送,通過請求的方式獲取推送信息.
對于1.1&1.2場景, 如果遠程通知到達時應(yīng)用程序未運行,則
application: didReceiveRemoteNotification: fetchCompletionHandler:
該方法將啟動應(yīng)用程序并在啟動選項字典中提供適當?shù)男畔ⅰ?/p>
if the app is not running when a remote notification arrives,
the method launches the app and provides the appropriate information in the launch options dictionary.
The app does not call this method to handle that remote notification.
Instead, your implementation of the
application:willFinishLaunchingWithOptions:
or
application:didFinishLaunchingWithOptions:
method needs to get the remote notification payload data and respond appropriately.
關(guān)于角標:
App當前角標 | 收到推送 | 變化 |
---|---|---|
角標為0 | 推送badge > 0 | 角標 = badge |
角標為0 | 推送badge = 0 | 不顯示角標 |
角標不為0 | 推送badge > 0 | 角標 = badge (最后一條推送中的badge) |
角標不為0 | 推送badge = 0 | 角標 = 0 , 同時在通知欄清空之前的推送記錄 |