1.1、实时音频、实时视频均通过相同的接口进行调用,遵循相同的业务流程。不同的业务通过呼叫接口参数CallType进行区分,CallType一共有2种类型:CallType.VIDEO(视频),CallType.VOICE(音频)。
注意:5.0以上的SDK集成的客户端,测试音视频功能,音视频,会议,群组等操作需要,先将在我们控制台创建的应用上线,才可测试(控制台提供的测试demo中的应用id和应用token,不能用来测试,需要使用自己在官网控制台创建的应用的id和应用token)。
1.2、接口逻辑:
接口调用是采取异步调用的方式。所有的呼叫相关接口的调用结果通过回调接口OnVoipListener中的方法OnCallEvents来接受服务端返回的各种状态。
1.3、业务流程
(1)客户A呼叫客户B发起请求
(2)云通讯服务端收到A请求并把请求转发给B
(3)客户B收到请求并应答
(4)云通讯服务端收到B应答并转发A
(5)A收到应答,通话建立
✾ 音频呼叫 — 我们假设Tony音频呼叫John,则代码如下:
String mCurrentCallId = ECDevice.getECVoIPCallManager().makeCall(ECVoIPCallManager.CallType.VOICE,
"john的账号");
说明:mCurrentCallId如果返回空则代表呼叫失败,可能是参数错误引起。否则返回是一串数字,是当前通话的标识。
✾ 视频呼叫 — 我们假设Tony视频呼叫John,此时代码和音频呼叫相同,区别是呼叫类型需要传入CallType.VIDEO,并且在呼叫前需要设置本地和对方的视频view,代码如下:
//view 显示远端视频的surfaceview
//localView本地显示视频的view
ECDevice.getECVoIPSetupManager().setVideoView(view, localView);
String mCurrentCallId = ECDevice.getECVoIPCallManager().makeCall(ECVoIPCallManager.CallType.VIDEO,
"john的账号");
说明:mCurrentCallId如果返回空则代表呼叫失败,可能是参数错误引起。否则返回是一串数字,是当前通话的标识。
✾ 获取来电参数 — 被叫John接到Tony的呼叫,John同意接听该呼入,John侧的呼入activity的设置已经在sdk初始化的回调onInitialized中设置过。Sdk底层收到呼入请求后,会自动弹出该Activity.在Activity的onCreate中取出相关的参数。
1、 在呼入调起的界面中,获取到呼入的类型是音频或者视频呼叫,然后来设置对应UI布局,代码如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = savedInstanceState;
//或者
Bundle extras = getIntent().getExtras();
if (extras == null) {
finish();
return;
}
//获取是否是呼入还是呼出
mIncomingCall = !(getIntent().getBooleanExtra(EXTRA_OUTGOING_CALL, false));
//获取是否是音频还是视频
mCallType = (ECVoIPCallManager.CallType)
getIntent().getSerializableExtra(ECDevice.CALLTYPE);
//获取当前的callid
mCallId = getIntent().getStringExtra(ECDevice.CALLID);
//获取对方的号码
mCallNumber = getIntent().getStringExtra(ECDevice.CALLER);
}
}
2、假设John侧调起来音频或者视频呼入的界面,界面上有“接受”和“拒绝”两个按钮;
(1)John点击“接受”按钮,则调用的代码:
//如果视频呼叫,则在接受呼叫之前,需要先设置视频通话显示的view
ECDevice.getECVoIPSetupManager().setVideoView(view, localView);
//view 显示远端视频的surfaceview
//localView本地显示视频的view
ECDevice.getECVoIpCallManager().acceptCall(mCurrentCallId);
(2)John点击“拒绝”按钮,音视频拒绝的代码是一致的,调用的代码是:
ECDevice.getECVoIpCallManager().rejectCall(mCurrentCallId,”拒绝的原因,传入整形值”);
✾ 处理回调事件 — Tony在呼叫John的过程中,会有若干状态返回,都在回调onCallEvents中处理,其监听的设置已经在sdk初始化的回调onInitialized中设置过。代码示例如下:
注意:在集成音视频通话的时候,当结束当前通话的时候,需要在处理回调事件的onCallEvents中调用一下releaseCall方法,以保证当前通话占用的资源都释放了,避免在下次呼叫的时候出现线路被占用现象。(android、ios均需这样操作),Android的调用地方,onCallEvents中的 ECCALL_RELEASED:
@Override
protected void onCallEvents(ECVoIPCallManager.VoIPCall voipCall) {
if(voipCall==null) return;
switch(voipCall. callState){
case ECCALL_ALERTING:
Log(” 对方振铃”);
break;
case ECCALL_PROCEEDING:
Log(” 呼叫中”);
break;
case ECallAnswered:
Log(” John接受了呼叫应答”);
break;
case ECCALL_FAILED://
Log(” 呼叫失败”);
break;
case ECCALL_RELEASED:
//无论是Tony还是John主动结束通话,双方都会进入到此回调
Log(” 结束当前通话”);
break;
default:
break;
}
}
}
✾ 处理回调事件 — Tony和John的通话过程中,任何一方想结束呼叫,则都可以调用如下代码:
ECDevice.getECVoIpCallManager().releaseCall(mCurrentCallId);
(1)设置扬声器状态
ECDevice. getECVoIPSetupManager().enableLoudSpeaker( boolean on);
功能: 设置扬声器的状态;
参数:on:true是开启,false则为关闭。
(2)获取扬声器状态
ECDevice. getECVoIPSetupManager().getLoudSpeakerStatus();
功能:获取当前扬声器的状态
参数:无
返回值:true是开启,false则为关闭。
(3)设置静音
ECDevice. getECVoIPSetupManager().setMute(boolean on);
功能:设置通话静音状态
参数:on:传入true则对方听不到说话,false则对方可以听到说话。
返回值:无
(4)获取静音的状态
ECDevice.getECVoIPSetupManager().getMuteStatus();
功能:获取当前通话静音状态
参数:无
返回值:返回true则是静音状态,false则不是静音状态.
(5)设置视频通话显示的窗口
ECDevice.getECVoIPSetupManager().setVideoView( SurfaceView view, SurfaceView localView);
功能:设置视频通话过程中显示的视图
参数:view对方显示的视图,localView本地显示的视图。
返回值:无
(6)创建一个用于绘制视频图像的ECOpenGlView控件
ECOpenGlView mGlView = new ECOpenGlView(this);
// 设置预览类型为本地预览、可以显示于其他SurfaceView之上
mGlView.setGlType(ECOpenGlView.RenderType.RENDER_PREVIEW);
// 或者设置为远端绘制
mGlView.setGlType(ECOpenGlView.RenderType.RENDER_REMOTE);
// 设置当前图像填充方式(根据中心区域显示,填充屏幕并剪切)
mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.CROP);
// 按照图像的比例显示(分辨率和图像分辨率不等时上下、左右会出现一种黑边情况)
mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.FIT);
// 按照View的宽高拉伸图像
mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.FILL);
(7)设置远端视频图像显示View为ECOpenGlView
ECVoIPSetupManager setUpMgr = ECDevice.getECVoIPSetupManager();
if(setUpMgr != null) {
setUpMgr.setVideoView(mGlView , mCaptureView);
}
(8)设置本地/远端视频图像显示View为ECOpenGlView
// 创建一个本地图像显示控件
ECOpenGlView mSelfGlView = new ECOpenGlView(this);
// 设置预览类型为本地预览、可以显示于其他SurfaceView之上
mSelfGlView.setGlType(ECOpenGlView.RenderType.RENDER_PREVIEW);
// 设置当前图像填充方式(根据中心区域显示,填充屏幕并剪切)
mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.CROP);
// 创建一个远端图像显示控件
ECOpenGlView mRemoteGlView = new ECOpenGlView(this);
// 设置预览类型为远端、可以显示于其他SurfaceView之下
mRemoteGlView.setGlType(ECOpenGlView.RenderType.RENDER_PREVIEW);
// 设置当前图像填充方式(根据中心区域显示,填充屏幕并剪切)
mRemoteGlView.setAspectMode(ECOpenGlView.AspectMode.CROP);
// 调用SDK接口设置图像显示View
ECVoIPSetupManager setUpMgr = ECDevice.getECVoIPSetupManager();
if(setUpMgr != null) {
// 设置图像采集
setUpMgr.setCaptureView(new ECCaptureView(this));
// 设置本地远端图像显示View
setUpMgr.setGlDisplayWindow(mSelfGlView , mRemoteGlView);
}
(9)动态切换本地/远端图像(对换本地远端图像显示位置)
mSelfGlView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ECVoIPSetupManager setUpMgr = ECDevice.getECVoIPSetupManager();
if(setUpMgr != null) {
// 设置当前远端图像显示为全屏/小屏幕
mMaxSizeRemote = !mMaxSizeRemote;
// 调用接口对换View位置
if(mMaxSizeRemote) {
setUpMgr.setGlDisplayWindow(mSelfGlView , mRemoteView);
} else {
setUpMgr.setGlDisplayWindow(mRemoteView , mSelfGlView);
}
}
}
});
(10)视频会议使用ECOpenGlView显示成员图像
// 创建一个图像显示控件View
ECOpenGlView mGlView = new ECOpenGlView(this);
mGlView.setGlType(ECOpenGlView.RenderType.RENDER_REMOTE);
mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.CROP);
// 获取会议管理API接口
ECMeetingManager meetMgr = ECDevice.getECMeetingManager();
// 使用接口设置图像显示View
meetMgr.requestMemberVideoInVideoMeeting("conf0000", null, "yuntx", mGlView , "ip", 8080, null);
(11)获取手机摄像头参数
ECDevice.getECVoIPSetupManager().getCameraInfos();
功能: 获取手机摄像头参数信息(摄像头个数,名称、以及摄像头所持有的分辨率)
参数:无。
返回值:手机摄像头参数信息
(12)切换前置和后置摄像头
/**
* 选择摄像头。可以在通话过程中选择;如果不调用,底层将使用系统默认摄像头
* @param cameraIndex CameraInfo的index值
* @param capabilityIndex CameraCapability的index值。范围[0,capabilityCount-1]
* @param fps 最大帧数
* @param rotate 旋转的角度( {ROTATE_AUTO,ROTATE_0,ROTATE_90,ROTATE_180,ROTATE_270};中的值)
* @param force 是否强制启动本SDK调用的摄像头。默认选false
* @param scale 缩放
* @return 是否成功 0:成功; 非0失败
*/
ECDevice.getECVoIPSetupManager().selectCamera(int cameraIndex, int capabilityIndex,
int fps, Rotate rotate, boolean force,float scale);
(13)设置VoIP呼叫透传信息
// 创建一个个人信息参数对象
VoIPCallUserInfo mUserInfo = new VoIPCallUserInfo();
mUserInfo.setNickName("nickname");
mUserInfo.setPhoneNumber("PhoneNumber");
// 调用VoIP设置接口注入VoIP呼叫透传参数
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
setupManager.setVoIPCallUserInfo(mUserInfo);
(14)设置是否启用来去电铃声播放
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 设置来电响铃(v5.1.8r版本以及以前)
setupManager.setIncomingSoundEnabled(true);
// 查询是否来电响铃(v5.1.8r版本以及以前)
setupManager.isIncomingSoundEnabled();
// 设置VoIP呼叫是否播放回铃音(v5.1.8r版本以及以前)
setupManager.setOutgoingSoundEnabled(true);
// 查询是否启用呼叫播放回铃音(v5.1.8r版本以及以前)
setupManager.isOutgoingSoundEnabled();
// 设置VoIP呼叫是否播放呼叫失败提示音(v5.1.8r版本以及以前)
setupManager.setDisconnectSoundEnabled(true);
// 查询是否启用呼叫失败提示音(v5.1.8r版本以及以前)
setupManager.isDisconnectSoundEnabled();
v5.1.9r版本开始通过如下接口设置:
// 设置VOIP 自定义铃声路径
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
if(setupManager != null) {
// 目前支持下面三种路径查找方式
// 1、如果是assets目录则设置为前缀[assets://]
setupManager.setInComingRingUrl(true, "assets://phonering.mp3");
setupManager.setOutGoingRingUrl(true, "assets://phonering.mp3");
setupManager.setBusyRingTone(true, "assets://played.mp3");
// 2、如果是raw目录则设置为前缀[raw://]
// 3、如果是SDCard目录则设置为前缀[file://]
}
(15)设置音频处理开关,在通话前调用
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 比如设置开启回音消除模式
setupManager.setAudioConfigEnabled(ECVoIPSetupManager.AudioType.AUDIO_EC ,
true , ECVoIPSetupManager.AudioMode.EC_Conference);
(16)查询相关的音频处理参数
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 比如是否启用回音消除
setupManager.getAudioConfig(ECVoIPSetupManager.AudioType.AUDIO_EC);
// 查询回音消除模式
setupManager.getAudioConfigMode(ECVoIPSetupManager.AudioType.AUDIO_EC);
(17)设置视频通话码流(需要在通话前使用)
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 比如:将视频通话码流设置成150
setupManager.setVideoBitRates(150);
(18)设置SDK支持的编解码方式,默认全部支持
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 比如:设置当前通话使用 G729编码传输
setupManager.setCodecEnabled(ECVoIPSetupManager.Codec.Codec_G729 , true);
// 查询制定编解码是否支持
setupManager.getCodecEnabled(ECVoIPSetupManager.Codec.Codec_G729);
(19)实时获取通话中的统计数据
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 比如:获取音频通话信息
// 具体参数信息可以参考API文档CallStatisticsInfo
CallStatisticsInfo statistics = setupManager.getCallStatistics("callId", false);
(20)获取VoIP、视频、实时对讲、聊天室、会议上下行流量
// 获取一个VoIP设置接口对象
ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager();
// 具体参数信息可以参考API文档NetworkStatistic
NetworkStatistic networkStatistic = setupManager.getNetworkStatistic("callId");
(21)获取服务器callSid,建议通话建立后获取。代码示例如下:
private Map map = new HashMap(); private void get(){ String s = ECDevice.getECVoIPCallManager().getUserData(3,mCallId); if(!TextUtils.isEmpty(s)){ if(s.contains(";")) { String[] arr = s.split("\\;"); if (arr != null) { for (String item : arr) { if (!TextUtils.isEmpty(item) && item.startsWith("servercallid")){ String[] arr2 = item.split("\\="); if (arr2 != null && arr2.length == 2) { map.put("sid", arr2[1]); } } } } }else { if(s.startsWith("servercallid=")){ String [] arr = s.split("\\="); if(arr!=null&&arr.length==2){ map.put("sid",arr[1]); } } } } }
(22)获取用户在线状态
ECDevice.getUsersState(new String[]{userId}, new OnGetUsersStateListener() {
@Override
public void onGetUsersState(ECError error, ECUserState... userState) {
//查询多个用户状态回调 可变数组 userState
}
});
(23)单应用多证书
/**
* ECDevice类
* 多证书设置
* @param pushCerKey 推送证书标识,与服务器上传证书保持一致
*/
ECDevice.setPushCerKey("xxxx");
(24)设置网络代理
/**
* ECDevice类
* 设置网络代理。需要走代理时登录前设置,不支持ssl;socks5代理支持im和点对点(底层将关闭媒体流内网打洞),http代理支持im
* @param proxyHost 代理服务器地址,最大长度255。当设置空时,取消代理
* @param proxyPort 代理端口
* @param authType 鉴权类型。 目前支持 0 不鉴权;2 用户名密码鉴权
* @param userName 用户名,最大长度255。authType=2时有效
* @param userPass 用户名密码,最大长度255。authType=2时有效
* @param proxyType 代理类型。 目前支持 0 socks5代理;1 http代理
* @return
*/
ECDevice.setNetworkProxy(proxyHost,proxyPort,authType,userName,userPass,proxyType);
文档更新时间:2017年12月4日