iOS10 推送

push的主要工作流程:


  • iOS設(shè)備連接網(wǎng)絡(luò)后,會自動與APNS保持類似TCP的長連接,等待APNS推送消息。
  • 應(yīng)用啟動時會注冊消息推送,并且會從APNS獲取到注冊的唯一設(shè)備標(biāo)識deviceToken,我們要把上傳給應(yīng)用的服務(wù)器。
692194-4be41eab63ed71a9-1.jpg
  • 在需要給應(yīng)用推送消息時,Provider把push內(nèi)容、接受push消息的deviceToken按APNS指定的格式打包好,發(fā)送給APNS;
  • APNS接收到Provider發(fā)送的消息后,查找deviceToken,如果該設(shè)備已經(jīng)和APNS建立了連接,則立即將該消息推送給該設(shè)備,如果設(shè)備不在線,則在設(shè)備下次連接到APNS后將消息推送給該設(shè)備。請注意蘋果并不保證推送一定成功。
  • 設(shè)備受到push消息后,iOS系統(tǒng)會根據(jù)SSL證書判斷這個push消息是發(fā)給那個應(yīng)用的,進(jìn)而啟動相應(yīng)的客戶端。

在上述過程中,有兩個關(guān)鍵步驟需要自己處理:

  • 獲取設(shè)備的deviceToken并上傳到Provider;
  • Provider發(fā)送推送消息到APNS;

這兩個步驟都需要蘋果的證書授權(quán)。

iOS 10 中以前雜亂的和通知相關(guān)的 API 都被統(tǒng)一了,現(xiàn)在開發(fā)者可以使用獨(dú)立的 UserNotifications.framework 來集中管理和使用 iOS 系統(tǒng)中通知的功能。在此基礎(chǔ)上,Apple 還增加了撤回單條通知,更新已展示通知,中途修改通知內(nèi)容,在通知中展示圖片視頻,自定義通知 UI 等一系列新功能,非常強(qiáng)大。
在程序啟動后注冊通知:

  if (NSClassFromString(@"UNUserNotificationCenter")) {
        [UNUserNotificationCenter currentNotificationCenter].delegate = self;
        [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError *error) {
            if (granted) {
#if !TARGET_IPHONE_SIMULATOR
                UIApplication *application = [UIApplication sharedApplication];
                [application registerForRemoteNotifications];
#endif
            }
        }];
        return;
    }

程序第一次啟動調(diào)用這個方法時又彈出框:

IMG_0464.jpg

要注意的是,一旦用戶選擇了不允許,之后程序里再次調(diào)用該方法也不會再進(jìn)行彈窗,granted會一直是NO,用戶必須自行前往系統(tǒng)的設(shè)置中為你的應(yīng)用打開通知才能收到推動消息。

遠(yuǎn)程推送

一旦用戶同意后,你就可以在應(yīng)用中發(fā)送本地通知了。如果你想通過服務(wù)器發(fā)送遠(yuǎn)程通知的話,還需要多一個獲取用戶 token 的操作。你的服務(wù)器可以使用這個 token 向 Apple Push Notification 的服務(wù)器提交請求,然后 APNs 通過 token 識別設(shè)備和應(yīng)用,將通知推給用戶。

我們使用 UIApplication 的 registerForRemoteNotifications 來注冊遠(yuǎn)程通知,在 AppDelegate 的 代理方法中獲取用戶 token:

UIApplication *application = [UIApplication sharedApplication];
[application registerForRemoteNotifications];

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

發(fā)送一個本地的推送:

UNMutableNotificationContent * content = [[UNMutableNotificationContent alloc] init];
content.title = @"test local push";
content.body = @"本地的推送消息";
    
UNTimeIntervalNotificationTrigger * trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:10 repeats:NO];
NSString * requestIdentifier = @"com.onevcat.usernotification.myFirstNotification";
UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:requestIdentifier content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
     if (error) {
         NSLog(@"%@", error);
     }
 }];

調(diào)用這個方法以后把程序切換到后臺(程序在前臺時不會顯示本地通知):


push.jpg

處理通知:

//當(dāng)應(yīng)用在前臺收到通知時會調(diào)用這個方法,應(yīng)用在后臺或殺掉應(yīng)用時是不會調(diào)用的
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
     //在前臺顯示通知
    completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);
    //如果不想顯示這個通知,可以
    //completionHandler(0);
}

//這個代理方法會在用戶與你推送的通知進(jìn)行交互時被調(diào)用(不論在前臺還是后臺),包括用戶通過通知打開了你的應(yīng)用,或者出發(fā)了某個action,在這個方法的里必須要調(diào)用completionHandler來告訴系統(tǒng)你已經(jīng)處理了通知
//UNNotificationResponses是一個幾乎包含了通知所有信息的對象,可以獲取到本地推送消息的userinfo,遠(yuǎn)程推送的payload內(nèi)的內(nèi)容也會出現(xiàn)在這個userInfo中??梢酝ㄟ^userInfo的內(nèi)容來決定頁面的跳轉(zhuǎn)或者是進(jìn)行其它操作。
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response 
withCompletionHandler:(void(^)())completionHandler {
    NSLog(@"%s", __func__);
    completionHandler();
}

![response.jpg](http://upload-images.jianshu.io/upload_images/1311714-046082786218e449.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

在iOS10里,本地通知和遠(yuǎn)程通知合二為一,區(qū)分本地通知跟遠(yuǎn)程通知的類是UNPushNotificationTrigger這個類,UNPushNotificationTrigger的類型是新增加的,通過它,我們可以得到一些通知的觸發(fā)條件,在使用時,我們不應(yīng)該直接使用這個類,應(yīng)當(dāng)使用它的子類。

  • UNTimeIntervalNotificationTrigger 在特定的時間后出發(fā)本地通知
    UNCalendarNotificationTrigger 在特定的date觸發(fā)本地通知
    UNLocationNotificationTrigger 在用戶到達(dá)特定的地理位置時出發(fā)本地通知
    UNPushNotificationTrigger 表示APNS通知
// iOS 10收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
    NSDictionary * userInfo = notification.request.content.userInfo;
    UNNotificationRequest *request = notification.request; // 收到推送的請求
    UNNotificationContent *content = request.content; // 收到推送的消息內(nèi)容
    NSNumber *badge = content.badge;  // 推送消息的角標(biāo)
    NSString *body = content.body;    // 推送消息體
    UNNotificationSound *sound = content.sound;  // 推送消息的聲音
    NSString *subtitle = content.subtitle;  // 推送消息的副標(biāo)題
    NSString *title = content.title;  // 推送消息的標(biāo)題

    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 前臺收到遠(yuǎn)程通知:%@", [self logDic:userInfo]);

    }
    else {
        // 判斷為本地通知
        NSLog(@"iOS10 前臺收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
    }
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要執(zhí)行這個方法,選擇是否提醒用戶,有Badge、Sound、Alert三種類型可以設(shè)置
}
通知的點(diǎn)擊事件
- (void)userNotificationCenter:(UNUserNotificationCenter *)center 
didReceiveNotificationResponse:(UNNotificationResponse *)response 
         withCompletionHandler:(void(^)())completionHandler{

    NSDictionary * userInfo = response.notification.request.content.userInfo;
    UNNotificationRequest *request = response.notification.request; // 收到推送的請求
    UNNotificationContent *content = request.content; // 收到推送的消息內(nèi)容
    NSNumber *badge = content.badge;  // 推送消息的角標(biāo)
    NSString *body = content.body;    // 推送消息體
    UNNotificationSound *sound = content.sound;  // 推送消息的聲音
    NSString *subtitle = content.subtitle;  // 推送消息的副標(biāo)題
    NSString *title = content.title;  // 推送消息的標(biāo)題
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 收到遠(yuǎn)程通知:%@", [self logDic:userInfo]);

    }
    else {
        // 判斷為本地通知
        NSLog(@"iOS10 收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
    }

    // Warning: UNUserNotificationCenter delegate received call to -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: but the completion handler was never called.
    completionHandler();  // 系統(tǒng)要求執(zhí)行這個方法
actionable.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 極光推送: 1.JPush當(dāng)前版本是1.8.2,其SDK的開發(fā)除了正常的功能完善和擴(kuò)展外也緊隨蘋果官方的步伐,SD...
    Isspace閱讀 6,874評論 10 16
  • iOS10新增加了一個UserNotificationKit(用戶通知框架)來整合通知相關(guān)的API,UserNot...
    AlanGe閱讀 513評論 0 0
  • 簡介 新框架 獲取權(quán)限 獲取用戶設(shè)置 注冊APNS,獲取deviceToken 本地推送流程 遠(yuǎn)程推送流程 通知策...
    liuyanhongwl閱讀 20,731評論 35 51
  • 本文發(fā)布在:iOS10 推送通知詳解(UserNotifications) iOS10新增加了一個UserNoti...
    曲年閱讀 9,394評論 2 22
  • NO1:《阿甘正傳》 NO2:《比海更深》 NO3:《革命之路》 NO4:《辛德勒名單》 NO5:《一個陌生女人的...
    三歲喜歡錢閱讀 164評論 0 0

友情鏈接更多精彩內(nèi)容