基于anyrtc的sdk实现直播连麦互动
前言
1.由于粘贴了较大的代码,造成内容比较长,可能会花费您较长的时间。
2.项目里面没有做权限判断,所以如果发现有页面发生崩溃可能是权限没有打开,请打开权限后再进行尝试。
3.录制的GIF画质好差,真实环境很好。
一.有图有真相
主播端 : http://d2.freep.cn/3tb_160831194207x8fa572812.gif
游客端 : http://d3.freep.cn/3tb_160831194126nt2e572812.gif
二.集成步骤,教你实现直播连麦互动
从github上https://github.com/AnyRTC/RTMPCHybirdEngine-Android下载下来,导入AS,结构如下图所示。
1.初始化RTMP引擎
MainActivity.java
RTMPCHybird.Inst().Init(getApplicationContext());
RTMPCHybird.Inst().InitEngineWithAnyrtcInfo("你的开发者ID", "liveDemo", "LslMfUyvcW8hv6NgY0n8FOWf5t1K+YWpoMzRsqwkBiE", "d6ff4b7d1b549f497a0b94cf500fd549");
以上的四个参数可以在https://www.anyrtc.io注册开发者账号并创建一个应用可得,如下图所示。你可以把它放在继承Application的onCreate()方法中。
2.获取直播列表,随时随地观看主播
MainActivity.java
1 RTMPCHttpSDK.GetLiveList(this, RTMPCHybird.Inst().GetHttpAddr(), 你的开发者ID", "liveDemo", "d6ff4b7d1b549f497a0b94cf500fd549", mRTMPCHttpCallback); 2 3 private RTMPCHttpSDK.RTMPCHttpCallback mRTMPCHttpCallback = new RTMPCHttpSDK.RTMPCHttpCallback() { 4 @Override 5 public void OnRTMPCHttpOK(String strContent) { 6 mRecyclerViewUtils.endRefreshing(); 7 try { 8 listLive.clear(); 9 JSONObject liveJson = new JSONObject(strContent); 10 JSONArray liveList = liveJson.getJSONArray("LiveList"); 11 JSONArray memberList = liveJson.getJSONArray("LiveMembers"); 12 for (int i = 0; i < liveList.length(); i++) { 13 LiveItemBean bean = new LiveItemBean(); 14 JSONObject itemJson = new JSONObject(liveList.getString(i)); 15 bean.setmHosterId(itemJson.getString("hosterId")); 16 bean.setmRtmpPullUrl(itemJson.getString("rtmp_url")); 17 bean.setmHlsUrl(itemJson.getString("hls_url")); 18 bean.setmLiveTopic(itemJson.getString("topic")); 19 bean.setmAnyrtcId(itemJson.getString("anyrtcId")); 20 bean.setmMemNumber(memberList.getInt(i)); 21 listLive.add(bean); 22 } 23 mAdapter.setDatas(listLive); 24 } catch (JSONException e) { 25 e.printStackTrace(); 26 } 27 } 28 29 @Override 30 public void OnRTMPCHttpFailed(int code) { 31 32 } 33 };
以上代码可以获取所有正在直播列表名单
3.发起直播,成就自己的直播梦
a.你可以自己设置推流地址和拉流地址,这里我直接用他提供的地址了
RTMPUrlHelper.java
1 public class RTMPUrlHelper { 2 /** 3 * rtmp 推流地址 4 */ 5 public static final String RTMP_PUSH_URL = "rtmp://192.168.7.207:1935/live/%s"; 6 /** 7 * rtmp 拉流地址 8 */ 9 public static final String RTMP_PULL_URL = "rtmp://192.168.7.207:1935/live/%s"; 10 /** 11 * hls 地址 12 */ 13 public static final String HLS_URL = "http://192.169.7.207/live/%s.m3u8"; 14 /** 15 * 分享页面url地址 16 */ 17 public static final String SHARE_WEB_URL = "http://123.59.68.21/rtmpc-demo/?%s"; 18 }
b.这里要使用到你创建应用的anyrtcid、推流拉流hls地址、直播名称。到这一步你已经离你的直播梦完成了一半了<( ̄︶ ̄)>。
PreStartLiveActivity.java
1 String anyrtcId = RTMPCHttpSDK.getRandomString(12); 2 String rtmpPushUrl = String.format(RTMPUrlHelper.RTMP_PUSH_URL, anyrtcId); 3 String rtmpPullUrl = String.format(RTMPUrlHelper.RTMP_PULL_URL, anyrtcId); 4 String hlsUrl = String.format(RTMPUrlHelper.HLS_URL, anyrtcId); 5 JSONObject item = new JSONObject(); 6 try { 7 item.put("hosterId", "hostID"); 8 item.put("rtmp_url", rtmpPullUrl); 9 item.put("hls_url", hlsUrl); 10 item.put("topic", topic); 11 item.put("anyrtcId", anyrtcId); 12 } catch (JSONException e) { 13 e.printStackTrace(); 14 } 15 Bundle bundle = new Bundle(); 16 bundle.putString("hosterId", "hostID"); 17 bundle.putString("rtmp_url", rtmpPushUrl); 18 bundle.putString("hls_url", hlsUrl); 19 bundle.putString("topic", topic); 20 bundle.putString("andyrtcId", anyrtcId); 21 bundle.putString("userData", item.toString()); 22 Intent intent = new Intent(this, HosterActivity.class); 23 intent.putExtras(bundle); 24 startActivity(intent);
4.你的直播梦就在此就要实现了,打起精神(⊙o⊙)哦
a.从上个Activity拿到传过来的数据
HosterActivity.java
1 mHosterId = getIntent().getExtras().getString("hosterId"); 2 mRtmpPushUrl = getIntent().getExtras().getString("rtmp_url"); 3 mAnyrtcId = getIntent().getExtras().getString("andyrtcId"); 4 mUserData = getIntent().getExtras().getString("userData"); 5 mHlsUrl = getIntent().getExtras().getString("hls_url"); 6 mTopic = getIntent().getExtras().getString("topic");
这里的R.id.rl_rtmpc_videos表示打开手机摄像头捕获的像呈现的地方,如下图所示。
HosterActivity.java
1 mVideoView = new RTMPCVideoView((RelativeLayout) findViewById(R.id.rl_rtmpc_videos), RTMPCHybird.Inst().Egl(), true); 2 mVideoView.setBtnCloseEvent(mBtnVideoCloseEvent); 3 mHosterKit = new RTMPCHosterKit(this, mHosterListener); 4 5 { 6 VideoRenderer render = mVideoView.OnRtcOpenLocalRender(); 7 mHosterKit.SetVideoCapturer(render.GetRenderPointer(), true); 8 }
b.这里是创建和音频管理器,将照顾音频路由,音频模式,音频设备枚举等、存储现有的音频设置更改音频模式达到最佳的VoIP性能。
1 { 2 // Create and audio manager that will take care of audio routing, 3 // audio modes, audio device enumeration etc. 4 mRtmpAudioManager = RTMPAudioManager.create(this, new Runnable() { 5 // This method will be called each time the audio state (number 6 // and 7 // type of devices) has been changed. 8 @Override 9 public void run() { 10 onAudioManagerChangedState(); 11 } 12 }); 13 // Store existing audio settings and change audio mode to 14 // MODE_IN_COMMUNICATION for best possible VoIP performance. 15 mRtmpAudioManager.init(); 16 mRtmpAudioManager.setAudioDevice(RTMPAudioManager.AudioDevice.SPEAKER_PHONE); 17 } 18 19 mStartRtmp = true; 20 /** 21 * 开始推流 22 */ 23 mHosterKit.StartPushRtmpStream(mRtmpPushUrl); 24 /** 25 * 建立RTC连线连接 26 */ 27 mHosterKit.OpenRTCLine(mAnyrtcId, mHosterId, mUserData);
c.主播的直播回调接口
mHosterKit = new RTMPCHosterKit(this, mHosterListener);
这句代码是主播直播的回调接口,可以做连麦、取消连麦、接收消息和弹幕消息、实时观看人数和人员上下线等。实用的操作一般再此实行。
HosterActivity.java
1 /** 2 * 主播回调信息接口 3 */ 4 private RTMPCAbstractHoster mHosterListener = new RTMPCAbstractHoster() { 5 /** 6 * rtmp连接成功 7 */ 8 @Override 9 public void OnRtmpStreamOKCallback() { 10 HosterActivity.this.runOnUiThread(new Runnable() { 11 @Override 12 public void run() { 13 ((TextView) findViewById(R.id.txt_rtmp_connection_status)).setText(R.string.str_rtmp_connect_success); 14 } 15 }); 16 } 17 18 /** 19 * rtmp 重连次数 20 * @param times 重连次数 21 */ 22 @Override 23 public void OnRtmpStreamReconnectingCallback(final int times) { 24 HosterActivity.this.runOnUiThread(new Runnable() { 25 @Override 26 public void run() { 27 ((TextView) findViewById(R.id.txt_rtmp_connection_status)).setText(String.format(getString(R.string.str_reconnect_times), times)); 28 } 29 }); 30 } 31 32 /** 33 * rtmp 推流状态 34 * @param delayMs 推流延时 35 * @param netBand 推流码流 36 */ 37 @Override 38 public void OnRtmpStreamStatusCallback(final int delayMs, final int netBand) { 39 HosterActivity.this.runOnUiThread(new Runnable() { 40 @Override 41 public void run() { 42 ((TextView) findViewById(R.id.txt_rtmp_status)).setText(String.format(getString(R.string.str_rtmp_status), delayMs, netBand)); 43 } 44 }); 45 } 46 47 /** 48 * rtmp推流失败回调 49 * @param code 50 */ 51 @Override 52 public void OnRtmpStreamFailedCallback(int code) { 53 HosterActivity.this.runOnUiThread(new Runnable() { 54 @Override 55 public void run() { 56 ((TextView) findViewById(R.id.txt_rtmp_connection_status)).setTextColor(R.color.yellow); 57 ((TextView) findViewById(R.id.txt_rtmp_connection_status)).setText(R.string.str_rtmp_connect_failed); 58 } 59 }); 60 } 61 62 /** 63 * rtmp 推流关闭回调 64 */ 65 @Override 66 public void OnRtmpStreamClosedCallback() { 67 finish(); 68 } 69 70 /** 71 * RTC 连接回调 72 * @param code 0: 连接成功 73 * @param strErr 原因 74 */ 75 @Override 76 public void OnRTCOpenLineResultCallback(final int code, String strErr) { 77 HosterActivity.this.runOnUiThread(new Runnable() { 78 @Override 79 public void run() { 80 if (code == 0) { 81 ((TextView) findViewById(R.id.txt_rtc_connection_status)).setText(R.string.str_rtc_connect_success); 82 } else { 83 ((TextView) findViewById(R.id.txt_rtc_connection_status)).setTextColor(R.color.yellow); 84 ((TextView) findViewById(R.id.txt_rtc_connection_status)).setText(R.string.str_rtmp_connect_failed); 85 } 86 } 87 }); 88 } 89 90 /** 91 * 游客有申请连线回调 92 * 93 * @param strLivePeerID 94 * @param strCustomID 95 * @param strUserData 96 */ 97 @Override 98 public void OnRTCApplyToLineCallback(final String strLivePeerID, final String strCustomID, final String strUserData) { 99 HosterActivity.this.runOnUiThread(new Runnable() { 100 @Override 101 public void run() { 102 ShowDialog(HosterActivity.this, strLivePeerID, strCustomID); 103 } 104 }); 105 } 106 107 /** 108 * 视频连线超过4人时回调 109 * @param strLivePeerID 110 * @param strCustomID 111 * @param strUserData 112 */ 113 @Override 114 public void OnRTCLineFullCallback(final String strLivePeerID, String strCustomID, String strUserData) { 115 HosterActivity.this.runOnUiThread(new Runnable() { 116 @Override 117 public void run() { 118 Toast.makeText(HosterActivity.this, getString(R.string.str_connect_full), Toast.LENGTH_LONG).show(); 119 mHosterKit.RejectRTCLine(strLivePeerID, true); 120 } 121 }); 122 } 123 124 /** 125 * 游客挂断连线回调 126 * @param strLivePeerID 127 */ 128 @Override 129 public void OnRTCCancelLineCallback(String strLivePeerID) { 130 HosterActivity.this.runOnUiThread(new Runnable() { 131 @Override 132 public void run() { 133 Toast.makeText(HosterActivity.this, getString(R.string.str_line_disconnect), Toast.LENGTH_LONG).show(); 134 } 135 }); 136 } 137 138 /** 139 * RTC 连接关闭回调 140 * @param code 207:请去AnyRTC官网申请账号,如有疑问请联系客服! 141 * @param strReason 142 */ 143 @Override 144 public void OnRTCLineClosedCallback(final int code, String strReason) { 145 HosterActivity.this.runOnUiThread(new Runnable() { 146 @Override 147 public void run() { 148 if (code == 207) { 149 Toast.makeText(HosterActivity.this, getString(R.string.str_apply_anyrtc_account), Toast.LENGTH_LONG).show(); 150 finish(); 151 } 152 } 153 }); 154 } 155 156 /** 157 * 连线接通时的视频图像回调; 158 * @param strLivePeerID 159 */ 160 @Override 161 public void OnRTCOpenVideoRenderCallback(final String strLivePeerID) { 162 HosterActivity.this.runOnUiThread(new Runnable() { 163 @Override 164 public void run() { 165 final VideoRenderer render = mVideoView.OnRtcOpenRemoteRender(strLivePeerID); 166 if (null != render) { 167 mHosterKit.SetRTCVideoRender(strLivePeerID, render.GetRenderPointer()); 168 } 169 } 170 }); 171 } 172 173 /** 174 * 连线关闭时的视频图像回调; 175 * @param strLivePeerID 176 */ 177 @Override 178 public void OnRTCCloseVideoRenderCallback(final String strLivePeerID) { 179 HosterActivity.this.runOnUiThread(new Runnable() { 180 @Override 181 public void run() { 182 mHosterKit.SetRTCVideoRender(strLivePeerID, 0); 183 mVideoView.OnRtcRemoveRemoteRender(strLivePeerID); 184 } 185 }); 186 } 187 188 /** 189 * 消息回调 190 * @param strCustomID 消息的发送者id 191 * @param strCustomName 消息的发送者昵称 192 * @param strCustomHeader 消息的发送者头像url 193 * @param strMessage 消息内容 194 */ 195 @Override 196 public void OnRTCUserMessageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strMessage) { 197 HosterActivity.this.runOnUiThread(new Runnable() { 198 @Override 199 public void run() { 200 addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strMessage)); 201 } 202 }); 203 } 204 205 /** 206 * 弹幕回调 207 * @param strCustomID 弹幕的发送者id 208 * @param strCustomName 弹幕的发送者昵称 209 * @param strCustomHeader 弹幕的发送者头像url 210 * @param strBarrage 弹幕的内容 211 */ 212 @Override 213 public void OnRTCUserBarrageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strBarrage) { 214 HosterActivity.this.runOnUiThread(new Runnable() { 215 @Override 216 public void run() { 217 addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strBarrage)); 218 IDanmakuItem item = new DanmakuItem(HosterActivity.this, new SpannableString(strBarrage), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1); 219 mDanmakuView.addItemToHead(item); 220 } 221 }); 222 } 223 224 /** 225 * 直播观看总人数回调 226 * @param totalMembers 观看总人数 227 */ 228 @Override 229 public void OnRTCMemberListWillUpdateCallback(final int totalMembers) { 230 HosterActivity.this.runOnUiThread(new Runnable() { 231 @Override 232 public void run() { 233 ((TextView) findViewById(R.id.txt_watcher_number)).setText(String.format(getString(R.string.str_live_watcher_number), totalMembers)); 234 } 235 }); 236 } 237 238 /** 239 * 人员上下线回调 240 * @param strCustomID 241 * @param strUserData 242 */ 243 @Override 244 public void OnRTCMemberCallback(final String strCustomID, final String strUserData) { 245 HosterActivity.this.runOnUiThread(new Runnable() { 246 @Override 247 public void run() { 248 try { 249 JSONObject userData = new JSONObject(strUserData); 250 addChatMessageList(new ChatMessageBean(userData.getString("nickName"), "", userData.getString("headUrl"), "")); 251 } catch (JSONException e) { 252 e.printStackTrace(); 253 } 254 } 255 }); 256 } 257 258 @Override 259 public void OnRTCMemberListUpdateDoneCallback() { 260 261 } 262 };
d.一些对应直播回调的方法
接下来就要说对应这些回调的方法了,这里可以做关闭直播、直播分享、切换摄像头和发送消息。
HosterActivity.java
1 public void OnBtnClicked(View btn) { 2 if (btn.getId() == R.id.btn_close) { 3 mStartRtmp = false; 4 mHosterKit.StopRtmpStream(); 5 finish(); 6 } else if (btn.getId() == R.id.btn_copy_hls) { 7 int index = mHlsUrl.lastIndexOf("/"); 8 int lastIndex = mHlsUrl.lastIndexOf("."); 9 String shareUrl = String.format(RTMPUrlHelper.SHARE_WEB_URL, mHlsUrl.substring(index + 1, lastIndex)); 10 mShareHelper.shareWeiXin(mTopic, shareUrl); 11 } else if (btn.getId() == R.id.btn_switch_camera) { 12 mHosterKit.SwitchCamera(); 13 } else if (btn.getId() == R.id.btn_send_message) { 14 String message = editMessage.getText().toString(); 15 editMessage.setText(""); 16 if (message.equals("")) { 17 return; 18 } 19 if (mCheckBarrage.isChecked()) { 20 mHosterKit.SendBarrage(mNickname, "", message); 21 IDanmakuItem item = new DanmakuItem(HosterActivity.this, new SpannableString(message), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1); 22 mDanmakuView.addItemToHead(item); 23 } else { 24 mHosterKit.SendUserMsg(mNickname, "", message); 25 } 26 27 addChatMessageList(new ChatMessageBean(mNickname, mNickname, "", message)); 28 } else if (btn.getId() == R.id.iv_host_text) { 29 btnChat.clearFocus(); 30 vaBottomBar.setDisplayedChild(1); 31 editMessage.requestFocus(); 32 softKeyboardUtil.showKeyboard(HosterActivity.this, editMessage); 33 } 34 }
5.主播端的已经完成了,现在该轮到你的小伙伴们看你直播~(≧▽≦)/~啦啦啦
a.前面已经说了,我们可以实时获取开启直播的主播,点击列表就可以观看主播直播。
MainActivity.java
1 @Override 2 public void onItemChildClick(ViewGroup viewGroup, View view, int i) { 3 Intent it = new Intent(this, GuestActivity.class); 4 Bundle bundle = new Bundle(); 5 bundle.putString("hls_url", listLive.get(i).getmHlsUrl()); 6 bundle.putString("rtmp_url", listLive.get(i).getmRtmpPullUrl()); 7 bundle.putString("anyrtcId", listLive.get(i).getmAnyrtcId()); 8 bundle.putString("userData", new JSONObject().toString()); 9 bundle.putString("topic", listLive.get(i).getmLiveTopic()); 10 it.putExtras(bundle); 11 startActivity(it); 12 }
b.再实现游客端这个项目基本上就完成了,是不是有点小激动?
与主播端一样,拿上个Activity传过来的数据,其实这里代码与主播端的代码基本上可以说是一模一样,看完之后你应该会有我这样的体会。
GuestActivity.java
1 mNickname = ((HybirdApplication)HybirdApplication.app()).getmNickname(); 2 mRtmpPullUrl = getIntent().getExtras().getString("rtmp_url"); 3 mAnyrtcId = getIntent().getExtras().getString("anyrtcId"); 4 mHlsUrl = getIntent().getExtras().getString("hls_url"); 5 mGuestId = mNickname;//getIntent().getExtras().getString("guestId"); 6 7 mTopic = getIntent().getExtras().getString("topic");
1 mVideoView = new RTMPCVideoView((RelativeLayout) findViewById(R.id.rl_rtmpc_videos), RTMPCHybird.Inst().Egl(), false); 2 3 mVideoView.setBtnCloseEvent(mBtnVideoCloseEvent); 4 /** 5 * 初始化rtmp播放器 6 */ 7 mGuestKit = new RTMPCGuestKit(this, mGuestListener); 8 VideoRenderer render = mVideoView.OnRtcOpenLocalRender(); 9 10 { 11 // Create and audio manager that will take care of audio routing, 12 // audio modes, audio device enumeration etc. 13 mRtmpAudioManager = RTMPAudioManager.create(this, new Runnable() { 14 // This method will be called each time the audio state (number 15 // and 16 // type of devices) has been changed. 17 @Override 18 public void run() { 19 onAudioManagerChangedState(); 20 } 21 }); 22 // Store existing audio settings and change audio mode to 23 // MODE_IN_COMMUNICATION for best possible VoIP performance. 24 mRtmpAudioManager.init(); 25 mRtmpAudioManager.setAudioDevice(RTMPAudioManager.AudioDevice.SPEAKER_PHONE); 26 } 27 28 mUserData = new JSONObject(); 29 try { 30 mUserData.put("nickName", mNickname); 31 mUserData.put("headUrl", ""); 32 } catch (JSONException e) { 33 e.printStackTrace(); 34 } 35 36 /** 37 * 开始播放rtmp流 38 */ 39 mGuestKit.StartRtmpPlay(mRtmpPullUrl, render.GetRenderPointer()); 40 /** 41 * 开启RTC连线连接 42 */ 43 mGuestKit.JoinRTCLine(mAnyrtcId, mGuestId, mUserData.toString());
c.观看直播的回调接口
mGuestKit = new RTMPCGuestKit(this, mGuestListener);
这句代码是观看直播的回调接口,可以做申请连麦、断开连麦、接收消息和弹幕消息、实时观看人数和人员上下线等。实用的操作一般再此实行。
GuestActivity.java
1 /** 2 * 观看直播回调信息接口 3 */ 4 private RTMPCAbstractGuest mGuestListener = new RTMPCAbstractGuest() { 5 6 /** 7 * rtmp 连接成功 8 */ 9 @Override 10 public void OnRtmplayerOKCallback() { 11 } 12 13 /** 14 * rtmp 当前播放状态 15 * @param cacheTime 当前缓存时间 16 * @param curBitrate 当前播放器码流 17 */ 18 @Override 19 public void OnRtmplayerStatusCallback(int cacheTime, int curBitrate) { 20 21 } 22 23 /** 24 * rtmp 播放缓冲区时长 25 * @param time 缓冲时间 26 */ 27 @Override 28 public void OnRtmplayerCacheCallback(int time) { 29 30 } 31 32 /** 33 * rtmp 播放器关闭 34 * @param errcode 35 */ 36 @Override 37 public void OnRtmplayerClosedCallback(int errcode) { 38 39 } 40 41 /** 42 * 游客RTC 状态回调 43 * @param code 回调响应码:0:正常;101:主播未开启直播; 44 * @param strReason 原因描述 45 */ 46 @Override 47 public void OnRTCJoinLineResultCallback(final int code, String strReason) { 48 GuestActivity.this.runOnUiThread(new Runnable() { 49 @Override 50 public void run() { 51 if (code == 0) { 52 53 } else if (code == 101) { 54 Toast.makeText(GuestActivity.this, R.string.str_hoster_not_live, Toast.LENGTH_LONG).show(); 55 mHandler.sendEmptyMessageDelayed(CLOSED, 2000); 56 } 57 } 58 }); 59 } 60 61 /** 62 * 游客申请连线回调 63 * @param code 0:申请连线成功;-1:主播拒绝连线 64 */ 65 @Override 66 public void OnRTCApplyLineResultCallback(final int code) { 67 GuestActivity.this.runOnUiThread(new Runnable() { 68 @Override 69 public void run() { 70 if (code == 0) { 71 VideoRenderer render = mVideoView.OnRtcOpenRemoteRender("LocalCameraRender"); 72 mGuestKit.SetVideoCapturer(render.GetRenderPointer(), true); 73 } else if (code == -1) { 74 Toast.makeText(GuestActivity.this, R.string.str_hoster_refused, Toast.LENGTH_LONG).show(); 75 mStartLine = false; 76 mBtnConnect.setText(R.string.str_connect_hoster); 77 } 78 } 79 }); 80 } 81 82 /** 83 * 当与主播连线成功时,其他用户连线回调 84 * @param strLivePeerID 85 * @param strCustomID 86 * @param strUserData 87 */ 88 @Override 89 public void OnRTCOtherLineOpenCallback(String strLivePeerID, String strCustomID, String strUserData) { 90 91 } 92 93 /** 94 * 其他用户连线回调 95 * @param strLivePeerID 96 */ 97 @Override 98 public void OnRTCOtherLineCloseCallback(String strLivePeerID) { 99 100 } 101 102 /** 103 * 挂断连线回调 104 */ 105 @Override 106 public void OnRTCHangupLineCallback() { 107 //主播连线断开 108 GuestActivity.this.runOnUiThread(new Runnable() { 109 @Override 110 public void run() { 111 mGuestKit.HangupRTCLine(); 112 mVideoView.OnRtcRemoveRemoteRender("LocalCameraRender"); 113 mStartLine = false; 114 mBtnConnect.setText(R.string.str_connect_hoster); 115 } 116 }); 117 } 118 119 /** 120 * 主播已离开回调 121 * @param code 122 * @param strReason 123 */ 124 @Override 125 public void OnRTCLineLeaveCallback(int code, String strReason) { 126 //主播关闭直播 127 GuestActivity.this.runOnUiThread(new Runnable() { 128 @Override 129 public void run() { 130 Toast.makeText(GuestActivity.this, R.string.str_hoster_leave, Toast.LENGTH_LONG).show(); 131 mHandler.sendEmptyMessageDelayed(CLOSED, 2000); 132 } 133 }); 134 } 135 136 /** 137 * 连线接通后回调 138 * @param strLivePeerID 139 */ 140 @Override 141 public void OnRTCOpenVideoRenderCallback(final String strLivePeerID) { 142 GuestActivity.this.runOnUiThread(new Runnable() { 143 @Override 144 public void run() { 145 final VideoRenderer render = mVideoView.OnRtcOpenRemoteRender(strLivePeerID); 146 mGuestKit.SetRTCVideoRender(strLivePeerID, render.GetRenderPointer()); 147 } 148 }); 149 } 150 151 /** 152 * 连线关闭后图像回调 153 * @param strLivePeerID 154 */ 155 @Override 156 public void OnRTCCloseVideoRenderCallback(final String strLivePeerID) { 157 GuestActivity.this.runOnUiThread(new Runnable() { 158 @Override 159 public void run() { 160 mGuestKit.SetRTCVideoRender(strLivePeerID, 0); 161 mVideoView.OnRtcRemoveRemoteRender(strLivePeerID); 162 } 163 }); 164 } 165 166 /** 167 * 消息回调 168 * @param strCustomID 消息的发送者id 169 * @param strCustomName 消息的发送者昵称 170 * @param strCustomHeader 消息的发送者头像url 171 * @param strMessage 消息内容 172 */ 173 @Override 174 public void OnRTCUserMessageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strMessage) { 175 GuestActivity.this.runOnUiThread(new Runnable() { 176 @Override 177 public void run() { 178 addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strMessage)); 179 } 180 }); 181 } 182 183 /** 184 * 弹幕回调 185 * @param strCustomID 弹幕的发送者id 186 * @param strCustomName 弹幕的发送者昵称 187 * @param strCustomHeader 弹幕的发送者头像url 188 * @param strBarrage 弹幕的内容 189 */ 190 @Override 191 public void OnRTCUserBarrageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strBarrage) { 192 GuestActivity.this.runOnUiThread(new Runnable() { 193 @Override 194 public void run() { 195 addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strBarrage)); 196 IDanmakuItem item = new DanmakuItem(GuestActivity.this, new SpannableString(strBarrage), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1); 197 mDanmakuView.addItemToHead(item); 198 } 199 }); 200 } 201 202 /** 203 * 观看直播的总人数回调 204 * @param totalMembers 观看直播的总人数 205 */ 206 @Override 207 public void OnRTCMemberListWillUpdateCallback(final int totalMembers) { 208 GuestActivity.this.runOnUiThread(new Runnable() { 209 @Override 210 public void run() { 211 ((TextView) findViewById(R.id.txt_watcher_number)).setText(String.format(getString(R.string.str_live_watcher_number), totalMembers)); 212 } 213 }); 214 } 215 216 /** 217 * 人员上下线回调 218 * @param strCustomID 219 * @param strUserData 220 */ 221 @Override 222 public void OnRTCMemberCallback(final String strCustomID, final String strUserData) { 223 GuestActivity.this.runOnUiThread(new Runnable() { 224 @Override 225 public void run() { 226 try { 227 JSONObject userData = new JSONObject(strUserData); 228 addChatMessageList(new ChatMessageBean(userData.getString("nickName"), "", userData.getString("headUrl"), "")); 229 } catch (JSONException e) { 230 e.printStackTrace(); 231 } 232 } 233 }); 234 } 235 236 @Override 237 public void OnRTCMemberListUpdateDoneCallback() { 238 239 } 240 };
d.一些对应观看直播回调的方法
接下来就要说对应这些回调的方法了,这里可以做直播分享、申请连麦、断开连麦和发送消息。
GuestActivity.java
1 public void OnBtnClicked(View btn) { 2 if(btn.getId() == R.id.btn_copy_hls) { 3 int index = mHlsUrl.lastIndexOf("/"); 4 int lastIndex = mHlsUrl.lastIndexOf("."); 5 String shareUrl = String.format(RTMPUrlHelper.SHARE_WEB_URL, mHlsUrl.substring(index + 1, lastIndex)); 6 mShareHelper.shareWeiXin(mTopic, shareUrl); 7 } else if (btn.getId() == R.id.btn_line) { 8 if (!mStartLine) { 9 10 JSONObject json = new JSONObject(); 11 try { 12 json.put("guestId", mNickname); 13 } catch (JSONException e) { 14 e.printStackTrace(); 15 } 16 /** 17 * 向主播申请连线 18 */ 19 mGuestKit.ApplyRTCLine(json.toString()); 20 mStartLine = true; 21 mBtnConnect.setText(R.string.str_hangup_connect); 22 } else { 23 /** 24 * 挂断连线 25 */ 26 mGuestKit.HangupRTCLine(); 27 mVideoView.OnRtcRemoveRemoteRender("LocalCameraRender"); 28 mStartLine = false; 29 mBtnConnect.setText(R.string.str_connect_hoster); 30 } 31 } else if (btn.getId() == R.id.btn_send_message) { 32 String message = editMessage.getText().toString(); 33 editMessage.setText(""); 34 if (message.equals("")) { 35 return; 36 } 37 if (mCheckBarrage.isChecked()) { 38 mGuestKit.SendBarrage(mNickname, "", message); 39 IDanmakuItem item = new DanmakuItem(GuestActivity.this, new SpannableString(message), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1); 40 mDanmakuView.addItemToHead(item); 41 } else { 42 mGuestKit.SendUserMsg(mNickname, "", message); 43 } 44 addChatMessageList(new ChatMessageBean(mNickname, mNickname, "", message)); 45 } else if (btn.getId() == R.id.iv_host_text) { 46 btnChat.clearFocus(); 47 vaBottomBar.setDisplayedChild(1); 48 editMessage.requestFocus(); 49 softKeyboardUtil.showKeyboard(GuestActivity.this, editMessage); 50 } 51 }
结束语
对于这个基于Anyrtc sdk的直播RTMPCHybirdEngine-Android核心的几个类基本上介绍完成,我在此仅仅是大概介绍了几点,可以让你大概了解这个SDK的直播流程,方便您快速上手。
转载请注明出处,谢谢!