前段时间开发出一个语音连麦的小功能demo,平常自己玩玩,和小伙伴语音连麦,很好用,哈哈哈使用的也是anyRTC的API功能废话少说,开整,下面我们就来聊聊关于聊天连麦语音?接下来我们就一起去了解一下吧!

聊天连麦语音(怎么和小伙伴语音连麦)

聊天连麦语音

前段时间开发出一个语音连麦的小功能demo,平常自己玩玩,和小伙伴语音连麦,很好用,哈哈哈。使用的也是anyRTC的API功能。废话少说,开整!

不知道anyRTC的,可以点击这里了解官网(https://www.anyrtc.io/),Android文档(https://docs.anyrtc.io/cn/Live/api-ref/rtc_android/android_overview?platform=Android)!

demo下载
  • 点击下载(https://www.pgyer.com/fRjW)
  • 代码还没有上传到GitHub,日后上传更新demo。
demo演示

看波视频~ 省的给大家截图,视频来的实在,简单明了

主播端:点击观看(https://www.bilibili.com/video/BV1Nh41127Vz)

游客端:点击观看(https://www.bilibili.com/video/BV1KK4y1W7bW)

代码实现

这个是结合anyRTC的后台服务的,这个也是服务也是对外开放的

1.注册登录

我这边使用的杨振杰封装的HTTP:

implementation 'com.yanzhenjie:okalle:0.1.7'

  • 注册

public void signUp(){ JSONObject params = new JSONObject(); try { params.put("sex",0); params.put("userName", Build.MODEL); } catch (JSONException e) { e.printStackTrace(); } Kalle.post(String.format(Constants.SERVER,"user/signUp")) .addHeader(Constants.CONTENT_TYPE,"application/json") .body(new JsonBody(params.toString())) .perform(new SimpleCallback<String>() { @Override public void onResponse(SimpleResponse<String, String> response) { Log.i(TAG, "onResponse:signUp response =" response.succeed()); if (response.succeed().contains("success")){ signUpBean =gson.fromJson(response.succeed(),SignUpBean.class); if (signUpBean !=null){ String uid =signUpBean.getData().getUid(); SpUtil.putString(Constants.UID,uid); signIn(uid); } } } @Override public void onException(Exception e) { super.onException(e); e.printStackTrace(); } }); }

  • 登入

public void signIn(String uid){ JSONObject params = new JSONObject(); try { params.put("cType",1); params.put("pkg",ARApplication.the().getApplicationContext().getPackageName()); params.put("uid",uid); } catch (JSONException e) { e.printStackTrace(); } Kalle.post(String.format(Constants.SERVER,"user/signIn")) .addHeader(Constants.CONTENT_TYPE,"application/json") .body(new JsonBody(params.toString())) .perform(new SimpleCallback<String>() { @Override public void onResponse(SimpleResponse<String, String> response) { Log.i(TAG, "onResponse: signIn success =" response.succeed()); if (response.succeed().contains("success")){ signInBean =gson.fromJson(response.succeed(),SignInBean.class); getRoomList(signInBean); if (loginListener !=null){ loginListener.loginSuccess(signInBean); } } } @Override public void onException(Exception e) { super.onException(e); e.printStackTrace(); } }); }

2.主播创建和获取房间
  • 创建房间

a.首先需要初始化Rtc和Rtm实例

//创建RTC实例,appid 可以去anyRTC官网注册 mRtcEngine =RtcEngine.create(mContext, appId,mEventHandler); //创建RTM实例,appid同上 mRtmClient =RtmClient.createInstance(mContext, appId,mClientListener);

b.然后登录AR RTM

public void login(String rtmToken,String userId, final ResultCallback<Void> callback){ if (mRtmClient !=null){ if (mIsLogin) { if (callback != null) callback.onSuccess(null); return; } mRtmClient.login(rtmToken, String.valueOf(userId), new ResultCallback<Void>() { @Override public void onSuccess(Void aVoid) { Log.d(TAG, "rtm login success"); mIsLogin = true; if (callback != null) callback.onSuccess(aVoid); } @Override public void onFailure(ErrorInfo errorInfo) { Log.e(TAG, String.format("rtm join %s", errorInfo.getErrorDescription())); mIsLogin = false; if (callback != null) callback.onFailure(errorInfo); } }); } }

c.然后主播加入房间

加入RTC和RTM频道

RTC:音视频通话

RTM:实时消息

//加入RTM频道,完成主播和游客实时消息的发送 public void joinChannel(final String channelId, ResultCallback<Void> callback) { if (mRtmClient != null) { leaveChannel(); Log.w(TAG, String.format("joinChannel %s", channelId)); try { final RtmChannel rtmChannel = mRtmClient.createChannel(channelId, mChannelListener); if (rtmChannel == null) return; rtmChannel.join(new ResultCallback<Void>() { @Override public void onSuccess(Void aVoid) { Log.d(TAG, "rtm join success"); mRtmChannel = rtmChannel; getMembers(); } @Override public void onFailure(ErrorInfo errorInfo) { Log.e(TAG, String.format("rtm join %s", errorInfo.getErrorDescription())); //AlertUtil.showToast("RTM login failed, see the log to get more info"); mRtmChannel = rtmChannel; } }); } catch (Exception ex) { ex.printStackTrace(); } } } //加入RTC频道,实现主播和游客语音连麦 public void joinChannel(String rtcToken,String channelId, String userId) { if (mRtcEngine != null){ mRtcEngine.setClientRole(Constants.CLIENT_ROLE_BROADCASTER); mRtcEngine.joinChannel(rtcToken, channelId, null, userId); mRtcEngine.muteLocalAudioStream(false); //mRtcEngine.setEnableSpeakerphone(true); createStreamingInstance(); } }

  • 获取房间列表

//获取房间列表 public void getRoomList(SignInBean signInBean){ JSONObject params = new JSONObject(); try { params.put("count", Integer.MAX_VALUE); params.put("rType", Constants.R_TYPE_LIVE); } catch (JSONException e) { e.printStackTrace(); } Kalle.post(String.format(Constants.SERVER,"user/getRoomList")) .addHeader(Constants.CONTENT_TYPE,"application/json") .addHeader(Constants.AUTHORIZATION,"Bearer " signInBean.getData().getUserToken()) .body(new JsonBody(params.toString())) .perform(new SimpleCallback<String>() { @Override public void onResponse(SimpleResponse<String, String> response) { Log.i(TAG, "onResponse: getRoomList =" response.succeed()); if (response.succeed().contains("success")){ roomListBean =gson.fromJson(response.succeed(), RoomListBean.class); if (roomListener !=null){ roomListener.showRoomList(roomListBean); } } } @Override public void onException(Exception e) { super.onException(e); e.printStackTrace(); Log.i(TAG, "onException: ===> =" e.getMessage()); } }); }

注:上面展示语音连麦的部分功能,创建房间的是主播,下拉刷新出来加入房间的是游客

3.游客加入房间

加入房间第一步就是加入RTM频道,然后申请上麦后,主播同意后,再加入RTC频道,进行语音通话。

  • 加入房间

//调用服务接口,加入房间,接入有人进入房间 public void joinRoom(String roomId,String roomName,String pullRtmpUrl){ JSONObject params = new JSONObject(); try { params.put("cType",1); params.put("pkg",ARApplication.the().getApplicationContext().getPackageName()); params.put("roomId",roomId); } catch (JSONException e) { e.printStackTrace(); } Kalle.post(String.format(Constants.SERVER,"user/joinRoom")) .addHeader(Constants.CONTENT_TYPE,"application/json") .addHeader(Constants.AUTHORIZATION,"Bearer " signInBean.getData().getUserToken()) .body(new JsonBody(params.toString())) .perform(new SimpleCallback<String>() { @Override public void onResponse(SimpleResponse<String, String> response) { Log.i(TAG, "onResponse: joinRoom data =" response.succeed()); if (response.succeed().contains("success")){ joinRoomBean =gson.fromJson(response.succeed(),JoinRoomBean.class); if (roomListener !=null){ roomListener.joinRoom(joinRoomBean,roomId,roomName,pullRtmpUrl); } } } @Override public void onException(Exception e) { super.onException(e); e.printStackTrace(); Log.i(TAG, "onException: e=" e.getMessage()); } }); }

然后进行RTM加入房间,和上面主播加入房间一样。

  • 申请上麦流程

a.游客点击上麦,给主播发一条RTM消息,通知主播“我要上麦”

//点击按钮事件,进行发送消息 try { jsonObject.put("cmd","apply"); } catch (JSONException e) { e.printStackTrace(); } mChatRoomManager.getRtmManager().sendMessageToPeer(mAnchorId,jsonObject.toString(),null); //发送P to P消息 public void sendMessageToPeer(final String userId, final String content, final ResultCallback<Void> callback) { if (TextUtils.isEmpty(userId)) return; if (mRtmClient != null) { RtmMessage message = mRtmClient.createMessage(content); mRtmClient.sendMessageToPeer(userId, message, null, new ResultCallback<Void>() { @Override public void onSuccess(Void aVoid) { Log.d(TAG, String.format("sendMessageToPeer %s %s", userId, content)); if (callback != null) callback.onSuccess(aVoid); } @Override public void onFailure(ErrorInfo errorInfo) { Log.e(TAG, String.format("sendMessageToPeer %s", errorInfo.getErrorDescription())); if (callback != null) callback.onFailure(errorInfo); } }); } }

b.主播收到消息,然后弹出对话框,然后进行:确定上麦、拒绝上麦的操作!

//主播收到消息,进行的逻辑操作! applyDialog =new ApplyDialog(this, "连麦申请", mChannelData.getName(userId) "申请连麦", "拒绝", "确定", () -> { try { object.put("cmd",Constants.MIC_REJECT_LINE); } catch (JSONException e) { e.printStackTrace(); } mChatRoomManager.getRtmManager().sendMessageToPeer(userId,object.toString(),null); }, () -> { try { object.put("cmd",Constants.MIC_ACCEPT_LINE); } catch (JSONException e) { e.printStackTrace(); } mChatRoomManager.getRtmManager().sendMessageToPeer(userId,object.toString(),null); }); applyDialog.show();

c.主播同意上麦后,游客加入RTC频道,进行连麦。

//游客收到同意上麦的操作逻辑 micState = MIC_STATE_DOWN; isJoinMic =true; autoTipDialog =new AutoTipDialog(this,R.drawable.success_tip,"同意上麦"); autoTipDialog.show(); mJoinMic.setImageResource(R.drawable.down_mic); String rtcToken = Optional.ofNullable(serverManager) .map(ARServerManager::getJoinRoomBean) .map(JoinRoomBean::getData) .map(JoinRoomBean.DataBean::getRoom) .map(JoinRoomBean.DataBean.RoomBeans::getRtcToken) .orElse(""); Log.i(TAG, "onAcceptLineUpdated: rtcToken =" rtcToken); mChatRoomManager.joinRtcChannel(rtcToken,roomId); //j加入RTC频道 mediaPlayerKit.mute(true); if (isMic){ mChatMic.setImageResource(R.drawable.mic_close); }else { mChatMic.setImageResource(R.drawable.mic_open); } mChatRoomManager.getRtcManager().muteLocalAudioStream(isMic); if (isSpeaker){ mSpeaker.setImageResource(R.drawable.speaker_close); }else { mSpeaker.setImageResource(R.drawable.speaker_open); } mChatRoomManager.getRtcManager().getRtcEngine().setEnableSpeakerphone(!isSpeaker); rlMusic.setVisibility(View.VISIBLE); mChatMic.setVisibility(View.VISIBLE); mSpeaker.setVisibility(View.GONE); mFrameLayout.setVisibility(View.VISIBLE); rvGuestLog.setVisibility(View.GONE); mLogList.add(new LogBean(R.drawable.circle,getDate(),"上麦成功"));

这个时候就可以和你的小伙伴进行语音操作啦!

最后释放RTC和RTM资源,主播退出删除房间,游客退出房间就可以啦!

如有不懂的地方,欢迎大家留言。

作者:anyRTC-东慕雨

,