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)
代码如下:
<em> 2<br/>
3 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {<br/>
4<br/>
5<br/>
6<br/>
7 /**<br/>
8<br/>
9 注册远程推送和本地通知,适配至最新系统,目前是 iOS10<br/>
10<br/>
11 */<br/>
12<br/>
13 [self registerRemoteNotificationsForAlliOSSystemVersion];<br/>
14<br/>
15<br/>
16<br/>
17<br/>
18<br/>
19 // Override point for customization after application launch.<br/>
20<br/>
21 return YES;<br/>
22<br/>
23 }<br/>
24<br/>
25<br/>
26<br/>
27 /**<br/>
28<br/>
29 注册远程推送和本地通知,适配至最新系统,目前是 iOS10<br/>
30<br/>
31 */<br/>
32<br/>
33 -(void)registerRemoteNotificationsForAlliOSSystemVersion{<br/>
34<br/>
35<br/>
36<br/>
37 //<br/>
38<br/>
39<br/>
40<br/>
41<br/>
42<br/>
43 //导入文件 #import <UserNotifications/UserNotifications.h><br/>
44<br/>
45 //去capabilities(功能)设置这边打开 pushNotifications,并且打开 backgroundModes 中的backgroundFentch,Remote Notifications<br/>
46<br/>
47 CGFloat version = [[[UIDevice currentDevice] systemVersion] floatValue];<br/>
48<br/>
49 if (version >= 10.0) {//10.0及其以上<br/>
50<br/>
51 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];<br/>
52<br/>
53 //请求通知权限, 本地和远程共用<br/>
54<br/>
55 // 设定通知可选提示类型<br/>
56<br/>
57 [center requestAuthorizationWithOptions:UNAuthorizationOptionCarPlay | UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) {<br/>
58<br/>
59 if (error) {<br/>
60<br/>
61 NSLog(@"iOS10请求 接受远程和本地通知 授权失败:<%@>",[error description]);<br/>
62<br/>
63 }<br/>
64<br/>
65<br/>
66<br/>
67 if (granted) {<br/>
68<br/>
69 NSLog(@" iOS 10 request notification success");<br/>
70<br/>
71 NSLog(@"请求成功");<br/>
72<br/>
73 }else{<br/>
74<br/>
75 NSLog(@" iOS 10 request notification fail");<br/>
76<br/>
77 NSLog(@"请求失败");<br/>
78<br/>
79 }<br/>
80<br/>
81 }];<br/>
82<br/>
83<br/>
84<br/>
85 //设置通知的代理<br/>
86<br/>
87 center.delegate = self;//1.遵守UNUserNotificationCenterDelegate协议,2.成为代理;3.实现代理回调方法<br/>
88<br/>
89 }else if (version>=8.0){//8.0--->10.0<br/>
90<br/>
91 //请求用户授权 授权收到推送时有哪些提醒方式可以选<br/>
92<br/>
93 // 声音、角标、弹窗<br/>
94<br/>
95 UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert categories:nil];<br/>
96<br/>
97 [[UIApplication sharedApplication] registerUserNotificationSettings:setting];<br/>
98<br/>
99 }else{//8.0以下<br/>
100<br/>
101 UIRemoteNotificationType type = UIRemoteNotificationTypeSound| UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge;<br/>
102<br/>
103 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:type];<br/>
104<br/>
105 }<br/>
106<br/>
107<br/>
108<br/>
109 //注册通知<br/>
110<br/>
111 [[UIApplication sharedApplication] registerForRemoteNotifications];<br/>
112<br/>
113<br/>
114<br/>
115<br/>
116<br/>
117<br/>
118<br/>
119 }<br/>
120<br/>
121 #pragma mark-推送通知<br/>
122<br/>
123 //注册成功<br/>
124<br/>
125 -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{<br/>
126<br/>
127<br/>
128<br/>
129 NSString *token = [deviceToken description]; //获取<br/>
130<br/>
131<br/>
132<br/>
133 token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];<br/>
134<br/>
135 token = [token stringByReplacingOccurrencesOfString:@"<" withString:@""];<br/>
136<br/>
137 token = [token stringByReplacingOccurrencesOfString:@">" withString:@""];<br/>
138<br/>
139<br/>
140<br/>
141 NSLog(@"request notificatoin token success. %@",token);<br/>
142<br/>
143<br/>
144<br/>
145<br/>
146<br/>
147<br/>
148<br/>
149 }<br/>
150<br/>
151 //注册失败<br/>
152<br/>
153 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error<br/>
154<br/>
155 {<br/>
156<br/>
157 NSLog(@"request notification Token fail. %@",error.localizedDescription);<br/>
158<br/>
159 }<br/>
160<br/>
161<br/>
162<br/>
163 #pragma mark iOS 10 获取推送信息 UNUserNotificationCenter---Delegate<br/>
164<br/>
165<br/>
166<br/>
167 //APP在前台的时候收到推送的回调<br/>
168<br/>
169 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler<br/>
170<br/>
171 {<br/>
172<br/>
173<br/>
174<br/>
175<br/>
176<br/>
177 UNNotificationContent *content = notification.request.content;<br/>
178<br/>
179 NSDictionary *userInfo = content.userInfo;<br/>
180<br/>
181<br/>
182<br/>
183 [self handleRemoteNotificationContent:userInfo];<br/>
184<br/>
185<br/>
186<br/>
187 //前台运行推送 显示红色Label<br/>
188<br/>
189 [self showLabelWithUserInfo:userInfo color:[UIColor redColor]];<br/>
190<br/>
191<br/>
192<br/>
193<br/>
194<br/>
195 //可以设置当收到通知后, 有哪些效果呈现(提醒/声音/数字角标)<br/>
196<br/>
197 //可以执行设置 弹窗提醒 和 声音<br/>
198<br/>
199 completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound|UNNotificationPresentationOptionBadge);<br/>
200<br/>
201 }<br/>
202<br/>
203 //APP在后台,点击推送信息,进入APP后执行的回调<br/>
204<br/>
205 - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler<br/>
206<br/>
207 {<br/>
208<br/>
209<br/>
210<br/>
211<br/>
212<br/>
213 UNNotificationContent *content = response.notification.request.content;<br/>
214<br/>
215 NSDictionary *userInfo = content.userInfo;<br/>
216<br/>
217<br/>
218<br/>
219 [self handleRemoteNotificationContent:userInfo];<br/>
220<br/>
221 //后台及退出推送 显示绿色Label<br/>
222<br/>
223 [self showLabelWithUserInfo:userInfo color:[UIColor greenColor]];<br/>
224<br/>
225<br/>
226<br/>
227 completionHandler();<br/>
228<br/>
229 }<br/>
230<br/>
231<br/>
232<br/>
233 - (void)handleRemoteNotificationContent:(NSDictionary *)userInfo<br/>
234<br/>
235 {<br/>
236<br/>
237 NSLog(@" iOS 10 after Notificatoin message:\n %@",userInfo);<br/>
238<br/>
239 }<br/>
240<br/>
241 #pragma mark iOS 10 之前 获取通知的信息<br/>
242<br/>
243 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{<br/>
244<br/>
245<br/>
246<br/>
247 //静默推送 显示蓝色Label<br/>
248<br/>
249 [self showLabelWithUserInfo:userInfo color:[UIColor blueColor]];<br/>
250<br/>
251<br/>
252<br/>
253 completionHandler(UIBackgroundFetchResultNewData);<br/>
254<br/>
255 }<br/>
256<br/>
257 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo<br/>
258<br/>
259 {<br/>
260<br/>
261 NSLog(@"iOS 10 before Notification message。\n %@",userInfo);<br/>
262<br/>
263 }<br/>
264<br/>
265<br/>
266<br/>
267<br/>
268<br/>
269 - (void)showLabelWithUserInfo:(NSDictionary *)userInfo color:(UIColor *)color<br/>
270<br/>
271 {<br/>
272<br/>
273 UILabel *label = [UILabel new];<br/>
274<br/>
275 label.backgroundColor = color;<br/>
276<br/>
277 label.frame = CGRectMake(0, 250, [UIScreen mainScreen].bounds.size.width, 300);<br/>
278<br/>
279 label.text = userInfo.description;<br/>
280<br/>
281 label.numberOfLines = 0;<br/>
282<br/>
283 [[UIApplication sharedApplication].keyWindow addSubview:label];<br/>
284<br/>
285 }<br/>
286<br/>
287<br/>
288<br/>
289 </em>
