一、iOS推送原理
<p>IOS推送消息是许多IOS应用都具备的功能,最近也在研究这个功能,参考了很多资料终于搞定了,下面就把步骤拿出来分享下:</p>
<p>iOS消息推送的工作机制可以简单的用下图来概括:</p>
<p>Provider是指某个iPhone软件运用的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务器。</p>
<p>上图可以分为三个阶段:</p>
<p>第一阶段:应用程序的服务器把要发送的消息、目的iPhone的标识打包,发给APNS。</p>
<p>第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。 </p>
<p>第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。</p>
<p>从上图我们可以看到:</p>
<p>1、应用程序注册消息推送。</p>
<p>2、iOS从APNS Server获取device token,应用程序接收device token。</p>
<p>3、应用程序将device token发送给PUSH服务端程序。</p>
<p>4、服务端程序向APNS服务发送消息。</p>
<p> 5、APNS服务将消息发送给iPhone应用程序。</p>
<p>无论是iPhone客户端和APNS,还是Provider和APNS,都需要通过证书进行连接。</p>
二、创建推送证书
1、生成CSR文件
<p>到钥匙串的证书颁发机构请求证书</p>
<p>填写你的邮箱和常用名称,并选择保存到硬盘</p>
2、创建推送证书
<p>到要创建推送的App ID </p>
<p>点击右侧的 Create Certificate...,</p>
<p>点击Continue</p>
<p> 选择CSR文件,选择刚才创建的CSR文件即可,点击继续</p>
<p>创建证书完成,点击下载可得到要用到的cer证书</p>
<p>创建推送证书完成,App ID详情页面</p>
<p>双击已经下载的推送证书,到钥匙串中找到证书,可以导出成为.p12文件</p>
<p>此时,推送证书环境已经完成,接下来代码开发即可</p>
三、推送程序开发
//
// AppDelegate.m
// 推送
//
// Created by 泛在吕俊衡 on 2017/6/23.
// Copyright © 2017年 anjohnlv. All rights reserved.
//
#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate ()<UNUserNotificationCenterDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[UIDevice currentDevice].systemVersion floatValue]>=10.0) {
// iOS10以上的
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate=self;
[center requestAuthorizationWithOptions: UNAuthorizationOptionBadge |UNAuthorizationOptionSound |
UNAuthorizationOptionAlert |UNAuthorizationOptionCarPlay completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error == nil) {
NSLog(@"注册成功");
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"%@", settings);
}];
}
else {
NSLog(@"注册失败");
}
}];
} else if([[UIDevice currentDevice].systemVersion floatValue]>=8.0){
//ios8的
[application registerUserNotificationSettings: [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]];
} else {
// iOS8以下
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
}
//注册token
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
//获取到token,token需要提交到服务器
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"token:%@", deviceToken);
}
//获取到token失败
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"tokenError:%@", error.description);
}
//ios6-10接收到信息
-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
NSLog(@"%@", userInfo);
completionHandler(UIBackgroundFetchResultNewData);
}
// 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 前台收到远程通知:%@", 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 收到远程通知:%@", 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(); // 系统要求执行这个方法
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end