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日