基于anyrtc的sdk实现直播连麦互动

前言

1.由于粘贴了较大的代码,造成内容比较长,可能会花费您较长的时间。 
2.项目里面没有做权限判断,所以如果发现有页面发生崩溃可能是权限没有打开,请打开权限后再进行尝试。 
3.录制的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

 RTMPCHttpSDK.GetLiveList(this, RTMPCHybird.Inst().GetHttpAddr(), 你的开发者ID", "liveDemo",     "d6ff4b7d1b549f497a0b94cf500fd549", mRTMPCHttpCallback);

     private RTMPCHttpSDK.RTMPCHttpCallback mRTMPCHttpCallback = new RTMPCHttpSDK.RTMPCHttpCallback() {
@Override
public void OnRTMPCHttpOK(String strContent) {
mRecyclerViewUtils.endRefreshing();
try {
listLive.clear();
JSONObject liveJson = new JSONObject(strContent);
JSONArray liveList = liveJson.getJSONArray("LiveList");
JSONArray memberList = liveJson.getJSONArray("LiveMembers");
for (int i = 0; i < liveList.length(); i++) {
LiveItemBean bean = new LiveItemBean();
JSONObject itemJson = new JSONObject(liveList.getString(i));
bean.setmHosterId(itemJson.getString("hosterId"));
bean.setmRtmpPullUrl(itemJson.getString("rtmp_url"));
bean.setmHlsUrl(itemJson.getString("hls_url"));
bean.setmLiveTopic(itemJson.getString("topic"));
bean.setmAnyrtcId(itemJson.getString("anyrtcId"));
bean.setmMemNumber(memberList.getInt(i));
listLive.add(bean);
}
mAdapter.setDatas(listLive);
} catch (JSONException e) {
e.printStackTrace();
}
} @Override
public void OnRTMPCHttpFailed(int code) { }
};

以上代码可以获取所有正在直播列表名单

3.发起直播,成就自己的直播梦
a.你可以自己设置推流地址和拉流地址,这里我直接用他提供的地址了

RTMPUrlHelper.java

 public class RTMPUrlHelper {
/**
* rtmp 推流地址
*/
public static final String RTMP_PUSH_URL = "rtmp://192.168.7.207:1935/live/%s";
/**
* rtmp 拉流地址
*/
public static final String RTMP_PULL_URL = "rtmp://192.168.7.207:1935/live/%s";
/**
* hls 地址
*/
public static final String HLS_URL = "http://192.169.7.207/live/%s.m3u8";
/**
* 分享页面url地址
*/
public static final String SHARE_WEB_URL = "http://123.59.68.21/rtmpc-demo/?%s";
}
b.这里要使用到你创建应用的anyrtcid、推流拉流hls地址、直播名称。到这一步你已经离你的直播梦完成了一半了<( ̄︶ ̄)>。

PreStartLiveActivity.java

 String anyrtcId = RTMPCHttpSDK.getRandomString(12);
String rtmpPushUrl = String.format(RTMPUrlHelper.RTMP_PUSH_URL, anyrtcId);
String rtmpPullUrl = String.format(RTMPUrlHelper.RTMP_PULL_URL, anyrtcId);
String hlsUrl = String.format(RTMPUrlHelper.HLS_URL, anyrtcId);
JSONObject item = new JSONObject();
try {
item.put("hosterId", "hostID");
item.put("rtmp_url", rtmpPullUrl);
item.put("hls_url", hlsUrl);
item.put("topic", topic);
item.put("anyrtcId", anyrtcId);
} catch (JSONException e) {
e.printStackTrace();
}
Bundle bundle = new Bundle();
bundle.putString("hosterId", "hostID");
bundle.putString("rtmp_url", rtmpPushUrl);
bundle.putString("hls_url", hlsUrl);
bundle.putString("topic", topic);
bundle.putString("andyrtcId", anyrtcId);
bundle.putString("userData", item.toString());
Intent intent = new Intent(this, HosterActivity.class);
intent.putExtras(bundle);
startActivity(intent);
4.你的直播梦就在此就要实现了,打起精神(⊙o⊙)哦
a.从上个Activity拿到传过来的数据

HosterActivity.java

  mHosterId = getIntent().getExtras().getString("hosterId");
mRtmpPushUrl = getIntent().getExtras().getString("rtmp_url");
mAnyrtcId = getIntent().getExtras().getString("andyrtcId");
mUserData = getIntent().getExtras().getString("userData");
mHlsUrl = getIntent().getExtras().getString("hls_url");
mTopic = getIntent().getExtras().getString("topic");

这里的R.id.rl_rtmpc_videos表示打开手机摄像头捕获的像呈现的地方,如下图所示。 
HosterActivity.java

 mVideoView = new RTMPCVideoView((RelativeLayout) findViewById(R.id.rl_rtmpc_videos), RTMPCHybird.Inst().Egl(), true);
mVideoView.setBtnCloseEvent(mBtnVideoCloseEvent);
mHosterKit = new RTMPCHosterKit(this, mHosterListener); {
VideoRenderer render = mVideoView.OnRtcOpenLocalRender();
mHosterKit.SetVideoCapturer(render.GetRenderPointer(), true);
}

b.这里是创建和音频管理器,将照顾音频路由,音频模式,音频设备枚举等、存储现有的音频设置更改音频模式达到最佳的VoIP性能。
    {
// Create and audio manager that will take care of audio routing,
// audio modes, audio device enumeration etc.
mRtmpAudioManager = RTMPAudioManager.create(this, new Runnable() {
// This method will be called each time the audio state (number
// and
// type of devices) has been changed.
@Override
public void run() {
onAudioManagerChangedState();
}
});
// Store existing audio settings and change audio mode to
// MODE_IN_COMMUNICATION for best possible VoIP performance.
mRtmpAudioManager.init();
mRtmpAudioManager.setAudioDevice(RTMPAudioManager.AudioDevice.SPEAKER_PHONE);
} mStartRtmp = true;
/**
* 开始推流
*/
mHosterKit.StartPushRtmpStream(mRtmpPushUrl);
/**
* 建立RTC连线连接
*/
mHosterKit.OpenRTCLine(mAnyrtcId, mHosterId, mUserData);
c.主播的直播回调接口

mHosterKit = new RTMPCHosterKit(this, mHosterListener); 
这句代码是主播直播的回调接口,可以做连麦、取消连麦、接收消息和弹幕消息、实时观看人数和人员上下线等。实用的操作一般再此实行。 
HosterActivity.java

 /**
* 主播回调信息接口
*/
private RTMPCAbstractHoster mHosterListener = new RTMPCAbstractHoster() {
/**
* rtmp连接成功
*/
@Override
public void OnRtmpStreamOKCallback() {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.txt_rtmp_connection_status)).setText(R.string.str_rtmp_connect_success);
}
});
} /**
* rtmp 重连次数
* @param times 重连次数
*/
@Override
public void OnRtmpStreamReconnectingCallback(final int times) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.txt_rtmp_connection_status)).setText(String.format(getString(R.string.str_reconnect_times), times));
}
});
} /**
* rtmp 推流状态
* @param delayMs 推流延时
* @param netBand 推流码流
*/
@Override
public void OnRtmpStreamStatusCallback(final int delayMs, final int netBand) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.txt_rtmp_status)).setText(String.format(getString(R.string.str_rtmp_status), delayMs, netBand));
}
});
} /**
* rtmp推流失败回调
* @param code
*/
@Override
public void OnRtmpStreamFailedCallback(int code) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.txt_rtmp_connection_status)).setTextColor(R.color.yellow);
((TextView) findViewById(R.id.txt_rtmp_connection_status)).setText(R.string.str_rtmp_connect_failed);
}
});
} /**
* rtmp 推流关闭回调
*/
@Override
public void OnRtmpStreamClosedCallback() {
finish();
} /**
* RTC 连接回调
* @param code 0: 连接成功
* @param strErr 原因
*/
@Override
public void OnRTCOpenLineResultCallback(final int code, String strErr) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (code == 0) {
((TextView) findViewById(R.id.txt_rtc_connection_status)).setText(R.string.str_rtc_connect_success);
} else {
((TextView) findViewById(R.id.txt_rtc_connection_status)).setTextColor(R.color.yellow);
((TextView) findViewById(R.id.txt_rtc_connection_status)).setText(R.string.str_rtmp_connect_failed);
}
}
});
} /**
* 游客有申请连线回调
*
* @param strLivePeerID
* @param strCustomID
* @param strUserData
*/
@Override
public void OnRTCApplyToLineCallback(final String strLivePeerID, final String strCustomID, final String strUserData) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
ShowDialog(HosterActivity.this, strLivePeerID, strCustomID);
}
});
} /**
* 视频连线超过4人时回调
* @param strLivePeerID
* @param strCustomID
* @param strUserData
*/
@Override
public void OnRTCLineFullCallback(final String strLivePeerID, String strCustomID, String strUserData) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HosterActivity.this, getString(R.string.str_connect_full), Toast.LENGTH_LONG).show();
mHosterKit.RejectRTCLine(strLivePeerID, true);
}
});
} /**
* 游客挂断连线回调
* @param strLivePeerID
*/
@Override
public void OnRTCCancelLineCallback(String strLivePeerID) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HosterActivity.this, getString(R.string.str_line_disconnect), Toast.LENGTH_LONG).show();
}
});
} /**
* RTC 连接关闭回调
* @param code 207:请去AnyRTC官网申请账号,如有疑问请联系客服!
* @param strReason
*/
@Override
public void OnRTCLineClosedCallback(final int code, String strReason) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (code == 207) {
Toast.makeText(HosterActivity.this, getString(R.string.str_apply_anyrtc_account), Toast.LENGTH_LONG).show();
finish();
}
}
});
} /**
* 连线接通时的视频图像回调;
* @param strLivePeerID
*/
@Override
public void OnRTCOpenVideoRenderCallback(final String strLivePeerID) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
final VideoRenderer render = mVideoView.OnRtcOpenRemoteRender(strLivePeerID);
if (null != render) {
mHosterKit.SetRTCVideoRender(strLivePeerID, render.GetRenderPointer());
}
}
});
} /**
* 连线关闭时的视频图像回调;
* @param strLivePeerID
*/
@Override
public void OnRTCCloseVideoRenderCallback(final String strLivePeerID) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mHosterKit.SetRTCVideoRender(strLivePeerID, 0);
mVideoView.OnRtcRemoveRemoteRender(strLivePeerID);
}
});
} /**
* 消息回调
* @param strCustomID 消息的发送者id
* @param strCustomName 消息的发送者昵称
* @param strCustomHeader 消息的发送者头像url
* @param strMessage 消息内容
*/
@Override
public void OnRTCUserMessageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strMessage) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strMessage));
}
});
} /**
* 弹幕回调
* @param strCustomID 弹幕的发送者id
* @param strCustomName 弹幕的发送者昵称
* @param strCustomHeader 弹幕的发送者头像url
* @param strBarrage 弹幕的内容
*/
@Override
public void OnRTCUserBarrageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strBarrage) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strBarrage));
IDanmakuItem item = new DanmakuItem(HosterActivity.this, new SpannableString(strBarrage), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1);
mDanmakuView.addItemToHead(item);
}
});
} /**
* 直播观看总人数回调
* @param totalMembers 观看总人数
*/
@Override
public void OnRTCMemberListWillUpdateCallback(final int totalMembers) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.txt_watcher_number)).setText(String.format(getString(R.string.str_live_watcher_number), totalMembers));
}
});
} /**
* 人员上下线回调
* @param strCustomID
* @param strUserData
*/
@Override
public void OnRTCMemberCallback(final String strCustomID, final String strUserData) {
HosterActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject userData = new JSONObject(strUserData);
addChatMessageList(new ChatMessageBean(userData.getString("nickName"), "", userData.getString("headUrl"), ""));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} @Override
public void OnRTCMemberListUpdateDoneCallback() { }
};
d.一些对应直播回调的方法

接下来就要说对应这些回调的方法了,这里可以做关闭直播、直播分享、切换摄像头和发送消息。 
HosterActivity.java

 public void OnBtnClicked(View btn) {
if (btn.getId() == R.id.btn_close) {
mStartRtmp = false;
mHosterKit.StopRtmpStream();
finish();
} else if (btn.getId() == R.id.btn_copy_hls) {
int index = mHlsUrl.lastIndexOf("/");
int lastIndex = mHlsUrl.lastIndexOf(".");
String shareUrl = String.format(RTMPUrlHelper.SHARE_WEB_URL, mHlsUrl.substring(index + 1, lastIndex));
mShareHelper.shareWeiXin(mTopic, shareUrl);
} else if (btn.getId() == R.id.btn_switch_camera) {
mHosterKit.SwitchCamera();
} else if (btn.getId() == R.id.btn_send_message) {
String message = editMessage.getText().toString();
editMessage.setText("");
if (message.equals("")) {
return;
}
if (mCheckBarrage.isChecked()) {
mHosterKit.SendBarrage(mNickname, "", message);
IDanmakuItem item = new DanmakuItem(HosterActivity.this, new SpannableString(message), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1);
mDanmakuView.addItemToHead(item);
} else {
mHosterKit.SendUserMsg(mNickname, "", message);
} addChatMessageList(new ChatMessageBean(mNickname, mNickname, "", message));
} else if (btn.getId() == R.id.iv_host_text) {
btnChat.clearFocus();
vaBottomBar.setDisplayedChild(1);
editMessage.requestFocus();
softKeyboardUtil.showKeyboard(HosterActivity.this, editMessage);
}
}
5.主播端的已经完成了,现在该轮到你的小伙伴们看你直播~(≧▽≦)/~啦啦啦
a.前面已经说了,我们可以实时获取开启直播的主播,点击列表就可以观看主播直播。

MainActivity.java

 @Override
public void onItemChildClick(ViewGroup viewGroup, View view, int i) {
Intent it = new Intent(this, GuestActivity.class);
Bundle bundle = new Bundle();
bundle.putString("hls_url", listLive.get(i).getmHlsUrl());
bundle.putString("rtmp_url", listLive.get(i).getmRtmpPullUrl());
bundle.putString("anyrtcId", listLive.get(i).getmAnyrtcId());
bundle.putString("userData", new JSONObject().toString());
bundle.putString("topic", listLive.get(i).getmLiveTopic());
it.putExtras(bundle);
startActivity(it);
}
b.再实现游客端这个项目基本上就完成了,是不是有点小激动?

与主播端一样,拿上个Activity传过来的数据,其实这里代码与主播端的代码基本上可以说是一模一样,看完之后你应该会有我这样的体会。 
GuestActivity.java

 mNickname = ((HybirdApplication)HybirdApplication.app()).getmNickname();
mRtmpPullUrl = getIntent().getExtras().getString("rtmp_url");
mAnyrtcId = getIntent().getExtras().getString("anyrtcId");
mHlsUrl = getIntent().getExtras().getString("hls_url");
mGuestId = mNickname;//getIntent().getExtras().getString("guestId"); mTopic = getIntent().getExtras().getString("topic");
 mVideoView = new RTMPCVideoView((RelativeLayout) findViewById(R.id.rl_rtmpc_videos), RTMPCHybird.Inst().Egl(), false);

         mVideoView.setBtnCloseEvent(mBtnVideoCloseEvent);
/**
* 初始化rtmp播放器
*/
mGuestKit = new RTMPCGuestKit(this, mGuestListener);
VideoRenderer render = mVideoView.OnRtcOpenLocalRender(); {
// Create and audio manager that will take care of audio routing,
// audio modes, audio device enumeration etc.
mRtmpAudioManager = RTMPAudioManager.create(this, new Runnable() {
// This method will be called each time the audio state (number
// and
// type of devices) has been changed.
@Override
public void run() {
onAudioManagerChangedState();
}
});
// Store existing audio settings and change audio mode to
// MODE_IN_COMMUNICATION for best possible VoIP performance.
mRtmpAudioManager.init();
mRtmpAudioManager.setAudioDevice(RTMPAudioManager.AudioDevice.SPEAKER_PHONE);
} mUserData = new JSONObject();
try {
mUserData.put("nickName", mNickname);
mUserData.put("headUrl", "");
} catch (JSONException e) {
e.printStackTrace();
} /**
* 开始播放rtmp流
*/
mGuestKit.StartRtmpPlay(mRtmpPullUrl, render.GetRenderPointer());
/**
* 开启RTC连线连接
*/
mGuestKit.JoinRTCLine(mAnyrtcId, mGuestId, mUserData.toString());
c.观看直播的回调接口

mGuestKit = new RTMPCGuestKit(this, mGuestListener); 
这句代码是观看直播的回调接口,可以做申请连麦、断开连麦、接收消息和弹幕消息、实时观看人数和人员上下线等。实用的操作一般再此实行。 
GuestActivity.java

 /**
* 观看直播回调信息接口
*/
private RTMPCAbstractGuest mGuestListener = new RTMPCAbstractGuest() { /**
* rtmp 连接成功
*/
@Override
public void OnRtmplayerOKCallback() {
} /**
* rtmp 当前播放状态
* @param cacheTime 当前缓存时间
* @param curBitrate 当前播放器码流
*/
@Override
public void OnRtmplayerStatusCallback(int cacheTime, int curBitrate) { } /**
* rtmp 播放缓冲区时长
* @param time 缓冲时间
*/
@Override
public void OnRtmplayerCacheCallback(int time) { } /**
* rtmp 播放器关闭
* @param errcode
*/
@Override
public void OnRtmplayerClosedCallback(int errcode) { } /**
* 游客RTC 状态回调
* @param code 回调响应码:0:正常;101:主播未开启直播;
* @param strReason 原因描述
*/
@Override
public void OnRTCJoinLineResultCallback(final int code, String strReason) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (code == 0) { } else if (code == 101) {
Toast.makeText(GuestActivity.this, R.string.str_hoster_not_live, Toast.LENGTH_LONG).show();
mHandler.sendEmptyMessageDelayed(CLOSED, 2000);
}
}
});
} /**
* 游客申请连线回调
* @param code 0:申请连线成功;-1:主播拒绝连线
*/
@Override
public void OnRTCApplyLineResultCallback(final int code) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (code == 0) {
VideoRenderer render = mVideoView.OnRtcOpenRemoteRender("LocalCameraRender");
mGuestKit.SetVideoCapturer(render.GetRenderPointer(), true);
} else if (code == -1) {
Toast.makeText(GuestActivity.this, R.string.str_hoster_refused, Toast.LENGTH_LONG).show();
mStartLine = false;
mBtnConnect.setText(R.string.str_connect_hoster);
}
}
});
} /**
* 当与主播连线成功时,其他用户连线回调
* @param strLivePeerID
* @param strCustomID
* @param strUserData
*/
@Override
public void OnRTCOtherLineOpenCallback(String strLivePeerID, String strCustomID, String strUserData) { } /**
* 其他用户连线回调
* @param strLivePeerID
*/
@Override
public void OnRTCOtherLineCloseCallback(String strLivePeerID) { } /**
* 挂断连线回调
*/
@Override
public void OnRTCHangupLineCallback() {
//主播连线断开
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mGuestKit.HangupRTCLine();
mVideoView.OnRtcRemoveRemoteRender("LocalCameraRender");
mStartLine = false;
mBtnConnect.setText(R.string.str_connect_hoster);
}
});
} /**
* 主播已离开回调
* @param code
* @param strReason
*/
@Override
public void OnRTCLineLeaveCallback(int code, String strReason) {
//主播关闭直播
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(GuestActivity.this, R.string.str_hoster_leave, Toast.LENGTH_LONG).show();
mHandler.sendEmptyMessageDelayed(CLOSED, 2000);
}
});
} /**
* 连线接通后回调
* @param strLivePeerID
*/
@Override
public void OnRTCOpenVideoRenderCallback(final String strLivePeerID) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
final VideoRenderer render = mVideoView.OnRtcOpenRemoteRender(strLivePeerID);
mGuestKit.SetRTCVideoRender(strLivePeerID, render.GetRenderPointer());
}
});
} /**
* 连线关闭后图像回调
* @param strLivePeerID
*/
@Override
public void OnRTCCloseVideoRenderCallback(final String strLivePeerID) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mGuestKit.SetRTCVideoRender(strLivePeerID, 0);
mVideoView.OnRtcRemoveRemoteRender(strLivePeerID);
}
});
} /**
* 消息回调
* @param strCustomID 消息的发送者id
* @param strCustomName 消息的发送者昵称
* @param strCustomHeader 消息的发送者头像url
* @param strMessage 消息内容
*/
@Override
public void OnRTCUserMessageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strMessage) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strMessage));
}
});
} /**
* 弹幕回调
* @param strCustomID 弹幕的发送者id
* @param strCustomName 弹幕的发送者昵称
* @param strCustomHeader 弹幕的发送者头像url
* @param strBarrage 弹幕的内容
*/
@Override
public void OnRTCUserBarrageCallback(final String strCustomID, final String strCustomName, final String strCustomHeader, final String strBarrage) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
addChatMessageList(new ChatMessageBean(strCustomID, strCustomName, "", strBarrage));
IDanmakuItem item = new DanmakuItem(GuestActivity.this, new SpannableString(strBarrage), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1);
mDanmakuView.addItemToHead(item);
}
});
} /**
* 观看直播的总人数回调
* @param totalMembers 观看直播的总人数
*/
@Override
public void OnRTCMemberListWillUpdateCallback(final int totalMembers) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.txt_watcher_number)).setText(String.format(getString(R.string.str_live_watcher_number), totalMembers));
}
});
} /**
* 人员上下线回调
* @param strCustomID
* @param strUserData
*/
@Override
public void OnRTCMemberCallback(final String strCustomID, final String strUserData) {
GuestActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject userData = new JSONObject(strUserData);
addChatMessageList(new ChatMessageBean(userData.getString("nickName"), "", userData.getString("headUrl"), ""));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
} @Override
public void OnRTCMemberListUpdateDoneCallback() { }
};
d.一些对应观看直播回调的方法

接下来就要说对应这些回调的方法了,这里可以做直播分享、申请连麦、断开连麦和发送消息。 
GuestActivity.java

 public void OnBtnClicked(View btn) {
if(btn.getId() == R.id.btn_copy_hls) {
int index = mHlsUrl.lastIndexOf("/");
int lastIndex = mHlsUrl.lastIndexOf(".");
String shareUrl = String.format(RTMPUrlHelper.SHARE_WEB_URL, mHlsUrl.substring(index + 1, lastIndex));
mShareHelper.shareWeiXin(mTopic, shareUrl);
} else if (btn.getId() == R.id.btn_line) {
if (!mStartLine) { JSONObject json = new JSONObject();
try {
json.put("guestId", mNickname);
} catch (JSONException e) {
e.printStackTrace();
}
/**
* 向主播申请连线
*/
mGuestKit.ApplyRTCLine(json.toString());
mStartLine = true;
mBtnConnect.setText(R.string.str_hangup_connect);
} else {
/**
* 挂断连线
*/
mGuestKit.HangupRTCLine();
mVideoView.OnRtcRemoveRemoteRender("LocalCameraRender");
mStartLine = false;
mBtnConnect.setText(R.string.str_connect_hoster);
}
} else if (btn.getId() == R.id.btn_send_message) {
String message = editMessage.getText().toString();
editMessage.setText("");
if (message.equals("")) {
return;
}
if (mCheckBarrage.isChecked()) {
mGuestKit.SendBarrage(mNickname, "", message);
IDanmakuItem item = new DanmakuItem(GuestActivity.this, new SpannableString(message), mDanmakuView.getWidth(), 0, R.color.yellow_normol, 18, 1);
mDanmakuView.addItemToHead(item);
} else {
mGuestKit.SendUserMsg(mNickname, "", message);
}
addChatMessageList(new ChatMessageBean(mNickname, mNickname, "", message));
} else if (btn.getId() == R.id.iv_host_text) {
btnChat.clearFocus();
vaBottomBar.setDisplayedChild(1);
editMessage.requestFocus();
softKeyboardUtil.showKeyboard(GuestActivity.this, editMessage);
}
}
结束语

对于这个基于Anyrtc sdk的直播RTMPCHybirdEngine-Android核心的几个类基本上介绍完成,我在此仅仅是大概介绍了几点,可以让你大概了解这个SDK的直播流程,方便您快速上手。

转载请注明出处,谢谢!

基于anyrtc的sdk实现直播连麦互动的更多相关文章

  1. anyRTC Web SDK 实现音视频呼叫功能

    前言 大家好,今天小编带给大家一个基于 anyRTC Web SDK 实现音视频呼叫的功能(本项目采用vue开发). 前提条件 在开始写代码之前还需要做一些准备工作,如果你之前没有使用过 anyRTC ...

  2. 点聚合功能---基于ARCGIS RUNTIME SDK FOR ANDROID

    一直不更新博客的原因,如果一定要找一个,那就是忙,或者说懒癌犯了. 基于ArcGIS RunTime SDK for Android的点聚合功能,本来是我之前做过的一个系统里面的一个小部分,今天抽出一 ...

  3. 将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj

    原文 将 WPF.UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj 写过 .NET Standard 类库或者 .NET Core 程序的 ...

  4. 推荐一款语音直播连麦App YAMI

    推荐一款语音直播连麦App YAMI 1 介绍 功能描述:[语音直播]:海量超有才主播,游戏送礼抢红包,嗨玩不停:[多人聊天室]:连麦交友处CP,主持人带你玩游戏,边聊边玩:[语音交友]:海量声优专属 ...

  5. 从QQ音乐开发,探讨如何利用腾讯云SDK在直播中加入视频动画

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云+社区专栏 看着精彩的德甲赛事,突然裁判一声口哨,球赛断掉了,屏幕开始自动播放"吃麦趣鸡盒,看德甲比赛&q ...

  6. (UWP开发)基于Windows10 Anniversary SDK创造出位于可视化层的DropShadow

    Windows.UI.Composition API是可以从任何通用Windows平台应用程序调用的声明性保留模式API,从而可以直接在应用程序中创建合成对象.动画和效果. Composition A ...

  7. 一对一voip,直播连麦,在线会议,兼容webrtc,IM音视频

    功能 IM消息系统 一对一 高清音视频实时通信,可无缝切换P2P传输,节省服务器带宽 一对多互动直播 多对多在线会议 手机实时录屏传输 高度定制化 网络检测,动态码率与动态帧率,抗网络抖动,微信级效果 ...

  8. 基于EasyNVR摄像机无插件直播流媒体服务器实现类似于单点登录功能的免登录直播功能

    提出问题 EasyNVR是一套摄像机无插件直播的流媒体服务器软件,他可以接入各种各样的摄像机,再经过转化统一输出无插件化直播的RTMP.HLS.HTTP-FLV流,同时,EasyNVR为了数据安全,提 ...

  9. 基于华为物联网IOT的应用开发 --- 基于.net 的SDK封装

    最近,物联网的概念比较热门,一大批厂商抢着占领物联网的高低,包括有华为物联网.阿里云物联网.腾讯物联网.AWS物联网等等,无法一一列举,一般物联网包含设备侧开发.平台侧开发.应用侧开发,三个部分构成了 ...

随机推荐

  1. Which are in?

    Which are in? Given two arrays of strings a1 and a2 return a sorted array in lexicographical order a ...

  2. 我的第一个Struts程序

    1.程序结构 2.各种文件 LoginAction.java package com.tfj.action; public class LoginAction { private String use ...

  3. UpdatePanel 无刷新弹出窗口

    UpdatePanel下解决提示框不弹出的方法 用户体验上既想页面不刷新,也希望同时能够看到操作的效果(弹出提示框)! ①不刷新,我们可以使用UpdatePanel ②弹出消息框,这个有很多的方式:我 ...

  4. App Store 加急审核方式

    https://developer.apple.com/contact/app-store/?topic=expedite 1:理由一般是用户安全问题或者崩溃问题成功率会高一些. 如果是崩溃问题,你最 ...

  5. 【HtmlParser】HtmlParser使用

    转载 http://www.cnblogs.com/549294286/archive/2012/09/04/2670601.html HTMLParser的核心模块是org.htmlparser.P ...

  6. Microsoft StreamInsight install

    Microsoft StreamInsight 是一个开发平台.安装之后,可通过一组 .NET 命名空间来得到 SDK.有关 StreamInsight 应用程序开发的其他信息,请参阅上面列出的资源. ...

  7. [King.yue]Ext.JS 弹出窗体取值赋值

    //从Grid取值 var name = Ext.getCmp(gridGridID).getView().getSelectionModel().getSelection()[0].data.Nam ...

  8. 快速定位隐蔽的sql性能问题及调优【转载】

    在前几天,有个开发同事问我一个问题,其实也算是技术救援,他说在有个job数据处理的频率比较高,在测试环境中很难定位出在哪有问题,而且速度也还能接 受,但是在生产环境中总是会慢一些,希望我能在测试环境中 ...

  9. 【JS】Intermediate1:The DOM

    1.DOM(The Document Object Model) A way to manipulate the structure and style of an HTML page. It rep ...

  10. 算法导论学习-Dynamic Programming

    转载自:http://blog.csdn.net/speedme/article/details/24231197 1. 什么是动态规划 ------------------------------- ...