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
}];
}