最近,iOS 版微信完成版本更新,其中有一项全新功能备受用户关注:语音通话使用弹窗快捷接听。目前这一功能正在逐步覆盖中,部分 iOS 用户已经可以先行一步体验到更加便捷的语音通话操作了。
简单来说,此前当你的好友给你拨打微信语音通话时,会弹出“朋友邀请你语音通话”的弹窗通知,无论选择接听还是挂断,你都需要先解锁手机,打开微信客户端完成后续动作。
相信很多用户都有类似经历,看到弹窗、解锁手机、等待信息收取,然后就错过了语音电话。
而在开启“语音通话使用弹窗快捷接听”功能后,微信语音也能像普通电话一样接听。当好友微信来电,在灵动岛界面就会显示好友昵称,提供接受和拒绝两个选项;在接起电话后,也能像系统电话一样切换外放、静音、挂断。没有灵动岛设计的机型,则会在上方弹出卡片,同样具备这些功能。相比此前,这项功能给用户带来了极大的便利。
根据微信官方客服回复,这项功能优化并不是传统的 CallKit 框架,而是基于 LiveCommunicationKit 框架实现。相比于 CallKit 框架,LiveCommunicationKit 不会在 iOS 系统通讯录中留下通话记录,也不会全屏显示来电者信息,更加注重用户隐私保护。
现在,网易云信呼叫组件也具备了这样的能力,帮助开发者优化终端用户的通话体验。接下来我们就来看看具体如何实现?
呼叫方发起呼叫需求,网易云信服务器将呼叫信息通过 PushKit 推送给接听方,接听方选择接听或挂断后,将信息传递给云信呼叫组件,整体实现时序图如下。
实现流程
一、实现 PushKit 推送
1.在系统中注册 PushKit。
Objective-C//这边推荐使用子队列,防止可能出现系统异常情况
self.pushRegistry = [[PKPushRegistry alloc]
initWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
self.pushRegistry.delegate = self;
self.pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
2. 在网易云信配置 PushKit 证书。
Objective-CNIMSDKOption *option = [NIMSDKOption optionWithAppKey:kAppKey];
option.apnsCername = @"请输入远程推送证书名字";
if (@available(iOS 17.4, *)) {
option.pkCername = @"请输入您的VoIP推送证书";
}
option.v2 = YES;
[NIMSDK.sharedSDK registerWithOptionV2:option v2Option:nil];
3. 将 PushKit token 传给网易云信。
Objective-C- (void)pushRegistry:(PKPushRegistry *)registry
didUpdatePushCredentials:(PKPushCredentials *)credentials
forType:(PKPushType)type {
if ([credentials.token length] == 0) {
NSLog(@"voip token NULL");
return;
}
//Pushkit token 传给云信
[[NIMSDK sharedSDK] updatePushKitToken:credentials.token];
}
二、解析并弹出接听提示 UI
App 层接受 PushKit 消息后将消息传给 NERtcCallKit,由呼叫组件解析字段,并弹出相应的 UI。Objective-C- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion{
NSDictionary *dictionaryPayload = payload.dictionaryPayload;
//判断是否是云信发的payload
if (![dictionaryPayload objectForKey:@"nim"]) {
NSLog(@"not found nim payload");
return;
}
if (@available(iOS 17.4, *)) {
//传入payload
NECallSystemIncomingCallParam *param = [[NECallSystemIncomingCallParam alloc] init];
param.payload = dictionaryPayload;
param.ringtoneName = @"avchat_ring.mp3";
//若展示信息无法满足需求,可以自定义展示信息
NECallSystemIncomingCustomCallParam *customPayload = [[NECallSystemIncomingCustomCallParam alloc] init];
customPayload.displayContent = @"自定义展示信息";
param.customPayload = customPayload;
//弹出系统接听UI
[[NECallEngine sharedInstance] reportIncomingCallWithParam:param acceptCompletion:^(NSError * _Nullable error, NECallInfo * _Nullable callInfo) {
if (error) {
NSLog(@"accept failed %@", error);
}
// update 业务UI
} hangupCompletion:^(NSError * _Nullable error) {
if (error) {
NSLog(@"hangup failed %@", error);
}
//update 业务UI
} muteCompletion:^(NSError * _Nullable error, BOOL mute) {
if (error) {
NSLog(@"mute failed %@", error);
}
// update 业务UI
}];
}
completion();
}
干货内容,欢迎来✉!
《网易数智年度技术精选合集》
《泛娱乐出海白皮书》
《全球即时通讯(IM)PaaS市场洞察白皮书》
前来讨论更多,戳名片👇