PushKit的使用
1、为什么使用PushKit?
iOS10之后,苹果推出了CallKit框架增强VoIP应用的体验,主要表现在3个方面:
- 在锁屏状态下,如果有网络电话呼入,VoIP应用可以打开系统电话应用的待接听界面,告别了原来推送通知的展现方式。
- VoIP应用内发起通话、挂断电话等记录可以体现在系统电话应用的通话记录中。
- 从系统电话应用的通话记录、通讯录或者siri进入VoIP应用,发起通话。
总而言之,我们的VoIP应用拥有了和系统通话应用一样的用户体验。
那么,如何在锁屏状态下,呼出系统应用的待接听界面?如何在app杀死或者后台的情况下,知道有用户呼入?
在iOS8之后,苹果引入新的框架PushKit,一种新的push方式,有别于普通的APNs,它不会弹出通知,而是悄悄的告诉我们的app有推送过来,让app做出相应的处理。iOS10开始,苹果不在支持VoIP应用的后台socket长连接,需要使用苹果推荐的pushkit,降低app耗电。PushKit可以说是“准实时”的,实际上延迟在1s左右。
2、PushKit的使用
2.1、制作VoIP证书
文末的参考文章1都有介绍,这里不再赘述,与APNS类似。概述一下:VoIP证书的制作入口在certificates。该证书只有生产环境下的,但是开发环境下也可使用。App ID不能使用通配ID必须使用指定APP ID并且生成配置文件中选择Push Notifications服务。
2.2、制作php服务端使用的pem文件
VoIP证书安装完成后,在keychain中将证书和证书密钥分别导出.p12格式。具体制作过程见参考文章1或者stackoverflow。
2.3、客户端代码接入
- 在目标target的capabilities->background Modes下打开“Voice over IP”
- 引入PushKit框架
- 在app启动后注册PushKit服务,记得做iOS8之前的版本保护
PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:nil];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
- 在对应的类实现PushKit的代理方法
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type {
NSString * tokenString = [[[[credentials.token description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""] stringByReplacingOccurrencesOfString: @" " withString: @“"];
}
设备从苹果服务器获取到了VoIP token,这个token与APNs是不一样的。app将收到的token传递给push服务器。(流程和APNs类似,但是接受的代理方法和token都是不一样的)
获取到的token也是64位的,与APNs一样,需要去掉<>和空格。
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
// 呼出系统接听界面
// 或者生成本地推送
}
参数payload是一个字典,内容自定义。
上面这个回调,在一切正常的情况下, 在手机重启、应用被系统回收、手动kill程序的情况下, 依然能够被触发, 且可以有一段时间(大概10秒左右, 可能有时会比10秒少一点)用来执行自己的代码。
2.4、php服务端推送测试
php的测试代码见参考文章2,这里记录一下几个点:
- deviceToken:开发环境和生产环境的token不一样,同一个证书可以用于开发环境也可以用于生产环境。
- passphrase:pem文件制作时的密码,也可以不是用密码。
- 开发环境
ssl://gateway.sandbox.push.apple.com:2195
,生产环境去掉其中的sandbox
; - 执行php文件的时候出现错误:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in <Users/.../file.php> on line 30
。
原因:macOS sierra 系统下php的版本引起的语法问题。
处理方法如图:
3、其他
- 使用第三方平台
(1) 目前支持pushkit的第三方平台有zeropush,但是zeropush在一年前加入了fabric的twitter开发包,可是我好像找不到zeropush这个功能了,伤脑筋。如何使用zeropush集成pushkit功能:https://zeropush.com/guide/guide-to-pushkit-and-voip
(2) sinch好像也是支持pushkit的第三方平台,暂时没研究。使用教程:https://github.com/sinch/ios-pushkit-tutorial - mac上的推送测试工具:pushMeBaby
别人踩过的坑:https://my.oschina.net/u/1244672/blog/603024 - pushKit与APNs的比较
- iOS 8 pushkit使用总结(oc版本+java服务器测试)
- Example of iOS VoIP Notification / iOS VoIP Notification实例(swift版本+php服务器测试)
- 官方文档
- iOS 8之前socket长连接
- 该博主写了几篇pushkit API解释的文章