iOS

# 实现视频通话

本文档为您展示通过 SDK 实现多方视频通话的相关步骤,帮助您在多人视频通话场景下实现创建会议、邀请新成员加入、结束/离开会议的相关能力。

# 快速跑通 Sample

  1. 在 Juphoon RTC SDK 文档中心,选择 Android 平台下载体验 JCCSample 示例项目。

访问下载地址 (opens new window),示例如下:

img

  1. 下载完成后,打开安装包,解压 JCCSample,然后安装 JCCSample.apk

img

  1. 打开应用程序后,设置正确的 appkey,环境地址以及账号。

    1. 首先点击初始化按钮,成功后,登入按钮变为可点击;
    2. 确认账号输入无误之后,点击登入按钮,按钮字样变为登出,即登录成功;
    3. 点击多方按钮,即可进入多方体验多方相关的功能;
    4. 进入多方页面后,输入房间号,如果有房间密码输入密码,点击加入,即可进入房间。

img

img

# 功能实现

@startuml

autonumber

actor "用户1" as User1
participant "JRTCSDK" as JRTCSDK
participant "Server" as Server
participant "JRTCSDK" as JRTCSDK1
actor "用户2" as User2

activate User1
activate User2
User1 -> JRTCSDK: 初始化JRTCSDK(JRCCClient,JRTCMediaDevice,JRTCRoom)
User1 -> JRTCSDK: 登录login
JRTCSDK -> Server: 登录
Server -> JRTCSDK: 登录结果
User2 -> JRTCSDK1: 初始化JRTCSDK(JRCCClient,JRTCMediaDevice,JRTCRoom)
User2 -> JRTCSDK1: 登录login
JRTCSDK1 -> Server: 登录
Server -> JRTCSDK1: 登录结果

group 登录成功
JRTCSDK -> User1: onLogin(true, reason)
JRTCSDK1 -> User2: onLogin(true, reason)
User1 -> JRTCSDK: 加入房间join("roomId", JRTCRoomJoinParam)
JRTCSDK -> User1: 房间状态改变onRoomStateChanged(STATE_JOINING, STATE_IDLE, JRTCRoom)
JRTCSDK -> Server: 加入房间
Server -> JRTCSDK: 加入房间结果
User2 -> JRTCSDK1: 加入房间join("roomId", JRTCRoomJoinParam)
JRTCSDK1 -> User2: 房间状态改变onRoomStateChanged(STATE_JOINING, STATE_IDLE, JRTCRoom)
JRTCSDK1 -> Server: 加入房间
Server -> JRTCSDK1: 加入房间结果
group 加入房间成功
JRTCSDK -> User1: 房间状态改变onRoomStateChanged(STATE_JOINED, STATE_JOINING, JRTCRoom)
JRTCSDK -> User1: 加入房间结果onJoin(true, reason, "roomId", JRTCRoom)
JRTCSDK1 -> User2: 房间状态改变onRoomStateChanged(STATE_JOINED, STATE_JOINING, JRTCRoom)
JRTCSDK1 -> User2: 加入房间结果onJoin(true, reason, "roomId", JRTCRoom)
JRTCSDK -> User1: 成员加入房间onParticipantJoin(participant, JRTCRoom)
alt 业务操作
User1 <-> User2: 业务操作房间属性变化onRoomPropertyChanged(propChangeParam, JRTCRoom)
User1 <-> User2: onParticipantUpdate(participant, changeParam, JRTCRoom)
end
group 离开房间
User2 -> JRTCSDK1: 离开房间leave()
JRTCSDK1 -> Server: 离开房间
Server -> JRTCSDK1: 离开房间结果
Server -> JRTCSDK: 成员离开房间
JRTCSDK -> User1: onParticipantLeft(participant, reason, JRTCRoom)
JRTCSDK1 -> User2: 离开房间onLeave(reason, roomId, JRTCRoom)
end
end
group 加入房间失败
JRTCSDK -> User1: 房间状态改变onRoomStateChanged(STATE_IDLE, STATE_JOINING, JRTCRoom)
JRTCSDK -> User1: 加入房间结果onJoin(false, reason, null, JRTCRoom)
JRTCSDK -> User1: 房间状态改变onRoomStateChanged(STATE_IDLE, STATE_JOINING, JRTCRoom)
end
end

group 登录失败
JRTCSDK -> User1: onLogin(false, reason)
JRTCSDK1 -> User2: onLogin(false, reason)
end
@enduml

# 初始化

注:我们所有的方法都建议在主线程调用,否则可能会出现异常无法正常使用,回调接口也都在主线程上报。

在使用业务接口前,需对 Juphoon RTC SDK 进行初始化操作。

模块 描述
JRTCClient (opens new window) 登录模块 负责视频平台的登录登出,只有登录到视频平台才可以使用视频相关的业务
JRTCMediaDevice (opens new window) 媒体模块 负责本地的媒体设备操作,视频画面渲染等功能
JRTCRoom (opens new window) 多方通话模块 类似音视频房间的概念,可以通过房间号加入此房间,从而进行音视频通话。

AppKey 作为同个环境的分域依据,同一个域的终端才能实现互通,AppKey 由 Juphoon 视频平台提供。

在使用业务接口前,需对 Juphoon SDK 进行初始化操作。

初始化参数详见 JRTCClientLoginParam (opens new window)

示例代码:

class JRTCManager implements JRTCClientCallback, JRTCMediaDeviceCallback, JRTCRoomCallback {
    public void init() {
        
        JRTCClientInitParam param = new JRTCClientInitParam();
        /**
         * 设置AppKey
         * 用户从 Juphoon RTC 平台上申请的 AppKey 字符串
         */
        param.setAppKey("appKey");
        /**
         * 设置应用名称,比如:JRTCCGuest等
         */
        param.setAppName("appName");
        /**
         * 设置是否需要自动加载so库,默认true
         */
        param.setLoadLibrary(true);
        /**
         * 设置接入服务器地址
         */
        param.setServer("server");
        /**
         * 设置SDK信息存储目录,该目录下的log目录为日志目录
         */
        param.setSdkInfoDir("sdkInfoDir");
        
		// 创建 client 对象
        client = JRTCClient.create(context, this, param);
        // 创建 mediaDevice 对象
        mediaDevice = JRTCMediaDevice.create(client, this, null);
    	// 创建 room 对象
    	room = JRTCRoom.create(mClient, mMediaDevice, this);
        
        //设置基本参数
        client.setServer("server");
        client.SetAppKey("appKey");
        client.setDisplayName("displayName");
        client.setAppName("appName");
    }
}

然后根据 Android Stduio 的提示将 interface 的接口实现补全即可。

# 登录

SDK 初始化之后,即可进行登录的集成,登录接口调用流程如下所示:

img

登录到 Juphoon 视频平台主要调用的是 JRTCClient 的登录接口 login (opens new window)

/**
  * 登录 Juphoon RTC 平台,只有登录成功后才能进行平台上的各种业务
  * 登录结果通过 {@link JRTCClientCallback#onLogin onLogin} 回调通知
  * @param userId 用户ID
  * @param password 密码,不能为空
  * @return 接口调用结果
  * - true: 接口调用成功
  * - false: 接口调用异常
  * @warning 目前只支持免鉴权模式,服务器不校验账号密码,免鉴权模式下当账号不存在时会自动去创建该账号
  * @warning 用户名为英文数字和'+' '-' '_' '.',长度不要超过64字符,'-' '_' '.'不能作为第一个字符
  */
public abstract boolean login(String userId, String password);

/**
  * 登录 Juphoon RTC 平台,只有登录成功后才能进行平台上的各种业务
  * 登录结果通过 {@link JRTCClientCallback#onLogin onLogin} 回调通知
  *
  * @param userId            用户ID
  * @param password          密码,不能为空
  * @param clientLoginParam  登录参数,一般不需要设置,如需设置请询问客服,传 null 则按默认值
  * @see JRTCClientLoginParam
  * @return 接口调用结果
  * - true: 接口调用成功
  * - false: 接口调用异常
  * @warning 目前只支持免鉴权模式,服务器不校验账号密码,免鉴权模式下当账号不存在时会自动去创建该账号
  * @warning 用户名为英文数字和'+' '-' '_' '.',长度不要超过64字符,'-' '_' '.'不能作为第一个字符
  */
public abstract boolean login(String userId, String password, JRTCClientLoginParam clientLoginParam);

/**
 * 重登录,该接口在如果有其他同类型终端登录着则会登录失败,一般用于记住了账号后重启自动登录逻辑
 *
 * @param password 密码,免鉴权模式密码可以随意输入,但不能为空
 * @return 返回 true 表示正常执行调用流程,false 表示调用异常,异常错误通过 JRTCClientCallback 通知
 */
public abstract boolean reLogin(String userId, String password);

JRTCClientLoginParam (opens new window) 参数介绍

terminalType 终端登录类型,支持多终端登录,默认所有终端相同会导致互踢
autoCreateAccount 是否自动创建账号(免鉴权使用),默认 true
deviceId 设备 id
token token
tokenType token 校验类型
tokenExtraParam token 校验拓展参数,json 字符串,token 为空不生效
certificate S3 国密密钥
accountEntry 帐户分录, 如果支持国密 S3 则需要设置 certificate,否则不设置
logFilter 日志过滤标签(用于日志管理平台过滤终端日志使用)
accelerateKey 加速云 KEY
accelerateKeySecret 加速云 KEY 密钥

登录的结果将会通过 JRTCClientCallback (opens new window) 中的 onLogin (opens new window) 接口上报。

/**
 * 登录结果回调
 *
 * @param result true 表示登陆成功,false 表示登陆失败
 * @param reason 当 result 为 false 时该值有效
 */
void onLogin(boolean result, @ReasonCode int reason);

示例代码:

// 创建登录配置参数
JRTCClientLoginParam loginParam = new JRTCClientLoginParam();
// 登录
client.login("6666", "123456", loginParam);

public void onLogin(boolean result, @ReasonCode int reason) {
    if(result) {
        //登录成功
    } else {
        // 登录失败,具体原因查询 reason 错误码
    } 
}

# 加入房间

通过 JRTCRoomJoinParam (opens new window) 可在加入房间前设置房间最大人数,房间密码,最大分辨率等。

/**
 * 加入房间
 *
 * 该方法让用户加入通话频道,在同一个频道内的用户可以互相通话。<br>
 * 如果用户已在频道中,必须退出当前频道,即处于空闲状态,才能进入其他频道,否则将直接返回 false,且不会收到回调通知。
 * @param roomId 频道标识
 * @param joinParam JRTCRoomJoinParam 对象,传 null 则使用默认配置
 * @see JRTCRoomJoinParam
 * @return 接口调用结果
 * - true: 接口调用成功,会收到 {@link JRTCRoomCallback#onJoin onJoin} 回调
 * - false: 接口调用异常
 */
public abstract boolean join(String roomId, JRTCRoomJoinParam joinParam);

加入房间结果通过 onJoin (opens new window) 回调。

/**
 * 加入房间结果回调
 *
 * 调用 {@link JRTCRoom#join join} 接口成功后,会收到此回调。
 * @param result 加入频道是否成功
 * - true: 成功
 * - false: 失败
 * @param reason        加入失败原因,当 result 为 false 时该值有效。失败原因参见:{@link ReasonCode 错误码}
 * @param roomId     频道标识
 * @param room  当前 JRTCRoom 对象
 */
void onJoin(boolean result, @ReasonCode int reason, String roomId, JRTCRoom room);

当加入房间后可通过 getParticipants (opens new window) 获取已经在房间中的成员,然后渲染当前所有成员。

示例代码:

// 创建加入房间参数
JRTCRoomJoinParam param = new JRTCRoomJoinParam();
param.setUploadLocalAudio(true);//是否上传本地音频流
param.setUploadLocalVideo(true);//是否上传本地视频流
// 加入房间
room.join(roomId, param);

// 加入房间结果回调
void JRTCRoomCallback.onJoin(boolean result, @ReasonCode int reason, String roomId, JRTCRoom room){
    if (result == true) {
        // 加入成功
        // 获取当前房间中所有成员
        List<JRTCRoomParticipant> participantList = room.getParticipants();
    } else {
        // 加入失败
    }
}

# 自身在房间中的状态变化

当自身在房间中的状态发生变化时,会收到 onRoomStateChanged (opens new window) 回调,例如加入房间、加入房间成功、离开回调等。

房间状态详见 RoomState (opens new window)

/**
* 自身在房间中的状态变化回调
* <p>
* 当自身在房间中的状态发生变化时,会收到此回调,例如加入房间、加入房间成功、离开回调等。
* 状态:
* - {@link JRTCEnum#STATE_IDLE STATE_IDLE} : 空闲状态
* - {@link JRTCEnum#STATE_JOINING STATE_JOINING}: 加入中
* - {@link JRTCEnum#STATE_JOINED STATE_JOINED} : 已加入
* - {@link JRTCEnum#STATE_LEAVING STATE_LEAVING} : 离开中
*
* @param state    当前状态
* @param oldState 变化前状态
* @param room     当前 JRTCRoom 对象
*/
void onRoomStateChanged(@RoomState int state, @RoomState int oldState, JRTCRoom room);

示例代码:

void onRoomStateChanged(@ConfState int state, @ConfState int oldState, JRTCRoom room){
    if (state == JRTCEnum.STATE_IDLE) {
        // 空闲状态
    } else if (state == JRTCEnum.STATE_JOINING) {
        // 加入中   
    } else if (state == JRTCEnum.STATE_JOINED) {
        // 已加入   
    } else if (state == JRTCEnum.STATE_LEAVING) {
        // 离开中   
    }
}

# 创建本地视频画面

初始化成功后,可以创建本地的视频画面,创建本地视频画面的时机没有具体要求,在加入房间前后调用皆可。

  1. 通过 startCameraVideo (opens new window) 方法,获取 JRTCMediaDeviceVideoCanvas (opens new window)本地的视频对象。
  2. 在界面画布上渲染本地视频对象画面。
/**
* 开始自身视频渲染
*
* 获取本端视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
* @note
* 调用此方法时需要保证默认摄像头不为空,即 {@link #defaultCamera} 不为空,否则将直接返回 null
* @param renderType 渲染模式:
* - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
* - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
* - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
* @return
* - JCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
* - null: 开始自身视频渲染失败
*/
public abstract JRTCMediaDeviceVideoCanvas startCameraVideo(@RenderType int renderType);

/**
* 开始自身视频渲染
*
* 获取本端视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
* @note
* 调用此方法时需要保证默认摄像头不为空,即 {@link #defaultCamera} 不为空,否则将直接返回 null
* @param renderType 渲染模式:
* - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
* - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
* - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
* @param useTextureView 是否使用TextureView作为视图控件,默认SurfaceView作为视图控件
* @return
* - JCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
* - null: 开始自身视频渲染失败
*/
public abstract JRTCMediaDeviceVideoCanvas startCameraVideo(@RenderType int renderType, boolean useTextureView);

RenderType (opens new window) 决定了视频的渲染模式:

  1. RENDER_FULL_SCREEN (opens new window) 为填充模式:即将画面内容居中等比缩放以充满整个显示区域,超出显示区域的部分将会被裁剪掉,此模式下画面可能不完整。
  2. RENDER_FULL_CONTENT (opens new window)为适应模式:即按画面长边进行缩放以适应显示区域,短边部分会被填充为黑色,此模式下图像完整但可能留有黑边。

img

示例代码:

// 创建本地视频画面对象
JRTCMediaDeviceVideoCanvas localCanvas = mediaDevice.startCameraVideo(JRTCMediaDevice.RENDER_FULL_SCREEN)

调用 startCameraVideo (opens new window) 渲染本地视频后方法后,在自己离开房间时需要对应调用 stopVideo (opens new window) 方法停止视频渲染。

# 新成员加入

当新成员加入房间后,其他成员会收到 onParticipantJoin (opens new window) 成员加入的回调。

/**
* 新成员加入回调
*
* 当有用户调用 {@link JRTCRoom#join join} 接口加入频道成功时,已在频道中的成员会收到此回调。
* @param participant  JRTCRoomParticipant 成员对象
* @param room 当前 JRTCRoom 对象
*/
void onParticipantJoin(JRTCRoomParticipant participant, JRTCRoom room);

此时可以通过回调获取到成员对象进行远端视图渲染并订阅远端成员的视频流。

示例代码:

// 新成员加入房间
void onParticipantJoin(JRTCRoomParticipant participant, JRTCRoom room ) {
    // 订阅该成员视频流
    room.requestVideo(participant, videoSize);
    // 渲染该成员视频画面
    JRTCMediaDeviceVideoCanvas canvas = mediaDevice.startVideo(participant.getStreamId(), JRTCMediaDevice.RENDER_FULL_CONTENT); 
    SurfaceView view = canvas.getVideoView();
    viewGroup.addView(view);
}

# 成员更新

当房间内成员状态发生改变时,其他成员能收到该成员状态变化通知 onParticipantUpdate (opens new window),具体成员变化属性参考 JRTCRoomParticipant.ChangeParam (opens new window),包含成员音量、网络状态、音视频上传状态、成员类型、视频订阅尺寸变化等。

/**
 * 成员属性更新回调
 *
 * 当房间中有成员的属性发生变化时,房间中的其他成员会收到此回调,例如音频上传状态、视频上传状态、网络状态等发生变化。
 * @param participant  JRTCRoomParticipant 成员对象
 * @param changeParam  {@link JRTCRoomParticipant.ChangeParam} 更新标识类对象
 * @param room 当前 JRTCRoom 对象
 */
void onParticipantUpdate(JRTCRoomParticipant participant, JRTCRoomParticipant.ChangeParam changeParam, JRTCRoom room);

示例代码:

public void onParticipantUpdate(JRTCRoomParticipant participant, JRTCRoomParticipant.ChangeParam changeParam, JRTCRoom room) {
    if (changeParam.volume) {
        //成员音量大小变化
    } else if (changeParam.volumeStatus) {
        //成员音量状态变化
    } else if (changeParam.netStatus) {
        //成员网络状态变化
    } else if (changeParam.netStatus) {
        //成员网络状态变化
    } else if (changeParam.audio) {
        //成员音频上传状态变化
    } else if (changeParam.video) {
        //成员视频上传状态变化
    } else if (changeParam.videoSize) {
        //订阅该成员视频尺寸变化
    } else if (changeParam.type) {
        //该成员类型变化
    }
}

# 创建远端视频画面

当加入房间后,除了本地的视频画面,还有房间内其他成员的视频画面,如果房间内其他成员有视频流上传,本端可以获取到其他成员的的视频流并进行渲染,详细见 4.3.6 章节;

当成员视频状态变化,比如该成员开始上传视频,此时可以去渲染该成员视频,该成员结束上传视频,则可以去停止渲染该成员视频。

# 订阅/取消订阅视频

在渲染成员视频前,需要先通过调用 requestVideo (opens new window) 方法订阅该视频,当成员离开需要调用 unRequestVideo (opens new window) 及时取消订阅该视频流。

/**
 * 订阅房间中其他用户的视频流
 *
 * @param participant  JRTCRoomParticipant 成员对象
 * @param videoSize    视频请求的尺寸,详见 {@link JRTCVideoSize}
 * @return 接口调用结果
 * - true: 接口调用成功,会收到 {@link JRTCRoomCallback#onParticipantUpdate onParticipantUpdate} 回调
 * - false: 接口调用异常
 */
public abstract boolean requestVideo(JRTCRoomParticipant participant, JRTCVideoSize videoSize);

/**
 * 取消订阅房间中其他用户的视频流
 *
 * @param participant  JRTCRoomParticipant 房间中其他成员对象
 * @return 调用是否正常
 * - true: 正常执行调用流程,会收到 {@link JRTCRoomCallback#onParticipantUpdate onParticipantUpdate} 回调
 * - false: 调用失败,不会收到回调通知
 */
public abstract boolean unRequestVideo(JRTCRoomParticipant participant);

# 渲染/停止渲染视频

远端视频渲染可以通过调用 startVideo (opens new window) 来实现,停止渲染通过调用 stopVideo (opens new window) 来实现。

/**
* 开始其他端的视频渲染
*
* 获取其他端的视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
*
* @param renderId 视频流ID
* @param renderType  渲染模式:
* - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
* - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
* - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
* @return
* - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
* - null: 开始自身视频渲染失败
*/
public abstract JRTCMediaDeviceVideoCanvas startVideo(String videoSource, @RenderType int renderType);

/**
* 开始其他端的视频渲染
*
* 获取其他端的视频预览对象 JRTCMediaDeviceVideoCanvas,通过此对象能获得视图用于UI显示
*
* @param renderId 视频流ID
* @param renderType  渲染模式:
* - {@link #RENDER_FULL_SCREEN RENDER_FULL_SCREEN} : 铺满窗口,会有裁剪
* - {@link #RENDER_FULL_CONTENT RENDER_FULL_CONTENT} : 全图像显示,会有黑边
* - {@link #RENDER_FULL_AUTO RENDER_FULL_AUTO} : 自适应
* @param useTextureView 是否使用TextureView作为视图控件,默认SurfaceView作为视图控件
* @return
* - JRTCMediaDeviceVideoCanvas 对象: 开始自身视频渲染成功
* - null: 开始自身视频渲染失败
*/
public abstract JRTCMediaDeviceVideoCanvas startVideo(String videoSource, @RenderType int renderType, boolean useTextureView);

/**
 * 停止视频渲染
 *
 * @param canvas JRTCMediaDeviceVideoCanvas 对象,由 {@link #startVideo startVideo} 或 {@link #startCameraVideo startCameraVideo} 接口返回
 */
public abstract void stopVideo(JRTCMediaDeviceVideoCanvas canvas);

示例代码:

public void onParticipantUpdate(JRTCRoomParticipant participant, JRTCRoomParticipant.ChangeParam changeParam, JRTCRoom room) {
    if (changeParam.video) {
        if (participant.isVideo()) {
            //根据需要的视频尺寸订阅该成员视频
            room.requestVideo(participant, new JRTCVideoSize(1280, 720));
            JRTCMediaDeviceVideoCanvas canvas = mediaDevice.startVideo(participant.getStreamId(), JRTCMediaDevice.RENDER_FULL_CONTENT); 
			SurfaceView view = canvas.getVideoView();
			viewGroup.addView(view);        
        } else {
            //取消订阅该成员视频
            room.unRequestVideo(participant);
            //停止渲染该成员视频
            mediaDevice.stopVideo(canvas);
        }
    }
}

# 成员离开

当成员离开房间后,其他成员会收到成员离开的回调 onParticipantLeft (opens new window) 回调通知,此时可以调用 stopVideo (opens new window) 取消订阅该成员视频流以及停止渲染该成员视频。

/**
* 成员离开回调
* <p>
* 当房间中有成员调用 {@link JRTCRoom#leave leave} 接口离开房间后,房间中的其他成员会收到此回调。
*
* @param participant 成员对象
* @param reason      成员离开原因
* @param room        当前 room 对象
*/
void onParticipantLeft(JRTCRoomParticipant participant, @ReasonCode int reason, JRTCRoom room);

示例代码:

public void onParticipantLeft(JRTCRoomParticipant participant, int reason, JRTCRoom room) {
    //其中remoteCanvas对象是通过 startVideo 返回
    mediaDevice.stopVideo(remoteCanvas);
}

# 离开房间

如果想离开房间,可以调用下面的接口 leave (opens new window),此时自己会收到 onLeave (opens new window) 回调,房间内其他成员会收到该成员离开的回调 onParticipantLeft (opens new window)

/**
 * 离开房间
 * @return 接口调用结果
 * - true: 接口调用成功,非空闲状态下,会收到 {@link JRTCRoomCallback#onLeave onLeave} 回调
 * - false: 接口调用异常
 */
public abstract boolean leave();
/**
 * 离开房间结果回调
 *
 * 调用 {@link JRTCRoom#leave leave} 接口成功后,会收到此回调。
 * @param reason       离开原因,参见:{@link ReasonCode 离开原因}
 * @param roomId    房间标识
 * @param room 当前 JRTCRoom 对象
 */
void onLeave(@ReasonCode int reason, String roomId, JRTCRoom room);

示例代码:

// 离开房间
room.leave();
// 离开房间结果回调
public void onLeave(@ReasonCode int reason, String roomId, JRTCRoom room) {
    // 可以停止渲染其他成员视频以及本地视频
    //其中localCanvas对象是通过startCameraVideo 返回
    mediaDevice.stopVideo(localCanvas);
    //其中remoteCanvas对象是通过 startVideo 返回
    mediaDevice.stopVideo(remoteCanvas);
}

# 销毁本地和远端视频画面

当不再需要查看视频画面,包括房间成员离开,或者离开房间,需要调用 stopVideo (opens new window) 接口来停止渲染的资源,该方法需传入要释放的 JRTCMediaDeviceVideoCanvas (opens new window) 对象,或者调用 stopAllVideos (opens new window) 接口来时停止所有正在渲染的视频,必须进行这步操作,不然会造成渲染内存不释放。

/**
* 停止视频渲染
*
* @param canvas JRTCMediaDeviceVideoCanvas 对象,由 {@link #startVideo startVideo} 或 {@link #startCameraVideo startCameraVideo} 接口返回
*/
public abstract void stopVideo(JRTCMediaDeviceVideoCanvas canvas);

/**
* 停止所有视频渲染
*/
public abstract void stopAllVideos();

示例代码:

// 离开房间结果回调
public void onLeave(@ReasonCode int reason, String roomId, JRTCRoom room) {
    // 可以停止渲染其他成员视频以及本地视频
    //其中localCanvas对象是通过startCameraVideo 返回
    mediaDevice.stopVideo(localCanvas);
    //其中remoteCanvas对象是通过 startVideo 返回
    mediaDevice.stopVideo(remoteCanvas);
    // 停止所有正在渲染的视频
    mediaDevice.stopAllVideo();
}

public void onParticipantLeft(JRTCRoomParticipant participant, int reason, JRTCRoom room) {
    //其中remoteCanvas对象是通过 startVideo 返回
    mediaDevice.stopVideo(remoteCanvas);
}

# 登出

离开房间后,可以做登出操作,登出接口调用流程如下所示:

img

成员可以通过调用 logout (opens new window) 方法登出视频平台,与平台断开一切连接。

/**
* 登出 Juphoon RTC 平台,登出后不能进行平台上的各种业务
*
* 登出结果通过 {@link JRTCClientCallback#onLogout onLogout} 回调通知
* @return 接口调用结果
* - true: 接口调用成功
* - false: 接口调用异常
*/
public abstract boolean logout();

登出结果通过 JRTCClientCallback (opens new window)onLogout (opens new window) 接口进行上报。

/**
* 登出回调
*
* @param reason 登出原因
*/
void onLogout(@ReasonCode int reason);

示例代码:

// 调用登出接口
client.logout();

// 登出结果回调
public void onLogout(@ReasonCode int reason) {
    // 登出完成   
}

# 登录状态改变通知

登录状态通过 JRTCClientCallback (opens new window)onClientStateChanged (opens new window) 接口上报

    /**
     * 登录状态变化通知
     * @param state 当前状态值
     * @param oldState 之前状态值
     */
    void onClientStateChanged(@JRTCClient.ClientState int state, @JRTCClient.ClientState int oldState);

登录状态详见 ClientState (opens new window)

示例代码:

//登录状态改变通知
public void onClientStateChanged(@ClientState int state, @ClientState int oldState) {
    //state 当前状态
    //oldState 之前状态
}

# 销毁 SDK

每个模块都有对应的销毁接口。如不需再使用 SDK 的相关功能,可以强制释放 SDK 的资源。

注意:该方法为同步调用,需要等待实例资源释放后才能执行其他操作,调用此方法后,你将无法再使用该模块的其它方法和回调。 我们不建议在 JRTCSDK 的回调中调用此方法销毁对象,否则可能出现崩溃现象。

public static void destroy()

示例代码:

JRTCRoom.destroy();
JRTCMediaDevice.destroy();
JRTCClient.destroy();