实现语聊房(基于NERoom)
更新时间: 2024/08/14 14:11:32
本文档为您展示通过 NERoom房间组件实现语聊房场景的相关步骤,帮助您在业务中实现麦位管理、低延时语音互动、文字聊天等能力。
开发环境要求
开发环境要求如下:
环境要求 | 说明 |
---|---|
JDK 版本 | 1.8.0 及以上版本 |
Android API 版本 | API 21 及以上版本 |
Android Studio 版本 | 5.0 及以上版本 |
CPU架构 | ARM 64、ARMV7 |
IDE | Android Studio |
其他 | 依赖 Androidx,不支持 support 库。 Android 系统 5.0 及以上版本的真机。 |
前提条件
方案架构
方案架构说明如下:
- 主播、连麦者和观众加入同一个音视频房间。
- 主播和连麦者在音视频房间内进行音频流的实时发布和订阅。
- 观众在音视频房间内仅订阅音频流,不发布音频流。
API调用时序图
sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client
note over hostClientA, audienceB: 主播开播
hostClientA ->> NERoomA: createRoom
NERoomA ->> app_server: createRoom
app_server -->> hostClientA: 房间信息
hostClientA ->> NERoomA: joinRoom
NERoomA ->> app_server: joinRoom
app_server -->> hostClientA: 加入成功
hostClientA ->> NERoomA: unmuteMyAudio
NERoomA ->> app_server: unmuteMyAudio
note over hostClientA, audienceB: 观众进入房间
audienceB ->> NERoomB: joinRoom
NERoomB ->> app_server: joinRoom
app_server -->> audienceB: 房间信息
audienceB ->> NERoomB: unmuteMyAudio
NERoomB ->> app_server: unmuteMyAudio
sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client
note over hostClientA, audienceB: 抱观众上麦
hostClientA ->> NERoomA: sendSeatInvitation <br>(邀请上麦)
NERoomA ->> app_server: sendSeatInvitation <br>(邀请上麦)
app_server -->> NERoomB: onSeatInvitationAccepted <br>(自动同意上麦的回调)
NERoomB -->> audienceB: onSeatInvitationAccepted <br>(自动同意上麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomA: onSeatInvitationAccepted <br>(自动同意上麦的回调)
NERoomA -->> hostClientA: onSeatInvitationAccepted <br>(自动同意上麦的回调)
app_server -->> NERoomA: onSeatListChanged <br> (麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
note over hostClientA, audienceB: 将观众移出麦位
hostClientA ->> NERoomA: kickSeat <br>(主播踢观众B下麦)
NERoomA ->> app_server: kickSeat <br>(主播踢观众B下麦)
app_server -->> NERoomB: onSeatKicked <br>(主播踢观众B下麦的回调)
NERoomB -->> audienceB: onSeatKicked <br>(主播踢观众B下麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomA: onSeatKicked <br>(主播踢观众B下麦的回调)
NERoomA -->> hostClientA: onSeatKicked <br>(主播踢观众B下麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client
note over hostClientA, audienceB: 观众申请上麦
audienceB ->> NERoomB: submitSeatRequest <br>(申请上麦)
NERoomB ->> app_server: submitSeatRequest <br>(申请上麦)
app_server ->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB ->> audienceB: onSeatListChanged <br>(麦位变更的回调)
app_server ->> NERoomA: onSeatRequestSubmitted <br>(观众B申请上麦的回调)
NERoomA ->> hostClientA: onSeatRequestSubmitted <br>(观众B申请上麦的回调)
app_server ->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA ->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
alt 主播同意上麦申请
hostClientA ->> NERoomA: approveSeatRequest <br>(主播同意上麦申请)
NERoomA ->> app_server: approveSeatRequest <br>(主播同意上麦申请)
app_server ->> NERoomA: onSeatRequestApproved <br>(主播同意上麦申请的回调)
NERoomA ->> hostClientA: onSeatRequestApproved <br>(主播同意上麦申请的回调)
app_server ->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA ->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server ->> NERoomB: onSeatRequestApproved <br>(主播同意上麦申请的回调)
NERoomB ->> audienceB: onSeatRequestApproved <br> (主播同意上麦申请的回调)
app_server ->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB ->> audienceB: onSeatListChanged <br> (麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
else 主播拒绝上麦申请
hostClientA ->> NERoomA: rejectRequestSeat <br>(主播不同意上麦申请)
NERoomA ->> app_server: rejectRequestSeat <br>(主播不同意上麦申请)
app_server -->> NERoomA: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
NERoomA -->> hostClientA: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomB: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
NERoomB -->> audienceB: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
end
sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client
note over hostClientA, audienceB: 观众取消申请上麦
audienceB ->> NERoomB: cancelSeatRequest<br> (取消申请上麦)
NERoomB ->> app_server: cancelSeatRequest <br> (取消申请上麦)
app_server -->> NERoomA: onSeatRequestCancelled <br>(观众B取消上麦的回调)
NERoomA -->> hostClientA: onSeatRequestCancelled <br>(观众B取消上麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomB: onSeatRequestCancelled <br>(观众B取消上麦的回调)
NERoomB -->> audienceB: onSeatRequestCancelled <br> (观众B取消上麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
note over hostClientA, audienceB: 观众下麦
audienceB ->> NERoomB: leaveSeat (下麦)
NERoomB ->> app_server: leaveSeat (下麦)
app_server -->> NERoomA: onSeatLeave <br>(观众B成功下麦的回调)
NERoomA -->> hostClientA: onSeatLeave <br>(观众B成功下麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomB: onSeatLeave <br>(观众B成功下麦的回调)
NERoomB -->> audienceB: onSeatLeave <br>(观众B成功下麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
登录鉴权
调用 NEAuthService
实例中的login
接口进行账号登录。
NEAuthService authService = NERoomKit.getInstance().getService(NEAuthService.class);
String account="your account";
String token="your token";
authService.login(account,token, new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
}
});
示例代码中的your account
和 your token
是您的应用服务器向 NERoom 服务器申请创建账号时,返回的 userUuid
和 userToken
的值,具体请参见创建账号。
主播开播
-
主播调用
createRoom
接口创建房间。创建房间麦位
NESeatInitParams
参数说明:参数 类型 描述 seatCount int 麦位数量 seatRequestApprovalMode int 从 NESeatRequestApprovalMode
内获取麦位申请审批模式。OFF
:关闭审批模式,即成员提交申请后不需要管理员同意,可直接上麦。ON
:开启审批模式,即成员提交申请后需要管理员同意才能上麦。
seatInvitationConfirmMode int 麦位邀请确认模式。 OFF
: 关闭确认模式,即管理员邀请其他成员上麦,不需要被邀请的成员确认,可直接上麦。ON
:开启确认模式,即管理员邀请其他成员上麦,需要被邀请的成员确认,接受后方可上麦。
示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); String roomUuid="123"; String roomName="roomName"; int templateId= 21; String password = "12345"; Map<String,String> initialProperties = new HashMap<String,String>(); initialRoomProperties.put("custom-property-key0", "custom-property-value0"); initialRoomProperties.put("custom-property-key1", "custom-property-value1"); /// 设置麦位数量8个,麦位申请需要审批。房主邀请上麦不需要观众同意 NESeatInitParams seatInitParams = new NESeatInitParams(8,NESeatRequestApprovalMode.ON,NESeatInvitationConfirmMode.OFF); NECreateRoomParams params=new NECreateRoomParams(roomUuid,roomName,templateId, password,seatInitParams, initialProperties); NECreateRoomOptions options = new NECreateRoomOptions(); roomService.createRoom(params, options, new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } });
-
主播调用
joinRoom
接口加入房间。示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); String roomUuid="123"; String userName="userName"; String role="host";//从模板获取角色名称,比如PK直播的场景中的角色名为:host,invited_host,audience String password = "password"; //设置为null,表示没有密码 Map<String,String> initialProperties = new HashMap<String,String>(); initialProperties.put("custom-property-key0", "custom-property-value0"); initialProperties.put("custom-property-key1", "custom-property-value1"); roomService.joinRoom(new NEJoinRoomParams(roomUuid, userName, role, password, initialProperties), new NEJoinRoomOptions(), new NECallback2<NERoomContext>() { @Override public void onSuccess(@Nullable NERoomContext neRoomContext) { super.onSuccess(neRoomContext); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } });
-
调用
joinRtcChannel
接口加入音视频房间。示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext!=null){ roomContext.getRtcController().joinRtcChannel(new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
-
调用
addRoomListener
接口监听房间里的事件。示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext!=null){ roomContext.addRoomListener(new NERoomListener() { @Override public void onMemberRoleChanged(@NonNull NERoomMember member, @NonNull NERoomRole oldRole, @NonNull NERoomRole newRole) { } @Override public void onMemberJoinRoom(@NonNull List<? extends NERoomMember> members) { } @Override public void onMemberLeaveRoom(@NonNull List<? extends NERoomMember> members) { } @Override public void onRoomEnded(@NonNull NERoomEndReason reason) { } @Override public void onMemberJoinRtcChannel(@NonNull List<? extends NERoomMember> members) { } @Override public void onMemberLeaveRtcChannel(@NonNull List<? extends NERoomMember> members) { } @Override public void onRtcChannelError(int code) { } @Override public void onMemberJoinChatroom(@NonNull List<? extends NERoomMember> members) { } @Override public void onMemberLeaveChatroom(@NonNull List<? extends NERoomMember> members) { } @Override public void onMemberAudioMuteChanged(@NonNull NERoomMember member, boolean mute, NERoomMember operateBy) { } @Override public void onMemberVideoMuteChanged(@NonNull NERoomMember member, boolean mute, NERoomMember operateBy) { } @Override public void onMemberScreenShareStateChanged(@NonNull NERoomMember member, boolean isSharing, NERoomMember operateBy) { } @Override public void onReceiveChatroomMessages(@NonNull List<? extends NERoomMessage> messages) { } @Override public void onMemberWhiteboardStateChanged(@NonNull NERoomMember member, boolean isSharing, NERoomMember operateBy) { } @Override public void onWhiteboardError(int code, @NonNull String message) { } @Override public void onRoomLiveStateChanged(@NonNull NELiveState state) { } @Override public void onRoomLockStateChanged(boolean isLocked) { } @Override public void onMemberNameChanged(@NonNull NERoomMember member, @NonNull String name) { } @Override public void onRoomPropertiesChanged(@NonNull Map<String, String> properties) { } @Override public void onRoomPropertiesDeleted(@NonNull Map<String, String> properties) { } @Override public void onMemberPropertiesChanged(@NonNull NERoomMember member, @NonNull Map<String, String> properties) { } @Override public void onMemberPropertiesDeleted(@NonNull NERoomMember member, @NonNull Map<String, String> properties) { } @Override public void onRtcAudioVolumeIndication(@NonNull List<NEMemberVolumeInfo> volumes, int totalVolume) { } @Override public void onRtcAudioOutputDeviceChanged(@NonNull NEAudioOutputDevice device) { } }); }
-
收到加入成功的
onMemberJoinRoom
回调后,调用unmuteMyAudio
方法开启本地音频采集。示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getRtcController().unmuteMyAudio(new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
6.调用 submitSeatRequest
方法上麦。
示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().submitSeatRequest(1,new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
Log.d(TAG,"success");
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
Log.d(TAG,"error");
}
});
}
观众进入房间
-
观众调用
joinRoom
接口加入房间。 -
观众调用
addRoomListener
接口监听房间里的事件。 -
观众调用
muteMyAudio
方法关闭本地音频采集。等到上麦后,再开启本地音频采集。
麦位管理
添加麦位事件监听
调用 addSeatListener
接口,监听麦位相关的事件。
示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().addSeatListener(new NESeatEventListener() {
@Override
public void onSeatManagerAdded(List<String> managers) {
}
@Override
public void onSeatManagerRemoved(List<String> managers) {
}
@Override
public void onSeatRequestSubmitted(int seatIndex, String user) {
}
@Override
public void onSeatRequestCancelled(int seatIndex, String user) {
}
@Override
public void onSeatRequestApproved(int seatIndex, String user, String operateBy, boolean isAutoAgree) {
}
@Override
public void onSeatRequestRejected(int seatIndex, String user, String operateBy) {
}
@Override
public void onSeatInvitationReceived(int seatIndex, String user, String operateBy) {
}
@Override
public void onSeatInvitationCancelled(int seatIndex, String user, String operateBy) {
}
@Override
public void onSeatInvitationAccepted(int seatIndex,String user, boolean isAutoAgree) {
}
@Override
public void onSeatInvitationRejected(int seatIndex, String user) {
}
@Override
public void onSeatLeave(int seatIndex, String user) {
}
@Override
public void onSeatKicked(int seatIndex, String user, String operateBy) {
}
@Override
public void onSeatListChanged(List<NESeatItem> seatItems) {
}
});
}
主播邀请观众上麦
-
主播调用
sendSeatInvitation
接口邀请观众上麦。String userId = "56789"; NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getSeatController().sendSeatInvitation(userId,new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
-
主播也可以在邀请观众上麦时指定麦位。
String userId = "56789"; int index = 2; NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getSeatController().sendSeatInvitation(index,userId,new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
主播同意观众上麦
主播调用 approveSeatRequest
接口同意观众上麦。
String userId = "56789";
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().approveSeatRequest(userId,new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
Log.d(TAG,"success");
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
Log.d(TAG,"error");
}
});
}
主播拒绝观众上麦
主播调用 rejectSeatRequest
接口拒绝观众上麦。
String userId = "56789";
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().rejectSeatRequest(userId,new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
Log.d(TAG,"success");
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
Log.d(TAG,"error");
}
});
}
主播将观众移出麦位
主播调用 kickSeat
接口将观众移出麦位。
String userId = "56789";
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().kickSeat(userId,new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
Log.d(TAG,"success");
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
Log.d(TAG,"error");
}
});
}
观众申请上麦
观众调用 submitSeatRequest
接口申请上麦。
-
观众不指定麦位
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getSeatController().submitSeatRequest(new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
-
观众指定麦位
int seatIndex = 2; NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getSeatController().submitSeatRequest(seatIndex,new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
观众取消申请上麦
观众调用 cancelSeatRequest
接口取消申请上麦。
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().cancelSeatRequest(new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
Log.d(TAG,"success");
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
Log.d(TAG,"error");
}
});
}
观众主动下麦
观众调用 leaveSeat
接口下麦。
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
if (roomContext != null) {
roomContext.getSeatController().leaveSeat(new NECallback2<Unit>() {
@Override
public void onSuccess(@Nullable Unit unit) {
super.onSuccess(unit);
Log.d(TAG,"success");
}
@Override
public void onError(int code, @Nullable String message) {
super.onError(code, message);
Log.d(TAG,"error");
}
});
}
离开房间
-
调用
leaveRoom
接口离开房间。示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext!=null){ roomContext.leaveRoom(new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
-
离开房间成功后,会触发
NERoomListener.onMemberLeaveRoom
回调,通知房间内所有成员。 -
主播调用
endRoom
接口删除房间。示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext!=null){ roomContext.endRoom(new NECallback2<Unit>() { @Override public void onSuccess(@Nullable Unit unit) { super.onSuccess(unit); Log.d(TAG,"success"); } @Override public void onError(int code, @Nullable String message) { super.onError(code, message); Log.d(TAG,"error"); } }); }
-
删除房间成功后,会触发
NERoomListener
协议中的onRoomEnded
回调方法。
进阶功能
伴音
- 调用
RtcController
的startAudioMixing
方法播放伴音。
NERoomCreateAudioMixingOption
参数说明如下表所示。
参数 | 类型 | 描述 |
---|---|---|
path | String | 待播放的音乐文件的绝对路径或 URL 地址,支持本地 SD 卡中的绝对路径或 URL 地址 |
loopCount | int | 伴音循环播放的次数。1:(默认)播放一次。≤ 0:无限循环播放 |
sendEnabled | boolean | 是否将伴音发送远端,默认为 true,即远端用户可以听到该伴音。 |
sendVolume | int | 音乐文件的发送音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。 |
playbackEnabled | boolean | 是否本地播放伴音。默认为 true,即本地用户可以听到该伴音。 |
playbackVolume | int | 音乐文件的播放音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。 |
startTimeStamp | long | 音乐文件开始播放的时间,UTC 时间戳,即从1970 年 1 月 1 日 0 点 0 分 0 秒开始到事件发生时的毫秒数。默认值为 0,表示立即播放。 |
sendWithAudioType | NERoomRtcAudioStreamType | 伴音跟随音频主流还是辅流,默认跟随主流。
|
-
设置伴音的音量。
- 通过
setAudioMixingSendVolume
设置伴音的发送音量 - 通过
setAudioMixingPlaybackVolume
设置伴音的播放音量。
- 通过
-
在离开房间前调用
stopAudioMixing
结束伴音。
示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
String path = "音频文件地址";
int loopCount = 1;
boolean sendEnabled = true;
int sendVolume = 100;
boolean playbackEnabled = true;
int playbackVolume = 100;
long startTimeStamp = 0;
NERoomRtcAudioStreamType sendWithAudioType = NERoomRtcAudioStreamType.NERtcAudioStreamTypeMain
NERoomCreateAudioMixingOption options = new NERoomCreateAudioMixingOption(path,loopCount,sendEnabled,sendVolume,
playbackEnabled,playbackVolume,startTimeStamp,sendWithAudioType);
if (roomContext != null) {
roomContext.getRtcController().startAudioMixing(options);
}
if (roomContext != null) {
roomContext.getRtcController().setAudioMixingSendVolume(80);
}
if (roomContext != null) {
roomContext.getRtcController().setAudioMixingPlaybackVolume(80);
}
if (roomContext != null) {
roomContext.getRtcController().stopAudioMixing();
}
音效
-
调用
RtcController
的playEffect
方法播放音效。NERoomCreateAudioEffectOption
参数说明如下表所示。参数 类型 描述 path String 待播放的音乐文件的绝对路径或 URL 地址,支持本地 SD 卡中的绝对路径或 URL 地址 loopCount int 音效循环播放的次数。1:(默认)播放一次。≤ 0:无限循环播放 sendEnabled boolean 是否将音效发送远端,默认为 true,即远端用户可以听到该音效。 sendVolume int 音效文件的发送音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。 playbackEnabled boolean 是否本地播放音效。默认为 true,即本地用户可以听到该音效。 playbackVolume int 音乐文件的播放音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。 startTimeStamp long 音乐文件开始播放的时间,UTC 时间戳,即从1970 年 1 月 1 日 0 点 0 分 0 秒开始到事件发生时的毫秒数。默认值为 0,表示立即播放。 sendWithAudioType NERoomRtcAudioStreamType 伴音跟随音频主流还是辅流,默认跟随主流。 - NERtcAudioStreamTypeMain:伴音跟随主流
- NERtcAudioStreamTypeSub:伴音跟随辅流
-
设置音效的音量。
-
调用
setEffectSendVolume
方法设置音效文件发送音量。 -
调用
setEffectPlaybackVolume
方法设置音效文件播放音量。
-
-
在离开房间前,调用
stopAllEffects
方法停止播放所有音效文件。
示例代码如下:
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
NERoomContext roomContext = roomService.getRoomContext(roomUuid);
String path = "音效文件地址";
int loopCount = 1;
boolean sendEnabled = true;
int sendVolume = 100;
boolean playbackEnabled = true;
int playbackVolume = 100;
long startTimeStamp = 0;
NERoomRtcAudioStreamType sendWithAudioType = NERoomRtcAudioStreamType.NERtcAudioStreamTypeMain
NERoomCreateAudioEffectOption options = new NERoomCreateAudioEffectOption(path,loopCount,sendEnabled,sendVolume,
playbackEnabled,playbackVolume,startTimeStamp,sendWithAudioType);
if (roomContext != null) {
roomContext.getRtcController().playEffect(options);
}
if (roomContext != null) {
roomContext.getRtcController().setEffectSendVolume(0, 80);
}
if (roomContext != null) {
roomContext.getRtcController().setEffectPlaybackVolume(0, 80);
}
if (roomContext != null) {
roomContext.getRtcController().stopAllEffects();
}
耳返
- 通过
onRtcAudioOutputDeviceChanged
监听播放设备的变化,当监听到播放设备切换为耳机时才开启耳返。public void onRtcAudioOutputDeviceChanged(@NonNull NEAudioOutputDevice device) { switch (device) { case SPEAKER_PHONE: Log.d(TAG, "扬声器"); break; case WIRED_HEADSET: Log.d(TAG, "有线耳机"); break; case EARPIECE: Log.d(TAG, "听筒"); break; case BLUETOOTH_HEADSET: Log.d(TAG, "蓝牙耳机"); break; } }
- 调用
enableEarBack
方法开启耳返。NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); int volumn = 100; // 耳返音量 默认100 NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getRtcController().enableEarBack(volumn); }
- 调用
disableEarBack
方法关闭耳返。NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class); NERoomContext roomContext = roomService.getRoomContext(roomUuid); if (roomContext != null) { roomContext.getRtcController().disableEarBack(); }