【关注 融云全球互联网通信云】2016 年,苹果 iOS10 发布了 CallKit 框架,使第三方 VoIP 类型语音通话类 APP,可以拥有与手机系统一样的来电体验——直接显示在锁屏界面,并且通话过程中,APP 的音视频权限和运营商电话一样,不会被其他应用打断。如何实现?

2018 年,苹果 APP 审核中心通过邮件告知开发者:在中国大陆地区上架的 APP 不可使用 Callkit。

并且,从 iOS13 开始,基于安全角度考虑,苹果要求在使用 VoIP 推送时必须配合 CallKit 框架使用,否则 iOS 系统将在收到 VoIP 推送后杀掉 APP 进程,就像没有收到 VoIP 推送一样。

苹果 CallKit 框架无法在国内上架使用,我们也就无法在国内使用 VoIP 推送功能在手机后台唤醒息屏了的 APP。

但是,对于在没有上架限制地区投放的应用,苹果 CallKit 依然是提升用户使用体验的重要手段。

当下,出海浪潮浩浩荡荡,融云作为布局全球的通信云服务商,为全球开发者提供安全、可靠的互联网通信云服务。上架海外应用商店的 APP,在使用融云 SDK 获得稳定通信能力后集成苹果 CallKit,可以大幅提高用户体验和使用便捷性。

本文分享通过苹果 CallKit 框架实现来电、接听、挂断、呼叫等通话场景的流程。

苹果 CallKit 效果

在 iPhone 锁屏状态下 APP 来电时,通过苹果 CallKit 可以像 iOS 原生电话来电一样展现全屏的来电及接听界面,VoIP APP 与系统 Call 有着相同的通话优先级别,而且在通讯录中的拔号记录、Siri 唤起、勿扰模式等都可以得到很好的支持。


(苹果 CallKit 框架下的 APP 来电界面)


(苹果 CallKit 框架下的 APP 接听界面)

下图简略描述了原生 APP、第三方 APP 在 CallKit 框架下的关系。CallKit 在系统中提供了一种独有的服务,在需要的时刻,原生或者第三方 APP 通过 CallKit 提供的 API 向系统请求诸如来电、拔出等展现服务,由 Call Service 统一安排调度这些请求以达成统一的交互响应。


(原生和第三方 APP 在 CallKit 框架下的关系)

如何使用苹果 CallKit

苹果 CallKit 提供了统一的语音通话 UI 及与该 UI 交互的 API,但实际的通话链路监听、搭建和管理还需要沿用 APP 原有的实现思路。下面,我们分享来电、拔出等场景下 APP 与 CallKit 的交互流程。

Prepare

① 创建 CXProvider,指定 CallKit 展现 UI 中的 APP 名称和图标、通话数量、来电铃声等 Configuration

② 实现 CXProviderDelegate 协议,以接收来自 Call Service 发来的更新状态,例如用户点击了接听或者挂断等动作,决定网络链路的处理动作;还有 AudioSession 的激活状态,决定 Audio 播放录制的启动关闭时机

③ 创建 CXCallController,使 APP 可以发送更新状态给 Call Service,例如用户拔出电话或者对方挂断电话等状态

④ 如果需锁屏界面及 APP 未启动状态下显示来电界面,要搭建 PushKit 通路,与 APNS 差不多,只是 APP 端处理方式有些不同。


(准备工作)

Incoming Call

① APP 前台时收到来自网络 Server 端的连接请求,或者 APP 后台时收到来自网络 Push Server 的 PushEvent

② APP 收到连接请求或者 Push 消息后,创建 CXCallUpdate 对象,指定此次来电的号码等属性

③ 将上面创建的 CXCallUpdate 对象通过 CXProvider 的 reportNewIncomingCall WithUUID 方法报告给 iOS 系统

④ Call Service 收到新的来电请求后根据当前的状态,展现原生来电 UI


(来电场景实现流程)

Answer Call

① 用户点击来电界面上的接听按钮

② Call Service 通过 CXProvider 的 Delegate 协议 performAnswerCallAction 方法告知 APP

③ APP 将接听命令通过网络传给对端,开始实际音频数据传输,进行通话


(接听场景实现流程)

End Call

① 用户点击 APP UI 中的挂断按钮

② 创建 CXEndCallAction 对象,指定此次通话的 UUID 属性

③ 创建 CXTransaction,将 Action 指定给它

④ 通过 CXCallController,调用 request Transaction 将这个挂断事件通知给 Call Service

⑤ Call Service 通过当前通话状态,通过 CXProvider 将挂断动作通知回给 APP

⑥ 在 CXProviderDelegate 中的 performEnd CallAction 中结束此次通话的网络链路,停止音频录制播放 Loop


(挂断场景实现流程)

Outgoing Call

① 用户通过 APP UI、通话录、Siri 发起一个拔出请求

② 创建 CXHandle 指定拨出的电话号码,创建 CXStartCallAction 并将 CXHandle 指定给它

③ 创建 CXTransaction,将刚刚的 Action 指定给它

④ 通过 CXCallController 调用 request Transaction,将这个拔出事件通知给 Call Service

⑤ Call Service 收到新的拨出请求后根据当前的状态,通过 CXProvider 将拨出动作通知回 APP

⑥ 在 CXProviderDelegate 中的 perform StartCallAction 中开启此次呼叫的网络链路,通过 CXProvider 的 reportOutgoing CallWithUUID 设置呼叫与接通时间,根据链路建立的结果来展现原生呼叫 UI 的状态(呼叫成功或者失败)


(拨出场景实现流程)

苹果 CallKit 开发框架,赋予语音或视频通话应用的开发者诸多便利——

允许开发者将 UI 界面整合在 iPhone 原生的电话 APP 中;

允许开发者将通讯 APP 的功能内建在电话 APP 的“常用联络资讯”以及“通话记录”,方便用户透过原生电话 APP,直接取用这些第三方功能;

允许用户在通知中心直接浏览并回复来电,来电的画面也将整合在 iOS 原生的 UI 里。

总而言之,苹果 CallKit 让 iOS 原本单纯用来打电信电话的“电话”功能,能够结合众多第三方语音通讯软件,具备更完整的数码电话能力。而对融云服务的广大出海开发者来说,集成苹果 CallKit,应用内的 VOIP 通话可以获得系统级的通话效果,极大地提升用户使用体验。


融云RongCloud
82 声望1.2k 粉丝

因为专注,所以专业