ios 实现 voip 功能 使用 PushKit CallKit

VOIP说是一种网络电话服务,其实质是一种特殊的长连接,使用它每个网络电话类APP不需要自己单独进行保活维护,在进行通话请求时,只需要发送一条VOIP推送,VOIP推送会将应用程序拉起,之后由应用程序处理通讯逻辑。VOIP也是Push的一种,只是其是一种特殊的Push,普通的Push当应用被杀死后可以收到,但是用户点击Push消息前应用程序是不会被激活的,VOIP则不然,可以直接激活应用。

-(void)testVOIP{
    //注册VOIP通知
    PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
    pushRegistry.delegate = self;
    pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
    
    NSLog(@"拿到token~~~token~~~%@~~~~~~~%@",credentials.token,credentials.type);
}

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
    
     NSLog(@"收到---voip推送 ----实现客户端逻辑~~~%@",type);
    
}

 

Callket 实现

@property (strong, nonatomic) NSUUID           *uuid;           //主动发起CallKit的Action的时候,需要使用
@property (strong, nonatomic) CXProvider       *provider;       //调用系统来电UI的主要变量
@property (strong, nonatomic) CXCallController *callController; //代码调用CallKit中Action的变量
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type{
    
    
    self.callController = [[CXCallController alloc] init];
    self.provider       = [[CXProvider alloc] initWithConfiguration:[self providerConfiguration]];
    [self.provider setDelegate:self queue:nil];//queue为nil即为在主队列

    
    CXTransaction *ction = [[CXTransaction alloc] init];
    
    
    //使用CXProvider触发一个来电,其中主要内容都包含在CXCallUpdate中
    CXCallUpdate *callUpdate = [[CXCallUpdate alloc] init];
    //不设置CXCallUpdate的remoteHandle的话,在通话记录中就不能启动到主程序
    //这个remoteHandle的话,还是必须要是设置的一个属性,几处地方调用主程序的时候会用到handle中的value值
    //PS:这个value值可以设置成其他的字符串,也可以是几个字符串拼接的,看需求可以灵活使用,比如联系人的ID
    callUpdate.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypeGeneric value:@"123456789"];
    //设置remoteHandle的hasVideo属性为YES,即会沉淀为视频通话的通话记录,并且点击通话记录会触发相应的视频通话的方法
    //不过来电的UI仍然与语音相差不大,只是语音通话的文字提示更改为视频通话,没有显示视频的画面
    callUpdate.hasVideo            = NO;
    //TODO::下面几个没有具体研究效果
    callUpdate.supportsDTMF        = NO;
    callUpdate.supportsHolding     = NO;
    callUpdate.supportsGrouping    = NO;
    callUpdate.supportsUngrouping  = NO;
    //'localizedCallerName'属性就是现实来电人的描述了,比如昵称或者ID等
    callUpdate.localizedCallerName = @"小周周";
    //这里执行AVAudioSession的设置方法,避免了使用引擎的失败,不设置会出现无声的现象
    
    //TODO::这里这个在之前测试的时候的确不写会有问题,也是查资料查到的,现在不知道什么情况,没有进行测试
//    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    
    //调用系统来电,正常就会调出系统来电的UI
    [self.provider reportNewIncomingCallWithUUID:ction.UUID update:callUpdate completion:^(NSError * _Nullable error) {
        //执行完成的block
      
    }];
}