通信集成指南 - iOS
简介
本篇文档描述了会议基本功能的实现。在集成时,涉及到 JCEngineManager
、JCRoomModel
和 JCParticipantModel
这三个类。
JCEngineManager
是管理类,包含了会议的所有接口。JCRoomModel
是房间属性的对象类,定义了会议信息的属性,用于 App 界面(以下简称 UI)展示会议的信息。JCParticipantModel
是成员对象,定义了成员信息的属性,用于 UI 展示会议成员的信息。
注:在集成会议功能前,确保已经完成 SDK 的导入和初始化工作。
基本交互
会议中 UI 和后台的交互基本都是异步方式,在 iOS 侧定义了 JCEngineDelegate protocol
,用于 UI 的回调
具体实现如下:
UI 实现
JCEngineDelegate protocol
方法//ViewController添加JCEngineDelegate协议 @interface ConferenceViewController () <JCEngineDelegate> // 加入房间成功的回调 -(void) onJoinRoomSuccess { //todo } // 错误的回调 -(void)onError:(JCEEventReason)eventReason { //todo } // 离开房间的回调 -(void)onLeftRoom:(JCEEventReason)eventReason { //todo } // 成员状态变化的回调 -(void)onParticipantUpdated:(NSString *)userId { //todo }
设置 delegate
//_confManager会议管理对象 JCEngineManager *_confManager = [JCEngineManager sharedManager]; //self为ViewController对象 [_confManager setDelegate:self];
加入会议
开发者需自定义一个字符串作为会议的标识 roomId
,不同的终端加入相同 roomId
的会议,即可加入到同一个会议中。
具体实现如下:
调用加入房间的接口。
//_roomId 会议房间id,是由中文、英文、数字组成的字符串,需自定义。 //_displayName 是在会议中显示的昵称。 int ret = [_confManager joinWithRoomId:_roomId displayName:_displayName]; if (ret == JCEOK) { //如果加入视频,需开启摄像头 [_confManager startCamera]; } else { //UI加入失败的提示 }
该接口为异步接口,调用接口返回 JCEOK 仅表明发起加入会议的请求。加入成功或失败需通过回调函数判断(详见第2步)。
处理会议加入事件的回调。
- 当加入房间成功,则会回调 - (void)onJoinRoomSuccess 事件
加入成功后,可调用接口
getRoomInfo
获取会议信息,然后可以将房间信息更新到 UI。 回调实现如下:- (void)onJoinRoomSuccess { //获取会议信息,JCRoomModel对象包含了会议的基本信息 JCRoomModel *confInfo = [_confManager getRoomInfo]; //房间roomId NSString *roomId = confInfo.roomId; //房间主题 NSString *title = confInfo.title; //获取成员列表 NSArray *participantsArray = confInfo.participants; //遍历成员列表 for (JCParticipantModel *model in participantsArray) { //将所有成员的userId保存到界面定义的数组中 //方便界面更新UITableView这类的容器 [_participantDataSource addObject:model.userId]; } //更新 UI 界面 //todo... }
注:如果终端已经在某个房间中,在离开此房间前,不能加入另一个。
离开房间
离开会议分两种情况:
- 调用离开房间的接口主动离开;
- 因终端断网超时导致离开房间。
调用离开房间的接口主动离开
已加入房间的终端想要离开房间,需调用leave
接口来退出房间。
具体实现如下:
调用离开房间的接口。
[_confManager leave];
该接口为异步接口,调用接口时并没有真正离开房间。离开房间成功通过回调函数判断(详见第2步)。
处理离开房间事件的回调。
- 当 UI 则会回调 - (void)onLeftRoom 事件,表明离开房间成功。
- UI 销毁房间界面。
回调实现如下:
- (void) onLeftRoom { //如果加入会议时打开了摄像头,需关闭摄像头 [_confManager stopCamera]; //销毁会议界面 [self dismissViewControllerAnimated:YES completion:nil]; }
因断网离开房间
已经加入房间的终端,如果发生断网并且持续时间超过30秒,就会导致该终端离开房间。
具体实现如下:
UI 会收到离开房间的回调 - (void)onError:(Error)errorReason,并且事件的结果为
ErrorEndOffline
,表明因断网离开会议。UI 可以提示用户断网,再销毁房间界面。
//会议相关的事件回调
-(void)onError:(ErrorReason)errorReason
{
//ErrorEndOffline 是因断网导致离开会议的结果
if (eventReason == ErrorEndOffline) {
//UI 界面可以提示用户
//todo...
//关闭摄像头
[_confManager stopCamera];
//销毁会议界面
[self dismissViewControllerAnimated:YES completion:nil];
}
}
终端若想回到房间中,需要再次调用加入房间的接口。
有新成员加入房间
终端在房间中时,若有新成员加入,UI 则会回调 - (void)onParticipantJoin:(NSString *)userId 事件 ,可在回调中更新 UI。
具体实现如下:
- (void)onParticipantJoin:(NSString *)userId
{
//更新 UI
//todo..
}
有成员离开房间
终端在会议中时,若有成员离开,UI 则会回调 - (void)onParticipantLeft:(ErrorReason)errorReason userId:(NSString *)userId 事件 ,可在回调中更新 UI。
具体实现如下:
- (void)onParticipantLeft:(ErrorReason)errorReason userId:(NSString *)userId
{
//更新 UI
//todo...
}
请求成员视频
在加入房间后,UI 若要显示房间中其他成员的视频,要先向服务器请求该成员的视频,服务器根据请求的视频分辨率大小结合当前网络状况发送最优分辨率的视频流到终端。
//请求成员视频流,userId对应成员的id,VideoPictureSizeLarge请求视频的分辨率
[_confManager requestVideoWithUserId:userId pictureSize:VideoPictureSizeLarge];
请求的视频分辨率越高,占用的网络带宽越大。为达到流畅的视频效果,请求视频分辨率的原则如下:
- 大的视频窗口请求高分辨率,小的视频窗口请求低分辨率。
- 应避免同时请求多个成员的高分辨率的视频。
- 服务器发送某个成员的视频流是最后一次请求该成员的视频分辨率,因此要注意同一个成员的不同分辨率的切换。
- 同时有大的视频窗口和小的视频窗口要显示同一个成员的视频,此时应请求高分辨率。
- UI 不显示某个成员时,可以不请求或者停止请求该成员的视频。
渲染会议成员视频
请求成员视频后,UI 调用startRender
接口渲染该成员的视频。
//renderView渲染的View,userId对应成员的id,RenderFullScreen视频渲染的填充方式
[_confManager startRender:renderView
userId:userId
mode:RenderFullScreen
completed:nil];
在离开房间时,已经在渲染的 View 应调用 stopRender
停止渲染,释放资源。
//释放的renderView是在渲染的view
[_confManager stopRender:renderView];
发送音视频
成员在会议中可通过调用异步接口打开/关闭向会场发送的本地音视频流,若操作成功,会场内所有成员(包括发起操作的成员)的 UI 都会收到- (void)onParticipantUpdated:(NSString *)userId;
(成员状态改变)事件回调,通过读取对应成员对象内的相关内容,来判断音视频发送的状态。
发送语音
接口enableLocalAudioStream
用于打开/关闭发向会场的本地语音流。当 UI 收到- (void)onParticipantUpdated:(NSString *)userId
的事件回调时,对应成员对象内的isAudioUpload
即表示该成员是否打开了他的本地语音流。
具体实现如下:
调用接口打开/关闭本地语音流。
//enable YES是开启语音流,NO是关闭语音流 - (int)enableLocalAudioStream:(BOOL)enable;
处理成员状态变化的事件回调。
在回调中可获取该成员本地语音流的开关状态,并以此更新 UI 上有关该成员的内容。
-(void)onParticipantUpdated:(NSString *)userId { //获取对应的成员对象 JCParticipantModel *model = [_confManager getParticipantWithUserId:userId]; //isAudioUpload为YES表示该成员是开启语音的状态,为NO表示该成员是关闭语音的状态 BOOL canAudio = model.isAudioUpload; //根据canAudio的值,更新对应成员的 UI //todo... }
注:新成员加入会议后,本地语音流默认未打开,此时会场中的其他成员听不到该成员的声
发送视频
接口enableLocalVideoStream
用于打开/关闭发向会场的本地视频流。当 UI 收到 - (void)onParticipantUpdated:(NSString *)userId
的事件回调时,对应成员对象内的isVedioUpload
即表示该成员是否打开了他的本地视频流。
具体实现如下:
调用接口打开/关闭本地视频流。
//enable YES是开启视频流,NO是关闭视频流 - (int)enableLocalVideoStream:(BOOL)enable;
处理成员状态变化的事件回调。
在回调中可获取该成员本地视频流的开关状态,并以此更新 UI 上有关该成员的内容。
-(void)onParticipantUpdated:(NSString *)userId { //获取对应的成员对象 JCParticipantModel *model = [_confManager getParticipantWithUserId:userId]; //isVideoUpload为YES表示该成员是打开视频流的状态,为NO表 示该成员是关闭视频流的状态。 BOOL canVideo = model.isVideoUpload; //根据canVideo的值更新对应成员的 UI //todo... } }
注:新成员加入房间后,本地视频流默认打开,此时中的其他成员可接收该成员的视频。