前言
之前说会单独整理消息通知的内容,但是因为工(就)作(是)的(很)事(懒)没有更新文章,违背了自己的学习的初衷。因为互联网一定要有危机意识,说不定眼一睁,我们就out丢了饭碗。
“狼,他没有狮子老虎强壮,也没有大象那庞大的身躯,但至少:我从来没在马戏团看到过他们的身影。”
也许只有狼在一直奔跑,这是我一直喜欢它的原因,要像狼一样不断奔跑,才能幸存!
看完楼主装的一手好X,我来总结一点点你都知道的通知方面的知识点!
背景
iOS10 新特性一出,各个大神就早已研究新特性能给场景智能化所带来的好处(唉,可惜我只是一个小白)。我也被安排适配iOS10的推送工作!
Apple 表示这是 iOS 有史以来最大的升级(our biggest release yet),更加智能开放的 Siri 、强化应用对 3D Touch 支持、 HomeKit 、电话拦截及全新设计的通知等等…
iOS 10 中将之前繁杂的推送通知统一成UserNotifications.framework 来集中管理和使用通知功能,还增加一些实用的功能——撤回单条通知、更新已展示通知、中途修改通知内容、在通知中显示多媒体资源、自定义UI等功能,功能着实强大!
本文主要是针对iOS 10的消息通知做介绍,所以很多代码没有对iOS 10之前做添加适配。
基本原理
iOS推送分为Local Notifications(本地推送) 和 Remote Notifications(远程推送)(原理图来源于网络,如有侵权请告知,我会添加来源,我怕我赔不起)
Local Notifications(本地推送)
- App本地创建通知,加入到系统的Schedule里,
- 如果触发器条件达成时会推送相应的消息内容
Remote Notifications(远程推送)
图中,Provider是指某个iPhone软件的Push服务器,这篇文章我将使用我花了12块大洋(心疼)买的 APNS Pusher 作为我的推送源。
APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的服务器。
上图可以分为三个阶段:
第一阶段:APNS Pusher应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序, 并且按照设定弹出Push通知。
从上图我们可以看到:
- 首先是应用程序注册消息推送。
- IOS跟APNS Server要deviceToken。应用程序接受deviceToken。
- 应用程序将deviceToken发送给PUSH服务端程序。
- 服务端程序向APNS服务发送消息。
- APNS服务将消息发送给iPhone应用程序。
基本配置和基本方法
如果只是简单的本地推送,跳过1 2 步骤,直接到3
1、 如果你的App有远端推送的话,那你需要开发者账号的,需要新建一个对应你bundle的push 证书。证书这一块我就不说了,如果针对证书有什么问题可以给我留言,我会单独把证书相关的知识点整理起来!当然本人是非常喜欢的分享的(又装逼),如果你没有账号,我可以把我测试用的证书发给你,用于你的测试和学习,私聊我。
2、 Capabilities中打开Push Notifications 开关
在XCode7中这里的开关不打开,推送也是可以正常使用的,但是在XCode8中,这里的开关必须要打开,不然会报错:
1 |
Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“aps-environment”的授权字符串" UserInfo={NSLocalizedDescription=未找到应用程序的“aps-environment”的授权字符串} |
打开后会自动在项目里生成entitlements文件。
3、 推送的注册
第一步: 导入 #import
且要遵守的协议,在Appdelegate.m中。
这里需要注意,我们最好写成这种形式(防止低版本找不到头文件出现问题)
1 2 3 |
#ifdef NSFoundationVersionNumber_iOS_9_x_Max #import #endif |
第二步:我们需要在
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中注册通知,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self replyPushNotificationAuthorization:application]; return YES; } #pragma mark - 申请通知权限 // 申请通知权限 - (void)replyPushNotificationAuthorization:(UIApplication *)application{ if (IOS10_OR_LATER) { //iOS 10 later UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; //必须写代理,不然无法监听通知的接收与点击事件 center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (!error && granted) { //用户点击允许 NSLog(@"注册成功"); }else{ //用户点击不允许 NSLog(@"注册失败"); } }]; // 可以通过 getNotificationSettingsWithCompletionHandler 获取权限设置 //之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意UNNotificationSettings是只读对象哦,不能直接修改! [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { NSLog(@"========%@",settings); }]; }else if (IOS8_OR_LATER){ //iOS 8 - iOS 10系统 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; }else{ //iOS 8.0系统以下 [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound]; } //注册远端消息通知获取device token [application registerForRemoteNotifications]; } |
上面需要注意:
1 2 3 |
#ifdef NSFoundationVersionNumber_iOS_9_x_Max #import #endif |
第二步:我们需要在
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中注册通知,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self replyPushNotificationAuthorization:application]; return YES; } #pragma mark - 申请通知权限 // 申请通知权限 - (void)replyPushNotificationAuthorization:(UIApplication *)application{ if (IOS10_OR_LATER) { //iOS 10 later UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; //必须写代理,不然无法监听通知的接收与点击事件 center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (!error && granted) { //用户点击允许 NSLog(@"注册成功"); }else{ //用户点击不允许 NSLog(@"注册失败"); } }]; // 可以通过 getNotificationSettingsWithCompletionHandler 获取权限设置 //之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意UNNotificationSettings是只读对象哦,不能直接修改! [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { NSLog(@"========%@",settings); }]; }else if (IOS8_OR_LATER){ //iOS 8 - iOS 10系统 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; }else{ //iOS 8.0系统以下 [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound]; } //注册远端消息通知获取device token [application registerForRemoteNotifications]; } |
上面需要注意:
1 2 3 4 5 6 7 8 9 10 11 12 -12">12 13 14 15
|
1. 必须写代理,不然无法监听通知的接收与点击事件 center.delegate = self; 下面是我在项目里定义的宏 #define IOS10_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) #define IOS9_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) #define IOS8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) #define IOS7_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) 2. 之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意UNNotificationSettings是只读对象哦,不能直接修改!只能通过以下方式获取 [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { NSLog(@"========%@",settings); }]; 打印信息如下: ======== |
4、 远端推送需要获取设备的Device Token的方法是没有变的,代码如下