实现首次通话
适用于 iOS 的 CallPlus 可在您的应用程序中为用户之间的一对一和多人通信提供语音和视频通话能力。
CallPlus 支持 一对一通话 和 多人通话。按照下面的指南使用 Objective-C 从头开始实现一对一通话和多人通话。
环境要求
适用于 iOS 的 CallPlus SDK 的最低要求如下。
- iOS 10.0 及更高版本
- Xcode 9.0 或以上版本
前置条件
-
注册开发者账 号。注册成功后,控制台会默认自动创建您的首个应用,默认生成开发环境下的 App Key,使用国内数据中心。
-
获取开发环境的应用 App Key。如不使用默认应用,请参考 如何创建应用,并获取对应环境 App Key 和 App Secret。
注意
每个应用具有两个不同的 App Key,分别对应开发环境与生产环境,两个环境之间数据隔离。在您的应用正式上线前,可切换到使用生产环境的 App Key,以便上线前进行测试和最终发布。
-
完成开通音视频服务。您需要开通音视频通话服务。
快速上手
您可以通过集成 CallPlus for iOS 进行一对一通话,或多人通话。
步骤 1 创建项目
打开 Xcode 并创建一个新项目。
步骤 2 集成 SDK
您可以使用 CocoaPods 安装 RongCallPlusLib,也可以通过下载对应的 Framework 文件手动导入到工程中。
CocoaPods
-
在您的项目目录中创建一个名为
Podfile
的文件,如下所示。touch Podfile
-
在 Xcode 中将
RongCallPlusLib
框架添加到你的Podfile
中,如下所示。# Podfile
pod 'RongCallPlusLib' -
运行以下命令,通过 CocoaPods 安装
RongCallPlusLib
框架。$ pod install
- 如果出现找不到相关版本的问题,可先执行 pod repo update ,再执行 pod install。
-
上一步完成后,会自动导入指定版本的融云 SDK,CocoaPods 会在您的工程根目录下生成一个 xcworkspace 文件,只需通过 XCode 打开该文件即可加载工程。
Framework
在导入 SDK 前,您需要前往 融云官网 SDK 下载页面,将 CallPlus for iOS SDK 下载到本地。
- 导入 RongIMLibCore.xcframework,并将 Embed 设置为 Embed & Sign 。
- 导入 RongRTCLib.xcframework,并将 Embed 设置为 Embed & Sign 。
- 导入 RongCallPlusLib.xcframework,并将 Embed 设置为 Embed & Sign 。
步骤 3 工程配置
- 您的用户需要授予您的应用访问设备上的摄像头和麦克风的权限,请在工程的 info.plist 中添加如下键值:
- Privacy - Microphone Usage Description
- Privacy - Camera Usage Description
- 如果需要支持后台保持通话,请将工程中 Target -> Signing & Capabilities -> Background Modes 如下内容勾选:
- Audio, AirPlay, and Picture in Picture
- 如果需要支持远程推送服务,请将工程中 Target -> Signing & Capabilities -> Background Modes 如下内容勾选:
- Remote notifications
步骤 4 设置推送
您可以通过远程通知接收有关一对一来电的推送通知。要使用远程通知接收通知,请转到 Xcode 项目的 Signing & Capabilities 并启用 Remote notifications。应用程序需要支持 APNs 推送,详见 APNs 推送集成。
暂不支持使用 VoIP 通知接收通知。
步骤 5 使用 App Key 初始化
RongCallPlusLib
是基于 RongIMLibCore
作为信令通道的,要在您的应用程序中集成和运行 ,您需要先对 IMLibCore
进行初始化。请使用您在融云申请的 App Key 初始化 RCCoreClient
实例。如果不换 App Key,在整个应用生命周期中,初始化一次即可。建议调用位置放在应用启动位置处,或在音视频功能模块的加载位置处。
NSString *appKey = @"Your_AppKey"; // example: bos9p5rlcm2ba
RCInitOption *initOption = nil;
[[RCCoreClient sharedCoreClient] initWithAppKey:appKey option:initOption];
初始化配置(RCInitOption
)中封装了区域码(RCAreaCode),导航服务地址(naviServer
)、文件服务地址(fileServer
)、数据统计服务地址(statisticServer
)配置。不作设置表示全部使用默认配置。SDK 默认连接北京数据中心。
如果 App Key 不属于中国(北京)数据中心,则必须传入有效的初始化配置。
注意
每个融云应用提供开发环境与生产环境,分别使用不同的 App Key,两个环境之间数据隔离。只要客户端应用使用同一个环境的 App Key,用户可以跨所有平台相互通信。
步骤 6 添加通话所需代理
CallPlus for iOS 提供了 RCCallPlusEventDelegate
与 RCCallPlusResultDelegate
两个代理来处理通话相关事件。
RCCallPlusEventDelegate
用于处理来电事件、通话状态、通话记录等事件相关回调。RCCallPlusResultDelegate
用于处理 API 异步结果回调监听。该监听可以接收 startCallWithUserIds:callType:mediaType:、acceptWithCallId:、hangup 等方法的结果回调。
注意
如果未设置
RCCallPlusEventDelegate
代理,则用户无法接收didReceivedCall
回调事件。请务必在下文连接(connectWithToken
)步骤之前使用setCallEventDelegate
注册监听,否则用户在未连接的情况下无法通过离线推送接收来电通知。
-
设置
RCCallPlusEventDelegate
和RCCallPlusResultDelegate
。// 初始化相关配置
- (void)initConfig {
/// 设置事件代理
[[RCCallPlusClient sharedInstance] setCallEventDelegate:self];
/// 响应api代理
[[RCCallPlusClient sharedInstance] setCallResultDelegate:self];
} -
实现
RCCallPlusEventDelegate
接收来电的代理方法。#pragma mark - RCCallPlusEventDelegate
/// 接收到呼入会话通知
/// @param session 会话
- (void)didReceivedCall:(RCCallPlusSession *)session {
/// 被呼叫端,通过该方法接收到通话
} -
实现
RCCallPlusResultDelegate
开始通话与接听来电的异步回调代理方法。#pragma mark - RCCallPlusResultDelegate
/// 开始通话回调
/// @param code 状态码, 0:成功 非0:失败
/// @param callId 通话id
/// @param busylineUsers 忙线用户列表
- (void)didStartCallResultCode:(RCCallPlusCode)code
callId:(nullable NSString *)callId
busylineUsers:(nullable NSArray<RCCallPlusUser *> *)busylineUsers {
if (code == RCCallPlusCode_Success) {
//发起通话,本端回调
}
}
/// 接受通话回调
/// @param code 状态码, 0:成功 非0:失败
/// @param callId 通话id
- (void)didAcceptCallResultCode:(RCCallPlusCode)code callId:(NSString *)callId {
}
步 骤 7 获取用户 Token
用户身份令牌(Token)与用户 ID 对应,是应用程序用户在融云的唯一身份标识。应用客户端在使用融云服务前必须与融云建立 IM 连接,连接时必须传入 Token。
在体验和调试阶段,我们将使用控制台「北极星」开发者工具箱,从 API 调试页面调用 获取 Token 接口,获取到 userId 为 1 的用户的 Token。提交后,可在返回正文中取得 Token 字符串。
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"code":200,"userId":"1","token":"gxld6GHx3t1eDxof1qtxxYrQcjkbhl1V@sgyu.cn.example.com;sgyu.cn.example.com"}
融云的客户端 SDK 不提供获取 token 的 API。在实际业务运行过程中,调用融云 Server API
/user/getToken.json
,传入您的应用分配的用户标识(userId)申请 Token。详见 Server API 文档 注册用户。
步骤 8 连接融云服务器
要拨打和接听一对一对呼叫或开始多人呼叫,必须先通过 RCCoreClient
的 connectWithToken
方法连接融云服务器,传入用户身份令牌(Token),向融云服务器验证用户身份。
获取 Token 以后,可以调用 connectWithToken
方法连接到融云服务器。
// 连接 IM 服务
[[RCCoreClient sharedCoreClient] connectWithToken:@"从您服务器端获取的 Token"
dbOpened:^(RCDBErrorCode code) {}
success:^(NSString *userId) {}
error:^(RCConnectErrorCode status) {}];
进行一对一通话
CallPlus for iOS SDK 提供了仅限两位用户通话的一对一通话类型 RCCallPlusSingleType
。发起一对一类型通话时,只允许传入一个被叫用户 ID,仅在被叫接听成功后才会建立通话。融云会在被叫接听成功后开始计时。
本节中将简单介绍如何发起一对一通话,如何接收来电,以及通话接通后双方通话界面如何显示。
步骤 9 发起呼叫
注意
从 CallPlus 2.X 开始,新增 startCallWithUserIds:callType:mediaType:pushConfig:extra: 方法,支持在发起呼叫时通过配置推送属性自定义远程推送标题等属性。支持携带自定义数据。如不需要配置推送属性,可以使用 startCallWithUserIds:callType:mediaType:。
使用 RCCallPlusClient
的 startCallWithUserIds:callType:mediaType:pushConfig:extra: 方法发起一对一通话。方法调用后,SDK 内部会以异步方式执行。在主叫与被叫端触发以下回调:
- 本地主叫用户通过 RCCallPlusResultDelegate 的 didStartCallResultCode:callId:busylineUsers: 回调来获取方法的执行结果。
- 远端被叫用户通过 RCCallPlusEventDelegate 的 didReceivedCall:extra: 回调获取来电通知。
如果远端被叫用户接听通话,本地主叫用户将通过 RCCallPlusEventDelegate 的 didRemoteUserStateChanged:userId:reason:userStatus: 回调获取到该用户状态变更,其中 RCCallPlusSessionUserState 枚举为 RCCallPlusUserStateConnecting
时表示用户已经接听,正在连接中。
/// 开始呼叫动作
- (void)startCallAction {
// 打开摄像头
[[RCCallPlusClient sharedInstance] startCamera];
// 设置本地视图
RCCallPlusVideoView *localView = [RCCallPlusVideoView new];
localView.userId = @"localUserId";
localView.frame = CGRectMake(100, 100, 100, 100);
[self.view addSubview:localView];
[[RCCallPlusClient sharedInstance] setVideoView:localView];
// 设置远端视图
RCCallPlusRemoteVideoView *remoteView = [RCCallPlusRemoteVideoView new];
remoteView.frame = CGRectMake(200, 100, 100, 100);
remoteView.userId = @"remoteUserId";
[self.view addSubview:remoteView];
[[RCCallPlusClient sharedInstance] setVideoView:remoteView];
/// 开始呼叫,并携带推送配置
RCCallPlusPushConfig *pushConfig = [[RCCallPlusPushConfig alloc] init];
pushConfig.disablePushTitle = NO;
[[RCCallPlusClient sharedInstance] startCallWithUserIds:@[@"remoteUserId"]
callType:RCCallPlusSingleType
mediaType:RCCallPlusAudioVideoMediaType
pushConfig:pushConfig
extra:@"extraString"];
}
/// 开始通话回调
/// @param code 状态码, 0:成功 非0:失败
/// @param callId 通话id
/// @param busylineUsers 忙线用户列表
- (void)didStartCallResultCode:(RCCallPlusCode)code
callId:(nullable NSString *)callId
busylineUsers:(nullable NSArray<RCCallPlusUser *> *)busylineUsers {
if (code == RCCallPlusCode_Success) {
}
}
步骤 10 接听
重要
非兼容性变更:从 CallPlus 2.X 开始,不再提供 CallPlus 1.X 的
didReceivedCall:
回调方法。请改为使用携带 extra 字段的 didReceivedCall:extra: 方法。
被呼叫端通过协议 RCCallPlusEventDelegate
的 didReceivedCall:extra: 方法接收通话,然后使用 acceptWithCallId: 方法接听来电。
/// 接收到呼入会话通知
/// @param session 会话
- (void)didReceivedCall:(RCCallPlusSession *)session {
// 接收到来电,记录 session
self.callSession = session;
// 判断通话类型决定是否开启摄像头并渲染视图
if (session.mediaType == RCCallPlusAudioVideoMediaType) {
[[RCCallPlusClient sharedInstance] startCamera];
// 被叫端设置本地视图
RCCallPlusVideoView *localView = [RCCallPlusVideoView new];
localView.userId = @"localUserId";
localView.frame = CGRectMake(100, 100, 100, 100);
[self.view addSubview:localView];
[[RCCallPlusClient sharedInstance] setVideoView:localView];
// 被叫端设置远端视图
RCCallPlusRemoteVideoView *remoteView = [RCCallPlusRemoteVideoView new];
remoteView.frame = CGRectMake(200, 100, 100, 100);
remoteView.userId = @"remoteUserId";
[self.view addSubview:remoteView];
[[RCCallPlusClient sharedInstance] setVideoView:remoteView];
}
}
/// 接听动作
- (void)acceptAction {
[[RCCallPlusClient sharedInstance] acceptWithCallId:self.callSession.callId];
}
/// 接受通话回调
/// @param code 状态码, 0:成功 非0:失败
/// @param callId 通话id
- (void)didAcceptCallResultCode:(RCCallPlusCode)code callId:(NSString *)callId {
NSLog(@"didAcceptCallResultCode:%@",@(code));
}
应用未启动,被叫方通过远程通知接收来电。点击收到的推送通知后启动 App,在设置
RCCallPlusEventDelegate
代理并连接 IM 成功后,还是通过 didReceivedCall:extra: 接收到通话。
进行多人通话
CallPlus for iOS SDK 提供了支持多人呼叫的通话类型 RCCallPlusGroupType
。发起多人通话与一对一通话使用相同的方法,但通话类型必须指定为 RCCallPlusGroupType
。多人通话一旦发起成功,融云即开始计时计费。
下文仅描述了发起多人通话的方法。在实际项目中,我们建议您先按照一对一通话 实现完整的通话流程,再按照多人通话补充实现与一对一通话有差异的步骤。
在一对一通话过程中可以邀请用户加入通话。一旦邀请成功,通话类型会自动转为多人通话。详见多人通话。
步骤 11 发起多人通话
使用 startCallWithUserIds:callType:mediaType: 方法,callType
参数必须为 RCCallPlusGroupType
多人通话类型。
- (void)startGroupCall {
// 开始呼叫
[[RCCallPlusClient sharedInstance] startCallWithUserIds:@[@"userId1",@"userId2"]
callType:RCCallPlusGroupType
mediaType:RCCallPlusAudioVideoMediaType];
}
注意
有关在您的应用程序中构建语音和视频通话功能的详细指南,请参阅完整的 一对一通话和多人通话 文档。我们建议您先按照一对一通话实现完整的通话流程,再按照多人通话补充实现与一对一通话有差异的步骤。