跳到主要内容

otherroom

跨房间连麦中需要区分主房间和副房间概念。主副房间是相对概念,定义如下:

  • 主房间:本端在最开始加入的房间,即 RCRTCRoom
  • 副房间:在连麦邀请被接受后,双方均需要加入对方房间。对方房间即:RCRTCOtherRoom

跨房间连麦前需要双方都已经加入自己的主房间,未加入主房间前无法进行连麦的邀请和被邀请。

两种房间的类都有对应的代理 IRCRTCRoomEventsListenerIRCRTCOtherRoomEventsListener 用来区分不同类型房间的回调。

主流程

(height=800)

发起邀请

向指定用户发送跨房间连麦请求,使用加入房间成功回调返回的 RCRTCRoom 类获取 RCRTCLocalUser 对象,调用 requestJoinOtherRoom 方法。

  • 代码示例:

    /**
    * 向指定用户发送跨房间连麦请求
    * <P>
    * 1: inviterAutoMix为true时:
    *
    * 1.1:如果被邀请方在加入邀请方房间之前发布了资源,当被邀请方加入邀请者房间成功后,服务器会把被邀请方流资源合并到邀请方视图 ·(默认仅悬浮布局合流)上。
    *
    * 1.2:如果被邀请方在加入邀请方房间之前没有发布过资源,将会在被邀请方发布资源成功后,服务器会把被邀请方流资源合并到邀请方视图(默认仅悬浮布局合流)上。
    *
    * 2:无论为true或false,双方都可以使用{@link RCRTCLiveInfo#setMixConfig(RCRTCMixConfig, IRCRTCResultCallback)} 方法主动设置合流布局。一旦主动设置过合流布局,后续音视频直播过程中设置的自动合流参数将失效。
    * <P/>
    */
    RCRTCRoom.getLocalUser().requestJoinOtherRoom(inviteeRoomId, inviteeUserId, inviterAutoMix, "extra", new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    }
    });
  • API 参考:

取消邀请

收到其他房间主播连麦邀请后,如果不打算加入,则调用 RCRTCLocalUser 中的 cancelRequestJoinOtherRoom 来取消正在进行中的跨房间连麦请求。

应答邀请

收到其他房间主播连麦邀请后,如果打算加入,则需要先调用 RCRTCLocalUser 中的 responseJoinOtherRoom 来响应跨房间麦连麦邀请,再调用 joinOtherRoom 加入副房间。

  • 代码示例:

        /**
    * <P>
    * 1:inviteeAutoMix 为true时:
    *
    * 1.1:如果邀请方在发送连麦请求之前发布了资源,当被邀请方加入邀请者房间成功后,服务器会把邀请方流资源合并到被邀请方视图(默认仅悬浮布局合流)上。
    *
    * 1.2:如果邀请方在发送连麦请求之前没有发布资源,将会在邀请方发布资源成功后,服务器才会把邀请方的资源合并到被邀请方视图(默认仅悬浮布局合流)上。
    *
    * 2: 无论为true或false,双方都可以使用{@link RCRTCLiveInfo#setMixConfig(RCRTCMixConfig, IRCRTCResultCallback)} 方法主动设置合流布局。一旦主动设置过合流布局,后续音视频直播过程中设置的自动合流参数将失效。
    *
    * <P/>
    */
    RCRTCRoom.getLocalUser().responseJoinOtherRoom(inviterRoomId, inviterUserId, agree, inviteeAutoMix, "extra", new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
    }

    @Override
    public void onFailed(RTCErrorCode errorCode) {
    }
    });
  • API 参考:

加入副房间

注册其他房间事件监听

  1. 在加入其他房间成功后的回调中,可以得到 RCRTCOtherRoom 对象,调用其中的 registerOtherRoomEventsListener 即可注册其他房间事件监听。当有其他房间主播加入、离开、发布资源后会触发此监听回调,在回调中订阅用户音视频资源,可进行音视频通话。

  2. 在不使用或退出房间之前需取消注册 RCRTCOtherRoom.unregisterOtherRoomEventsListener

    RCRTCOtherRoom.registerOtherRoomEventsListener(new IRCRTCOtherRoomEventsListener() {
    /**
    * 其他房间内用户发布资源
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    * @param list 发布的资源
    */
    @Override
    public void onRemoteUserPublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {}

    /**
    * 其他房间用户发布的音频资源静音或者取消静音
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    * @param rcrtcInputStream 音频流
    * @param mute true表示静音,false表示取消静音
    */
    @Override
    public void onRemoteUserMuteAudio(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, RCRTCInputStream rcrtcInputStream, boolean mute) {}

    /**
    * 远端用户打开或关闭发布的视频流。 例如用户开启或者关闭摄像头
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    * @param rcrtcInputStream 视频流
    * @param mute true表示关闭,false表示打开
    */
    @Override
    public void onRemoteUserMuteVideo(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, RCRTCInputStream rcrtcInputStream, boolean mute) {}

    /**
    * 房间内用户取消发布资源
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    * @param list 远端用户取消发布的资源
    */
    @Override
    public void onRemoteUserUnpublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {}

    /**
    * 用户加入房间
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    */
    @Override
    public void onUserJoined(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser) {}

    /**
    * 用户离开房间
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    */
    @Override
    public void onUserLeft(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser) {}

    /**
    * 用户离线
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    */
    @Override
    public void onUserOffline(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser) {}

    /**
    * 自己退出其他房间。 例如断网退出等
    *
    * @param rcrtcOtherRoom 加入的其他房间对象
    * @param reasonCode 状态码
    */
    @Override
    public void onLeaveRoom(RCRTCOtherRoom rcrtcOtherRoom, int reasonCode) {}
    });

离开副房间

当需要结束跨房间连麦时,调用 RCRTCEngine 中的 leaveOtherRoom 离开副房间。

邀请连麦流程

  • 场景一,邀请方发起邀请后,邀请方又取消邀请。

    提示

    此场景中被邀请方未做任何操作,仅被动收到两次代理回调。

邀请方被邀请方
步骤1:调用 RCRTCLocalUser 类中的 requestJoinOtherRoom 方法发起跨房间连麦邀请步骤2:在 IRCRTCRoomEventsListener 中收到 onRequestJoinOtherRoom 邀请回调
步骤3:调用 RCRTCLocalUser 类中的 cancelRequestJoinOtherRoom 方法结束之前发起的邀请步骤4:在 IRCRTCRoomEventsListener 中收到 onCancelRequestOtherRoom 取消受邀请的回调
  • 场景二,邀请方发起邀请后,被邀请方应答同意。

    提示

    此场景中被邀请方应答同意,只有被邀请方不会收到应答的回调,包含邀请人在内两个房间的所有非观众用户都会收到代理回调。

邀请方被邀请方
步骤1:调用 RCRTCLocalUser 类中的 requestJoinOtherRoom 方法发起跨房间连麦邀请步骤2:在 IRCRTCRoomEventsListener 中收到 onRequestJoinOtherRoom 邀请回调
步骤4:包含邀请人在内两个房间的所有非观众用户,不包含被邀请方,会在 IRCRTCRoomEventsListener 中收到 onResponseJoinOtherRoom 应答回调步骤3:调用 RCRTCLocalUser 类中的 responseJoinOtherRoom 应答邀请,其中,agree 参数的值为 true
  • 场景三,邀请方发起邀请后,被邀请方应答拒绝。

    提示

    此场景中被邀请方应答拒绝,只有邀请方会收到应答拒绝的回调,其他所有用户都不会收到代理回调。

邀请方被邀请方
步骤1:调用 RCRTCLocalUser 类中的 requestJoinOtherRoom 方法发起跨房间连麦邀请步骤2:在 IRCRTCRoomEventsListener 中收到 onRequestJoinOtherRoom 邀请回调
步骤4:只有邀请方会收到应答拒绝的回调,其他所有用户都不会收到 IRCRTCRoomEventsListener 中的 onResponseJoinOtherRoom 应答回调步骤3:调用 RCRTCLocalUser 类中的 responseJoinOtherRoom 应答邀请,其中,agree 参数的值为 false

加入副房间流程

  • 场景四,在 场景二 的前提下,邀请方在收到应答同意的回调后,加入被邀请方的房间,即:邀请方加入的副房间。

    被邀请方在调用应答同意后,加入邀请方的房间,即:被邀请方加入的副房间。

    邀请方被邀请方
    步骤2:在收到被邀请方同意代理回调后,调用 RCRTCEnginejoinOtherRoom 方法加入副房间步骤1:在应答邀请同意后,调用 RCRTCEnginejoinOtherRoom 方法加入副房间
  • 场景五,在加入主房间前,如果主房间的某用户已经与其他房间另一用户成功建立跨房间连麦。

    可以通过加入主房间成功后得到的 RCRTCRoom 对象中检查 getOtherRoomIds() 中是否存在房间中的用户已经加入的副房间。如果存在,可选择是否加入其他副房间

    /**
    * 主房间中主播已经加入的副房间Id列表
    */
    List<String> getOtherRoomIds();
    跨房间连麦成功后加入主房间的用户
    步骤1:调用 RCRTCEnginejoinRoom 方法加入主房间
    步骤2:检查发现 getOtherRoomIds() 中存在其他副房间
    步骤3:调用 RCRTCEnginejoinOtherRoom 方法加入副房间

订阅流程

场景四场景五 的前提下。

  • 场景六,订阅副房间用户已经发布的音视频资源方式一:加入副房间后,通过遍历取得副房间中所有远端用户中的 RCRTCInputStream 列表,再调用 RCRTCLocalUsersubscribeStreams 方法订阅副房间中远端用户已经发布的音视频资源。

    RCRTCEngine.getInstance().joinOtherRoom(roomId, new IRCRTCResultDataCallback<RCRTCOtherRoom>() {
    @Override
    public void onSuccess(RCRTCOtherRoom rcrtcOtherRoom) {
    List<RCRTCInputStream> inputStreamList=new ArrayList<>();
    //遍历远端用户列表
    for (int i = 0; i < rcrtcOtherRoom.getRemoteUsers().size(); i++) {
    //遍历远端用户发布的资源列表
    for (RCRTCInputStream stream : rcrtcOtherRoom.getRemoteUsers().get(i).getStreams()) {
    if(stream.getMediaType()== RCRTCMediaType.VIDEO){
    //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示
    RCRTCVideoView remoteView = new RCRTCVideoView(MainActivity.this);
    ((RCRTCVideoInputStream)stream).setVideoView(remoteView);
    //todo 本demo只演示添加1个远端用户的视图
    frameyout_remote.removeAllViews();
    frameyout_remote.addView(remoteView);
    }
    //如果要订阅所有远端用户的流。将其保存,方便后面统一订阅
    inputStreamList.add(stream);
    }
    }
    //开始订阅资源
    RCRTCRoom.getLocalUser().subscribeStreams(inputStreamList, new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
    }
    @Override
    public void onFailed(RTCErrorCode rtcErrorCode) {
    }
    });
    }

    @Override
    public void onFailed(RTCErrorCode rtcErrorCode) {
    }
    });
  • 订阅副房间用户刚发布的音视频资源方式二:加入副房间后,当有副房间中远端用户发布资源时,会回调 IRCRTCOtherRoomEventsListeneronRemoteUserPublishResource 方法,调用 RCRTCLocalUsersubscribeStreams 方法订阅副房间中远端用户刚发布的音视频资源。

    @Override
    public void onRemoteUserPublishResource(RCRTCOtherRoom rcrtcOtherRoom, RCRTCRemoteUser rcrtcRemoteUser, List<RCRTCInputStream> list) {
    //遍历远端用户发布的资源列表
    for (RCRTCInputStream stream : list) {
    if(stream.getMediaType()== RCRTCMediaType.VIDEO){
    //如果远端用户发布的是视频流,创建显示视图RCRTCVideoView,并添加到布局中显示
    RCRTCVideoView remoteView = new RCRTCVideoView(MainActivity.this);
    ((RCRTCVideoInputStream)stream).setVideoView(remoteView);
    frameyout_remote.removeAllViews();
    frameyout_remote.addView(remoteView);
    }
    }
    //开始订阅资源
    RCRTCRoom.getLocalUser().subscribeStreams(list, new IRCRTCResultCallback() {
    @Override
    public void onSuccess() {
    }

    @Override
    public void onFailed(RTCErrorCode rtcErrorCode) {
    }
    });
    }

离开副房间流程

  • 场景七,已经加入副房间的用户,需要退出副房间时,可以调用 RCRTCEngine 中的 leaveOtherRoom(String roomId, boolean notifyFinished, IRCRTCResultCallback callBack) 方法。

    提示

    此方法内部会取消订阅已经订阅的副房间所有用户音视频资源,上层无需自行取消订阅。 此方法中的 notifyFinished 参数为 false 时,仅代表调用方离开副房间,其他用户会收到 IRCRTCOtherRoomEventsListeneronUserLeft 回调。 :::

    @Override
    public void onUserLeft(RCRTCOtherRoom rcrtcBaseRoom, RCRTCRemoteUser rcrtcRemoteUser) {
    }
  • notifyFinished 参数为 true 时,其他用户会收到 IRCRTCOtherRoomEventsListeneronUserLeft 和在 IRCRTCRoomEventsListeneronFinishOtherRoom 回调。

    /**
    * 用户离开房间
    *
    * @param rcrtcBaseRoom 加入的其他房间对象
    * @param rcrtcRemoteUser 远端用户
    */
    @Override
    public void onUserLeft(RCRTCOtherRoom rcrtcBaseRoom, RCRTCRemoteUser rcrtcRemoteUser) {
    }
    /**
    * 收到结束跨房间连麦的通知
    *
    * @param roomId 结束连麦的房间 Id
    * @param userId 发起结束连麦的用户 id
    */
    @Override
    public void onFinishOtherRoom(String roomId, String userId) {
    super.onFinishOtherRoom(roomId, userId);
    }

被服务端踢出房间流程

提示

通过调用服务端 API 可以将指定房间的指定用户踢出该房间。

  • 在踢出某个用户之前 ,建议先通过服务下发消息让此客户端执行结束跨房间连麦 ,然后再从主房间踢出违禁用户。

  • 被踢出的房间是该用户加入的主房间时,RongRTCLib 内部会调用 RCRTCEngine.getInstance().leaveRoom 方法先退出已经加入的副房间,再退出主房间并销毁资源。UI 层无需再次调用离开主、副房间的方法,只处理上层逻辑即可。

  • 被踢出的房间是该用户加入的副房间时,RongRTCLib 内部会调用 IRCRTCOtherRoomEventsListeneronKickedByServer(RCRTCOtherRoom rcrtcBaseRoom) 方法仅退出指定的副房间,并取消订阅已经订阅的该副房间中用户的音视频资源,UI 层无需再次调用离开副房间的方法,只处理上层逻辑即可。

    /**
    * 被服务端踢下线
    * <p>如果用户在房间内, 此时收到服务器封禁的通知, SDK 会关闭音视频连接, 释放资源,
    * 将用户踢出房间, 回调通知用户</p>
    *
    * @param rcrtcBaseRoom 加入的其他房间对象
    */
    @Override
    public void onKickedByServer(RCRTCOtherRoom rcrtcBaseRoom) {
    super.onKickedByServer(rcrtcBaseRoom);
    }