iOS : PushKit的使用

因为最近项目要作关于voip业务,因此在此作个记录:咱们都知道当应用程序退出到后台时,socket是会断开链接,程序是被挂起的。咱们如今要作的就是在这种状况下直接唤醒APP。node

PushKit背景

PushKit是苹果在ios8苹果新引入的框架,一种新的push通知类型,被称做voip push.该push方式旨在提供区别于普通APNs push的能力,PushKit区别与普通APNS的地方是,它不会弹出通知,而是直接唤醒你的APP,进入回调,也就是说,能够在没点击APP启动的状况下,就运行咱们本身写的代码.ios

PushKit官方介绍:(developer.apple.com/documentati…)

PushKit框架将特定类型的通知(例如VoIP邀请,watchOS复杂性更新和文件提供程序更改通知)直接发送到您的应用程序以进行处理。缓存

PushKit通知与您使用UserNotifications框架处理的通知不一样。具体来讲,PushKit通知从不显示警报,标记应用程序的图标或播放声音。与用户通知相比,它们还具备如下优点:bash

  • 设备仅在收到PushKit通知时才会唤醒,这能够延长电池寿命。
  • 收到PushKit通知后,若是应用程序未运行,系统会自动启动它。相比之下,用户通知没法保证启动您的应用。
  • 系统会为您的应用执行时间(可能在后台)处理PushKit通知。
  • PushKit通知可包含比用户通知更多的数据。

在PushKit中最主要用到的就是PKPushRegistey这个类,首先咱们来分析一下这个类里面的内容:服务器

/* 目标推送类型 */
PK_EXPORT PKPushType const PKPushTypeVoIP NS_AVAILABLE_IOS(8_0);  //VOIP推送
PK_EXPORT PKPushType const PKPushTypeComplication NS_AVAILABLE_IOS(9_0);   //Watch更新
PK_EXPORT PKPushType const PKPushTypeFileProvider NS_AVAILABLE_IOS(11_0);   //文件传输


NS_CLASS_AVAILABLE_IOS(8_0)
@interface PKPushRegistry : NSObject

@property (readwrite,weak,nullable) id<PKPushRegistryDelegate> delegate;    //代理对象

@property (readwrite,copy,nullable) NSSet<PKPushType> *desiredPushTypes;

//获取本地缓存的Token  申请Token执行回调后 这个方法能够直接获取缓存
- (nullable NSData *)pushTokenForType:(PKPushType)type;

//初始化,并设置工做线程
- (instancetype)initWithQueue:(nullable dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;

@end

@protocol PKPushRegistryDelegate <NSObject>

@required

//申请Token更新后回调方法
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)pushCredentials forType:(PKPushType)type;

@optional

//收到推送后执行的回调方法
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type NS_DEPRECATED_IOS(8_0, 11_0);

//同上,收到推送后执行的回调方法,最后的block须要在逻辑处理完成后主动回调
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void(^)(void))completion NS_AVAILABLE_IOS(11_0);

//Token失效时的回调方法
- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(PKPushType)type;

@end

NS_ASSUME_NONNULL_END

复制代码

PushKit证书申请

跟APNs push相似,PushKit的voip push也须要申请证书的,申请证书步骤以下: app

申请.png

按申请步骤操做就能够完成,相信你们都有申请证书的经验,在这里就很少嘴了。 生成证书以后把它下载,双击安装到KeyChain中便可,这里须要在KeyChain里把VoIP证书的密钥导出成.p12格式,发给你的后台人员。(这里关于后台具体使用的证书格式,根据状况而定,咱们一般是把.p12文件通过nodes命令生成.pem文件给后台使用)框架

项目配置

和APNS同样,须要在Project-> Capabilities里打开推送开关和配置后台,Background Modes里把Voice over IP选项打开,同时把Background fetch ,Remote notification选项一块儿打开,并在Build Phases中加入PushKit.framework。socket

VoIP.png

听说Xcode9的Background Modes中是没有Voice over IP这个选项的,(我用的是Xcode10.2,仍是有这个选项的)若是没有的话,能够手动在info.plist文件中加入,在Required background modes里面添加一项 App provides Voice over IP services。ide

简单代码实现

在AppDelagate中须要导入PushKit框架#import <PushKit/PushKit.h> 注册PushKit,注意PushKit要ios8 及之后才可使用, 添加代理PKPushRegistryDelegate测试

if (CurrentSystemVersion.floatValue >= 8.0) {
    PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:nil];
    pushRegistry.delegate = self;
    pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
    }
复制代码

实现获取token的代理方法:

- (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同样,须要去掉<>和空格。

作接收到推送的处理

// iOS 8.0~11.0
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
    
    NSLog(@"收到push");
    
    NSDictionary *dic=payload.dictionaryPayload[@"aps"];
    UIUserNotificationType theType = [UIApplication sharedApplication].currentUserNotificationSettings.types;
    if (theType == UIUserNotificationTypeNone){
         UIUserNotificationSettings *userNotifySetting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
         [[UIApplication sharedApplication] registerUserNotificationSettings:userNotifySetting];
        }
    UILocalNotification *backgroudMsg = [[UILocalNotification alloc] init];
    backgroudMsg.timeZone = [NSTimeZone defaultTimeZone];
    backgroudMsg.alertBody= [dic  objectForKey:@"alert" ];
    backgroudMsg.soundName = [dic objectForKey:@"sound"];
    [[UIApplication sharedApplication] presentLocalNotificationNow:backgroudMsg];
    
}
复制代码

查看PKPushRegistry.h的文件,在iOS8.0~iOS11.0是使用上面这个代理方法来实现唤醒后的操做,但在iOS11.0以后,系统也提供了另一个方法:

//iOS 11.0以后
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void(^)(void))completion
复制代码

若是一切正常,就算程序杀掉进程,重启,退到后台,服务器推送过来的消息都会走这个代理方法,在这里为了能看到推送的内容,这里我是把接收到的内容生成一个本地的推送发出来了,而且播放声音,实际上在这个方法里面应该处理唤醒APP以后的操做。

推送测试

在这里我在作推送测试的时候使用的是Easy APNs Provider这个应用,使用起来仍是很方便的。 附上下载地址

1.首先要添加所要发送的Token值,这里有三种添加方式:

添加Token

2.而后并选择以前建立好的voip_services.cer证书,

3.链接至服务器,Debug模式选择sandbox,Release模式选择push,

链接至服务器.png
以后点击“链接至”按钮,查看是否链接成功。
成功

4.设置发送的内容(推送负载)

5.点击“发送推送”。

Easy APNs Provider.png
相关文章
相关标签/搜索