iOS---iOS10适配iOS当前所有系统的远程推送
一、iOS推送通知简介
众所周知苹果的推送通知从iOS3开始出现, 每一年都会更新一些新的用法. 譬如iOS7出现的Silent remote notifications(远程静默推送), iOS8出现的Category(分类, 也可称之为快捷回复), iOS9出现的Text Input action(文本框快捷回复).
而在iOS10, 苹果可谓是大刀阔斧般的, 对远程通知和本地通知进行了大范围的更新. iOS10推出了全新的UserNotifications框架(iOS10之前从属于UIKit框架).
新的推送通知框架, 整合了本地推送和远程推送的点击处理方法, 使得以前专门处理推送点击的方法只能处理静默推送了.
二、远程推送通知介绍
1、什么是远程推送
在联网的情况下,由远程服务器推送给客户端的通知,又称APNs(Apple Push Notification Services)不管应用是打开还是关闭的情况下,都能接收到服务器推送的远程通知在联网状态下,所有苹果设备都会与苹果服务器建立长连接
2、远程推送的实现原理:
1.打开App时: 发送UDID
和BundleID
给APNs
加密后返回deviceToken
2.获取Token
后,App调用接口,将用户身份信息和deviceToken
发给服务器,服务器记录
3.当推送消息时, 服务器按照用户身份信息找到存储的deviceToken
,将消息和deviToken
发送给APNs
4.苹果的APNs通过deviceToken
, 找到指定设备的指定程序, 并将消息推送给用户
3、实现远程推送功能的前提
1.真机
2.调试阶段的证书
iOS_development.cer
用于真机调试的证书
aps_development.cer
用于真机推送调试能的证书
xxx.mobileprovision
描述文件,记录了能够调试的手机、电脑和程序
3.发布阶段的证书
iOS_distribution.cer
用于发布app的证书
aps.cer
用于发布时,让app有推送功能的证书
xxx.mobileprovision
描述文件,记录了能够发布app的电脑
如何配置证书,请参考我的另一博文: iOS-推送,证书申请,本地推送
二、 iOS10远程推送通知的处理方法
当点击了推送后, 如果你希望进行处理. 那么在iOS10中, 还需要设置UNUserNotificationCenter
的delegate
, 并遵守UNUserNotificationCenterDelegate
协议.
以及实现下面实现3个方法, 用于处理点击通知时的不同情况的处理
willPresentNotification:withCompletionHandler
用于前台运行
didReceiveNotificationResponse:withCompletionHandler
用于后台及程序退出
didReceiveRemoteNotification:fetchCompletionHandler
用于静默推送
1.前台运行 会调用的方法
前台运行: 指的是程序正在运行中, 用户能看见程序的界面.
iOS10会出现通知横幅, 而在以前的框架中, 前台运行时, 不会出现通知的横幅.
代码开始前的设置
iOS 10 的推送 与原来的都不一样,他把本地的推送 跟 远程的推送结合到一起了,UserNotifications.framework 库。在使用推送的时候,先开启通知的开关。
就是上面这个。当你开启后,xcode 会自动帮你在 项目里面创建一个文件,xxxx.entitlements.
这个文件是系统帮你创建的,不用管它。
在appDeletgate 文件里面需要先导入 UNUserNotificationCenterDelegate 这个代理。他的代理方法分别是
- - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);
- - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler __IOS_AVAILABLE(10.0)
代码如下:
2 3 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 4 5 6 7 /** 8 9 注册远程推送和本地通知,适配至最新系统,目前是 iOS10 10 11 */ 12 13 [self registerRemoteNotificationsForAlliOSSystemVersion]; 14 15 16 17 18 19 // Override point for customization after application launch. 20 21 return YES; 22 23 } 24 25 26 27 /** 28 29 注册远程推送和本地通知,适配至最新系统,目前是 iOS10 30 31 */ 32 33 -(void)registerRemoteNotificationsForAlliOSSystemVersion{ 34 35 36 37 // 38 39 40 41 42 43 //导入文件 #import <UserNotifications/UserNotifications.h> 44 45 //去capabilities(功能)设置这边打开 pushNotifications,并且打开 backgroundModes 中的backgroundFentch,Remote Notifications 46 47 CGFloat version = [[[UIDevice currentDevice] systemVersion] floatValue]; 48 49 if (version >= 10.0) {//10.0及其以上 50 51 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; 52 53 //请求通知权限, 本地和远程共用 54 55 // 设定通知可选提示类型 56 57 [center requestAuthorizationWithOptions:UNAuthorizationOptionCarPlay | UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) { 58 59 if (error) { 60 61 NSLog(@"iOS10请求 接受远程和本地通知 授权失败:<%@>",[error description]); 62 63 } 64 65 66 67 if (granted) { 68 69 NSLog(@" iOS 10 request notification success"); 70 71 NSLog(@"请求成功"); 72 73 }else{ 74 75 NSLog(@" iOS 10 request notification fail"); 76 77 NSLog(@"请求失败"); 78 79 } 80 81 }]; 82 83 84 85 //设置通知的代理 86 87 center.delegate = self;//1.遵守UNUserNotificationCenterDelegate协议,2.成为代理;3.实现代理回调方法 88 89 }else if (version>=8.0){//8.0--->10.0 90 91 //请求用户授权 授权收到推送时有哪些提醒方式可以选 92 93 // 声音、角标、弹窗 94 95 UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert categories:nil]; 96 97 [[UIApplication sharedApplication] registerUserNotificationSettings:setting]; 98 99 }else{//8.0以下 100 101 UIRemoteNotificationType type = UIRemoteNotificationTypeSound| UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge; 102 103 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:type]; 104 105 } 106 107 108 109 //注册通知 110 111 [[UIApplication sharedApplication] registerForRemoteNotifications]; 112 113 114 115 116 117 118 119 } 120 121 #pragma mark-推送通知 122 123 //注册成功 124 125 -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ 126 127 128 129 NSString *token = [deviceToken description]; //获取 130 131 132 133 token = [token stringByReplacingOccurrencesOfString:@" " withString:@""]; 134 135 token = [token stringByReplacingOccurrencesOfString:@"<" withString:@""]; 136 137 token = [token stringByReplacingOccurrencesOfString:@">" withString:@""]; 138 139 140 141 NSLog(@"request notificatoin token success. %@",token); 142 143 144 145 146 147 148 149 } 150 151 //注册失败 152 153 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error 154 155 { 156 157 NSLog(@"request notification Token fail. %@",error.localizedDescription); 158 159 } 160 161 162 163 #pragma mark iOS 10 获取推送信息 UNUserNotificationCenter---Delegate 164 165 166 167 //APP在前台的时候收到推送的回调 168 169 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler 170 171 { 172 173 174 175 176 177 UNNotificationContent *content = notification.request.content; 178 179 NSDictionary *userInfo = content.userInfo; 180 181 182 183 [self handleRemoteNotificationContent:userInfo]; 184 185 186 187 //前台运行推送 显示红色Label 188 189 [self showLabelWithUserInfo:userInfo color:[UIColor redColor]]; 190 191 192 193 194 195 //可以设置当收到通知后, 有哪些效果呈现(提醒/声音/数字角标) 196 197 //可以执行设置 弹窗提醒 和 声音 198 199 completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound|UNNotificationPresentationOptionBadge); 200 201 } 202 203 //APP在后台,点击推送信息,进入APP后执行的回调 204 205 - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler 206 207 { 208 209 210 211 212 213 UNNotificationContent *content = response.notification.request.content; 214 215 NSDictionary *userInfo = content.userInfo; 216 217 218 219 [self handleRemoteNotificationContent:userInfo]; 220 221 //后台及退出推送 显示绿色Label 222 223 [self showLabelWithUserInfo:userInfo color:[UIColor greenColor]]; 224 225 226 227 completionHandler(); 228 229 } 230 231 232 233 - (void)handleRemoteNotificationContent:(NSDictionary *)userInfo 234 235 { 236 237 NSLog(@" iOS 10 after Notificatoin message:\n %@",userInfo); 238 239 } 240 241 #pragma mark iOS 10 之前 获取通知的信息 242 243 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ 244 245 246 247 //静默推送 显示蓝色Label 248 249 [self showLabelWithUserInfo:userInfo color:[UIColor blueColor]]; 250 251 252 253 completionHandler(UIBackgroundFetchResultNewData); 254 255 } 256 257 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 258 259 { 260 261 NSLog(@"iOS 10 before Notification message。\n %@",userInfo); 262 263 } 264 265 266 267 268 269 - (void)showLabelWithUserInfo:(NSDictionary *)userInfo color:(UIColor *)color 270 271 { 272 273 UILabel *label = [UILabel new]; 274 275 label.backgroundColor = color; 276 277 label.frame = CGRectMake(0, 250, [UIScreen mainScreen].bounds.size.width, 300); 278 279 label.text = userInfo.description; 280 281 label.numberOfLines = 0; 282 283 [[UIApplication sharedApplication].keyWindow addSubview:label]; 284 285 } 286 287 288 289