iOS 远程推送学习与总结
远程推送解决了当APP处于终止状态,client与sever断开时的通信困境,APNS是苹果所提供的一套服务。远程推送要求设备必须保持联网状态,若设备处于断网状态,这APNS将为其保留最后一条推送消息,若设备长时间处于断网状态,则将不再为其保留推送消息。
一、APNS的推送机制
推送机制如下图所示:
Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。
上图可以分为三个阶段:
第一阶段:应用程序的服务器端把要发送的消息、目的、iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
APNS推送通知的详细工作流程
下面这张图是说明APNS推送通知的详细工作流程:
根据图片我们可以概括一下:
1、应用程序注册APNS消息推送。
2、iOS从APNS Server获取devicetoken,应用程序接收device token。
3、应用程序将device token发送给程序的PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。
准备工作
首先要有一台苹果的设备,模拟器是不支持推送的,所以你需要一台iphone,ipod touch或者ipad。
我们的客户端与苹果服务器之间和我们自己的服务器与苹果服务器之间都需要证书来进行链接。下面我们来开始进入证书的制作过程。
二.创建本地请求证书文件--CertificateSigningRequest(也就是CSR)
1、打开钥匙串-证书助理-从证书颁发机构请求证书
2、填写邮箱和名称(无特殊要求可随意填写)-选择存储到磁盘
3、选择继续-保存至桌面,这时桌面上会有一个CertificateSigningRequest.certSigningRequest的请求文件,也就是我们说的CSR文件。在我们生成CSR文件的同时,会在钥匙串访问中生成一对秘钥,名称为刚才我们填写的常用名(此文件可长期重复使用,只作为本机器的一个识别作用)
三.开发证书和发布证书,进入苹果开发者网站:https://developer.apple.com/
1、依次选择Account(跳转到登录界面) -- Certificates, Identifiers &Profiles -- Certificates
2、选择当前要设置通知的APP IDs(此处以新建一个APP IDs为例),选择上图右上角"+"号创建一个APPID
3、填写name以及Bundle ID(Bundle ID需要与Xcode里项目Bundle ID一致)
4、勾选push notification 并完成提交
5、找到刚创建好的APP IDs,可以看到下面的通知选项处提示(为黄色)Configurable,表示证书还没配置,点击Edit进行编辑
6、这里看到推送证书分为2个版本,一个开发模式,一个生产模式,即我们在开发测试时使用开发模式证书,发布上线后采用生产模式证书,两个都要创建(本次只作开发模式演示,当然创建生产版证书的步骤也是一样的)
7、Choose File选择最开始创建在桌面的Request文件(CSR文件)
8、创建证书OK后 下载到本地
9、开发版和生产版证书都创建好后,此时这里已经都是启用状态了(为绿色)
10、打开下载好的开发模式证书,可以在钥匙串中看到,右键将该证书导出成.p12格式文件
证书密码可根据需求填写(可为空):
下面要输入你电脑管理员密码:
导出的.p12格式文件如下:
接下来终端进入该文件目录下使用命令把此文件转成pem格式(因为后端需要上传pem格式文件验证)
四、推送证书创建好了,接下来回到苹果开发者官网,按以下步骤创建Provisioning Profile文件
1、选择Provisioning Profile
2、选择该项目APP ID
3、勾选测试授权的设备
4、注意右侧的状态要Active才是可用的,若是invalid则需要Edit并重新下载一次
5、到此我们开发模式所需要的证书和描述文件都创建好了
五、进入第三方推送后台,登陆验证开发者身份,并创建一个推送应用
1、选择iOS,并上传开发版证书(当然如果你同时也创建了生产版证书也可以上传验证)
2、保存后,我们要用到的便是右侧的API KEY
六、项目里配置第三方推送
1、下载最新的第三方推送SDK,导入到工程,SDK需要以下库:Foundation.framework、CoreTelephony.framework、libz.dylib、SystemConfiguration.framework,请在工程中添加
2、再次强调要修改Bundle ID与之前创建证书时所填Bundle ID一致
3、在AppDelegate
中导入BPush.h
,并在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法中添加如下代码,并修改apiKey为刚才创建应用所得apiKey,推送模式为开发模式
4、添加3个方法
七.配置证书测试
1、双击之前创建好的的TestPush_ProvisioningDev.mobileprovision描述文件,并在Xcode-Targets配置好证书。这一步编译的时候容易failed,通常检查之前配置的provisioning文件状态是否为Active,若状态为Invalid,则需删除本地provisioning文件,clean,再次重新下载配置
2、真机运行成功后,可看到控制端打印出获得到Device Token,以及APP提示时候开启通知
八、创建通知测试
1、在第三方推送后台创建一个通知测试,请选择开发模式
2、现在我们就接收到刚才创建的通知了
九、iOS10 及以前系统的推送注册比较
iOS10正式版发布之后,网上各种适配XCode8以及iOS10的文章满天飞。但对于iOS10适配远程推送的文章却不多。iOS10对于推送的修改还是非常大的,新增了UserNotifications Framework。
1、Capabilities中打开Push Notifications 开关
在XCode7中这里的开关不打卡,推送也是可以正常使用的,但是在XCode8中,这里的开关必须要打开,不然会报错:
Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“aps-environment”的授权字符串" UserInfo={NSLocalizedDescription=未找到应用程序的“aps-environment”的授权字符串}
打开后会生成entitlements文件,在这里可以设置APS Environment
2、注册远程推送通知(获取deviceToken----包含设备信息和应用信息的一串编码)
首先引入UserNotifications Framework,
import <UserNotifications/UserNotifications.h>
if
(IOS_VERSION >= 10.0) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(
BOOL
granted, NSError * _Nullable error) {
if
(!error) {
DLog(@
"request authorization succeeded!"
);
}
}];
}
else
{
if
([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
//IOS8,创建UIUserNotificationSettings,并设置消息的显示类类型
UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:nil];
[application registerUserNotificationSettings:notiSettings];
}
}
3、UNUserNotificationCenterDelegate代理实现
在iOS10中处理推送消息需要实现UNUserNotificationCenterDelegate的两个方法:
其中第一个方法为App在前台的时候收到推送执行的回调方法,第二个为App在后台的时候,点击推送信息,进入App后执行的 回调方法。
以前处理推送,信息是在userInfo参数中,而新方法中表明上看并没有这个参数,其实我们一样可以获取到userInfo,如下:
/// App在前台时候回调
- (
void
)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(
void
(^)(UNNotificationPresentationOptions))completionHandler {
NSDictionary *userInfo = notification.request.content.userInfo;
[self handleRemoteNotificationForcegroundWithUserInfo:userInfo];
}
/// App在后台时候点击推送调用
- (
void
)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(
void
(^)())completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
[self handleRemoteNotificationBackgroundWithUserInfo:userInfo];
}