iOS10 推送

push的主要工作流程:


  • iOS设备连接网络后,会自动与APNS保持类似TCP的长连接,等待APNS推送消息。
  • 应用启动时会注册消息推送,并且会从APNS获取到注册的唯一设备标识deviceToken,我们要把上传给应用的服务器。
692194-4be41eab63ed71a9-1.jpg
  • 在需要给应用推送消息时,Provider把push内容、接受push消息的deviceToken按APNS指定的格式打包好,发送给APNS;
  • APNS接收到Provider发送的消息后,查找deviceToken,如果该设备已经和APNS建立了连接,则立即将该消息推送给该设备,如果设备不在线,则在设备下次连接到APNS后将消息推送给该设备。请注意苹果并不保证推送一定成功。
  • 设备受到push消息后,iOS系统会根据SSL证书判断这个push消息是发给那个应用的,进而启动相应的客户端。

在上述过程中,有两个关键步骤需要自己处理:

  • 获取设备的deviceToken并上传到Provider;
  • Provider发送推送消息到APNS;

这两个步骤都需要苹果的证书授权。

iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifications.framework 来集中管理和使用 iOS 系统中通知的功能。在此基础上,Apple 还增加了撤回单条通知,更新已展示通知,中途修改通知内容,在通知中展示图片视频,自定义通知 UI 等一系列新功能,非常强大。
在程序启动后注册通知:

  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;
    }

程序第一次启动调用这个方法时又弹出框:

IMG_0464.jpg

要注意的是,一旦用户选择了不允许,之后程序里再次调用该方法也不会再进行弹窗,granted会一直是NO,用户必须自行前往系统的设置中为你的应用打开通知才能收到推动消息。

远程推送

一旦用户同意后,你就可以在应用中发送本地通知了。如果你想通过服务器发送远程通知的话,还需要多一个获取用户 token 的操作。你的服务器可以使用这个 token 向 Apple Push Notification 的服务器提交请求,然后 APNs 通过 token 识别设备和应用,将通知推给用户。

我们使用 UIApplication 的 registerForRemoteNotifications 来注册远程通知,在 AppDelegate 的 代理方法中获取用户 token:

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

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

发送一个本地的推送:

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);
     }
 }];

调用这个方法以后把程序切换到后台(程序在前台时不会显示本地通知):


push.jpg

处理通知:

//当应用在前台收到通知时会调用这个方法,应用在后台或杀掉应用时是不会调用的
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
     //在前台显示通知
    completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);
    //如果不想显示这个通知,可以
    //completionHandler(0);
}

//这个代理方法会在用户与你推送的通知进行交互时被调用(不论在前台还是后台),包括用户通过通知打开了你的应用,或者出发了某个action,在这个方法的里必须要调用completionHandler来告诉系统你已经处理了通知
//UNNotificationResponses是一个几乎包含了通知所有信息的对象,可以获取到本地推送消息的userinfo,远程推送的payload内的内容也会出现在这个userInfo中。可以通过userInfo的内容来决定页面的跳转或者是进行其它操作。
- (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里,本地通知和远程通知合二为一,区分本地通知跟远程通知的类是UNPushNotificationTrigger这个类,UNPushNotificationTrigger的类型是新增加的,通过它,我们可以得到一些通知的触发条件,在使用时,我们不应该直接使用这个类,应当使用它的子类。

  • UNTimeIntervalNotificationTrigger 在特定的时间后出发本地通知
    UNCalendarNotificationTrigger 在特定的date触发本地通知
    UNLocationNotificationTrigger 在用户到达特定的地理位置时出发本地通知
    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; // 收到推送的消息内容
    NSNumber *badge = content.badge;  // 推送消息的角标
    NSString *body = content.body;    // 推送消息体
    UNNotificationSound *sound = content.sound;  // 推送消息的声音
    NSString *subtitle = content.subtitle;  // 推送消息的副标题
    NSString *title = content.title;  // 推送消息的标题

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

    }
    else {
        // 判断为本地通知
        NSLog(@"iOS10 前台收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
    }
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
}
通知的点击事件
- (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; // 收到推送的消息内容
    NSNumber *badge = content.badge;  // 推送消息的角标
    NSString *body = content.body;    // 推送消息体
    UNNotificationSound *sound = content.sound;  // 推送消息的声音
    NSString *subtitle = content.subtitle;  // 推送消息的副标题
    NSString *title = content.title;  // 推送消息的标题
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 收到远程通知:%@", [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();  // 系统要求执行这个方法
actionable.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 极光推送: 1.JPush当前版本是1.8.2,其SDK的开发除了正常的功能完善和扩展外也紧随苹果官方的步伐,SD...
    Isspace阅读 6,719评论 10 16
  • iOS10新增加了一个UserNotificationKit(用户通知框架)来整合通知相关的API,UserNot...
    AlanGe阅读 474评论 0 0
  • 简介 新框架 获取权限 获取用户设置 注册APNS,获取deviceToken 本地推送流程 远程推送流程 通知策...
    liuyanhongwl阅读 20,491评论 35 51
  • 本文发布在:iOS10 推送通知详解(UserNotifications) iOS10新增加了一个UserNoti...
    曲年阅读 9,181评论 2 22
  • NO1:《阿甘正传》 NO2:《比海更深》 NO3:《革命之路》 NO4:《辛德勒名单》 NO5:《一个陌生女人的...
    三岁喜欢钱阅读 117评论 0 0