怎么和小伙伴语音连麦,你造吗?

news/2024/10/27 22:19:40/

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

不知道anyRTC的,可以点击这里了解官网,Android文档!

demo下载

点击下载

代码还没有上传到GitHub,日后上传更新demo。

demo演示

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

主播端:点击观看

游客端:点击观看

代码实现

这个是结合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>() {@Overridepublic 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);}}}@Overridepublic 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>() {@Overridepublic 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);}}}@Overridepublic 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>() {@Overridepublic void onSuccess(Void aVoid) {Log.d(TAG, "rtm login success");mIsLogin = true;if (callback != null)callback.onSuccess(aVoid);}@Overridepublic 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>() {@Overridepublic void onSuccess(Void aVoid) {Log.d(TAG, "rtm join success");mRtmChannel = rtmChannel;getMembers();}@Overridepublic 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>() {@Overridepublic 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);}}}@Overridepublic 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>() {@Overridepublic 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);}}}@Overridepublic 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>() {@Overridepublic void onSuccess(Void aVoid) {Log.d(TAG, String.format("sendMessageToPeer %s %s", userId, content));if (callback != null)callback.onSuccess(aVoid);}@Overridepublic 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-东慕雨


http://www.ppmy.cn/news/645506.html

相关文章

昨晚尤大的连麦直播,我学到了很多!!!

昨晚朋友圈已经被连麦尤大的直播刷屏了&#xff0c;主要就是答答疑&#xff0c;聊聊天&#xff5e; 总共大概聊了一个半小时。给你们看看帅气的尤大 我也抱着 「学习」 、「长见识」 的态度去直播间听了一个多小时&#xff08;因为前半段有事&#xff0c;所以没能来得及赶上开场…

Mybatis插件拦截器实现异常条件拦截检测

背景 实际开发过程中可能会因为各种原因导致对数据库操作的代码缺少where条件&#xff0c;对于查询操作可能会导致全表扫描&#xff0c;对于更新操作可能会导致整个表的字段错误更新。大多数场景都不是符合我们的预期的。 所以做了这样一个插件(可以根据配置application.yml动…

Spring Boot中的Profile:原理、用法与示例

Spring Boot中的Profile&#xff1a;原理、用法与示例 前言 Spring Boot 是一个快速开发 Spring 应用程序的框架&#xff0c;它提供了很多有用的功能和特性。其中&#xff0c;Profile 是一个常用的功能&#xff0c;它可以根据不同的环境配置来加载不同的配置文件&#xff0c;…

Git常用命令及操作

91. Git常用命令及操作 当涉及到版本控制系统时&#xff0c;Git是最常用和流行的工具之一。下面是一些常用的Git命令和操作的示例以及简要介绍。 1. 初始化一个Git仓库&#xff1a; $ git init该命令在当前目录下创建一个新的Git仓库。 2. 克隆远程仓库到本地&#xff1a; …

GBase 8s RTSync服务端口介绍(一)

RTSync涉及多个组件&#xff0c;组件间交互以及与外界通信时都涉及通信端口。一般企业用户为了安全性&#xff0c;对端口访问都是有严格限制的&#xff0c;故部署RTSync前一般需要提前规划给RTSync使用及需要访问的服务端口。本节主要介绍RTSync使用的各类服务端口。 RTSync服…

GBase 8s性能

GBase8s高效的文件空间和磁盘管理 GBase8s通过建立多个磁盘I/O线程模拟异步的磁盘I/O来构建和读写数据库文件&#xff0c;并且I/O线程的数目是可配置的&#xff0c;它和后面提到的工作者线程是被分开管理的&#xff0c;并且专用于磁盘I/O操作。在磁盘操作上采用了两种成熟的启…

Seata介绍

Seata是一款开源的分布式事务解决方案 运行机制 Seata通过TC(事务协调者)、TM(事务管理器)、RM(资源管理器)来实现分布式事务。 【以下分析基于AT模式】 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态&#xff0c;驱动全局事务提交或回滚。 TC由se…