快速实现视频通话 编辑文档

在进行本部分前,请确认已阅读《环境配置》相关章节。
本章针对Java开发者集成QttAudio视频SDK,适用于Android应用开发。


Android实现视频通话

本节介绍如何使用 QttAudio 视频 SDK 在你的 app 里实现视频通话。

1.创建可视化界面

在用户界面中,你需要设置两个帧布局(FrameLayout),分别展示本地视图和远端视图。因此,将 /app/res/layout/activity_main.xml 文件中的内容替换成如下代码:

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<FrameLayout
android:id="@+id/local_video_view_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" />

<FrameLayout
android:id="@+id/remote_video_view_container"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:background="@android:color/darker_gray" />

</RelativeLayout>

2. 初始化SDK

请开发者使用自己的AppKey进行初始化


//ChannelObserver设置,频道事件的监听
ChannelObserverImpl channelObserver = new ChannelObserverImpl();
ChannelEngine channelEngine = ChannelEngine.GetChannelInstance(getApplicationContext(),
"your appkey",channelObserver);
if (channelEngine == null) {
Log.d("qtt_debug", "QttChannel初始化失败,原因是"+ChannelFactory.GetError());
return;
}
Log.d("qtt_debug", "QttChannel初始化成功");

3. 监听频道事件

实现ChannelObserver接口:

private class ChannelObserverImpl implements ChannelObserver {
@Override
public void onJoinSuccess(String roomName, long uid, ChannelRole role, boolean muted,String name) {
Log.d("qtt_rtc", "加入频道成功 roomId:" + roomName + " uid:" + uid + " role:" + role + " ");
//TODO 实现处理自己加入频道成功逻辑
}

@Override
public void onReJoinSuccess(String roomName, long uid, ChannelRole role, boolean muted,String name) {
Log.d("qtt_rtc", "重新加入频道成功 roomId:" + roomName + " uid:" + uid + " role:" + role + " ");
//TODO 实现处理自己重新加入频道成功逻辑
}

@Override
public void onOtherJoin(long uid, ChannelRole role, boolean muted,String name) {
Log.d("qtt_rtc", "uid " + uid + " 加入频道 role:" + role);
//TODO 实现处理他人加入频道成功逻辑
}

@Override
public void onJoinFail(final int code, final String message) {
Log.d("qtt_rtc", "加入频道失败 " + message);
//TODO 实现处理自己加入频道失败逻辑
}

@Override
public void onConnectionBreak() {
Log.d("qtt_rtc", "网络打断");
//TODO 实现处理网络被打断逻辑
}

@Override
public void onConnectionLost() {
Log.d("qtt_rtc", "网络失去连接");
//TODO 实现处理网络失去连接逻辑
}

@Override
public void onError(int err, String message) {
Log.d("qtt_rtc", "错误消息 " + message);
//TODO 实现处理SDK内部错误的逻辑
}

@Override
public void onWarning(int warn, String message) {
Log.d("qtt_rtc", "警告消息 " + message);
//TODO 实现处理SDK内部警告的逻辑
}

@Override
public void onLeave() {
Log.d("qtt_rtc", "离开频道");
//TODO 实现处理自己离开频道的逻辑
}

@Override
public void onOtherLeave(long uid, ChannelRole role,String name) {
Log.d("qtt_rtc", "远端用户离开频道 " + uid);
//TODO 实现处理远端用户离开频道的逻辑
}

@Override
public void onTalkingVolumeIndication(VolumeInfo[] volumeInfos, int size) {
Log.d("qtt_rtc", "用户说话");
//TODO 实现处理用户说话提示的逻辑
}

@Override
public void onMuteStatusChanged(long uid, boolean muted,String name) {
if (uid == 0) {
Log.d("qtt_rtc", "自己静麦状态变化: " + muted);
//TODO 实现处理自己静麦状态变化的逻辑
} else {
Log.d("qtt_rtc", "远端用户 " + uid + " 静麦状态变化: " + muted);
//TODO 实现处理远端用户静麦状态变化的逻辑
}
}

@Override
public void onRoleStatusChanged(long uid, ChannelRole role,String name) {
if (uid == 0) {
Log.d("qtt_rtc", "自己角色状态变化: " + role);
//TODO 实现处理自己角色状态变化的逻辑
} else {
Log.d("qtt_rtc", "远端用户 " + uid + " 角色状态变化: " + role);
//TODO 实现处理远端用户角色状态变化的逻辑
}
}
@Override
public void onNetworkStats(long uid, int txQuality, int rxQuality, RtcStat stat,String name) {
if (uid == 0) {
Log.d("qtt_rtc", "自己网络情况:上行质量 " + txQuality + " 下行质量 " + rxQuality + " 上行丢包 " + stat.mUpLossRate + " 下行丢包 " + stat.mDownLossRate + " 端到端时延 " + stat.mRttAverage + " 抖动 " + stat.mJitter);
//TODO 实现处理自己网络情况的逻辑
} else {
Log.d("qtt_rtc", "uid: " + uid + " 用户网络情况:上行质量 " + txQuality + " 下行质量 " + rxQuality + " 上行丢包 " + stat.mUpLossRate + " 下行丢包 " + stat.mDownLossRate + " 端到端时延 " + stat.mRttAverage + " 抖动 " + stat.mJitter);
//TODO 实现处理其它用户网络情况的逻辑
}
}
@Override
public void onAudioRouteChanged(int route) {
Log.d("qtt_rtc", "音频路由变化");
//TODO 实现处理音频路由变化的逻辑
}

@Override
public void onSoundStateChanged(int state) {
Log.d("qtt_log", "播放音乐状态变化 " + state);
//TODO 实现处理播放音乐状态变化的逻辑
}

@Override
public void onEffectFinished(int effectId) {
Log.d("qtt_log", "音效播放完成 " + effectId);
//TODO 实现处理音效播放完成的逻辑
}

/**
* 该回调是由远端用户调用 enableVideo 或 disableVideo 方法开启或关闭视频模块触发的
*/
@Overide
public void onUserEnableVideo(long uid, boolean enabled,String name){
Log.d("qtt_log", "远端用户开/关视频模块回调 ");
//TODO 实现处理远端用户开/关视频的逻辑。
}

/**
* 该回调是由远端用户调用enableLocalVideo方法开启或关闭视频采集触发的
*/
@Overide
public void onUserEnableVideo(long uid, boolean enabled,String name){
Log.d("qtt_log", "远端用户开/关本地视频采集回调");
//TODO 实现处理远端用户开/关本地视频的逻辑。
}

/**
* 当远端用户调用muteLocalVideoStream取消或恢复发布视频流时,SDK会触发该回调向本地用户报告远端用户的发流状况
*/
@Overide
public void onUserEnableVideo(long uid, boolean enabled,String name){
Log.d("qtt_log", "远端用户取消或恢复发布视频流回调");
//TODO 实现处理远端用户取消或恢复发布视的逻辑。
}
}

4.启用视频

channelEngine.enableVideo();

5.设置视频编码属性

channelEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
VideoEncoderConfiguration.VD_1280x720,//分辨率
VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,//帧数
0, //码率,0为自适应码率
VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT//输出竖屏模式的视频
));

4.进入频道

//以连麦角色进入频道
channelEngine.changeRole(ChannelRole.TALKER);
//设置频道名称。Appkey相同,并且频道名称相同的用户会进入同一个频道,可以互相通话。
//uid设置(32位无符号整形),用以区分用户,请保证同一个频道的用户uid唯一。
//如果填0,则由服务器分配,在onJoinSuccess里告知实际uid值
long uid = 0;
String channelId = "test1";
String suid = "";
channelEngine.join( "",channelId,uid,suid);

5. 渲染本地视频


FrameLayout container = findViewById(R.id.local_video_view_container);
//创建 RendererView。请在主线程调用该方法
SurfaceView localView = ChannelEngine.CreateRendererView(this);
channelEngine.setupLocalVideo(localView, 1, 0);
container.addView(localView);

6.渲染远端用户视频


FrameLayout container = findViewById(R.id.remote_video_view_container);

//请在主线程调用该方法
//在onOtherJoin回调中调用该方法,onOtherJoin是异步线程
private void setupRemoteVideo(long uid){
//创建 RendererView。
SurfaceView remoteView = ChannelEngine.CreateRendererView(this);
surfaceView.setZOrderMediaOverlay(true)
channelEngine.setupRemoteVideo(remoteView,uid, 1, 0);
container.addView(remoteView);
}

7. 离开频道

//对应channelEngine.join()进入频道
channelEngine.leave();

8. 释放资源

//ChannelEngine.GetChannelInstance();
channelEngine.delete();
channelEngine = null;
野狗新手?
立即注册,为你提供安全可靠的实时通信云服务。
没找到需要的文档?
你可以提交工单反馈 或 阅读常见问题