1.1、實(shí)時音頻、實(shí)時視頻均通過相同的接口進(jìn)行調(diào)用,遵循相同的業(yè)務(wù)流程。不同的業(yè)務(wù)通過呼叫接口參數(shù)CallType進(jìn)行區(qū)分,CallType一共有2種類型:CallType.VIDEO(視頻),CallType.VOICE(音頻)。
注意:5.0以上的SDK集成的客戶端,測試音視頻功能,音視頻,會議,群組等操作需要,先將在我們控制臺創(chuàng)建的應(yīng)用上線,才可測試(控制臺提供的測試demo中的應(yīng)用id和應(yīng)用token,不能用來測試,需要使用自己在官網(wǎng)控制臺創(chuàng)建的應(yīng)用的id和應(yīng)用token)。
1.2、接口邏輯:
接口調(diào)用是采取異步調(diào)用的方式。所有的呼叫相關(guān)接口的調(diào)用結(jié)果通過回調(diào)接口OnVoipListener中的方法OnCallEvents來接受服務(wù)端返回的各種狀態(tài)。
1.3、業(yè)務(wù)流程
(1)客戶A呼叫客戶B發(fā)起請求
(2)云通訊服務(wù)端收到A請求并把請求轉(zhuǎn)發(fā)給B
(3)客戶B收到請求并應(yīng)答
(4)云通訊服務(wù)端收到B應(yīng)答并轉(zhuǎn)發(fā)A
(5)A收到應(yīng)答,通話建立
? 音頻呼叫 — 我們假設(shè)Tony音頻呼叫John,則代碼如下:
String mCurrentCallId = ECDevice.getECVoIPCallManager().makeCall(ECVoIPCallManager.CallType.VOICE, "john的賬號"); 說明:mCurrentCallId如果返回空則代表呼叫失敗,可能是參數(shù)錯誤引起。否則返回是一串?dāng)?shù)字,是當(dāng)前通話的標(biāo)識。
? 視頻呼叫 — 我們假設(shè)Tony視頻呼叫John,此時代碼和音頻呼叫相同,區(qū)別是呼叫類型需要傳入CallType.VIDEO,并且在呼叫前需要設(shè)置本地和對方的視頻view,代碼如下:
//view 顯示遠(yuǎn)端視頻的surfaceview //localView本地顯示視頻的view ECDevice.getECVoIPSetupManager().setVideoView(view, localView); String mCurrentCallId = ECDevice.getECVoIPCallManager().makeCall(ECVoIPCallManager.CallType.VIDEO, "john的賬號"); 說明:mCurrentCallId如果返回空則代表呼叫失敗,可能是參數(shù)錯誤引起。否則返回是一串?dāng)?shù)字,是當(dāng)前通話的標(biāo)識。
? 獲取來電參數(shù) — 被叫John接到Tony的呼叫,John同意接聽該呼入,John側(cè)的呼入activity的設(shè)置已經(jīng)在sdk初始化的回調(diào)onInitialized中設(shè)置過。Sdk底層收到呼入請求后,會自動彈出該Activity.在Activity的onCreate中取出相關(guān)的參數(shù)。
1、 在呼入調(diào)起的界面中,獲取到呼入的類型是音頻或者視頻呼叫,然后來設(shè)置對應(yīng)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); //獲取當(dāng)前的callid mCallId = getIntent().getStringExtra(ECDevice.CALLID); //獲取對方的號碼 mCallNumber = getIntent().getStringExtra(ECDevice.CALLER); } }
2、假設(shè)John側(cè)調(diào)起來音頻或者視頻呼入的界面,界面上有“接受”和“拒絕”兩個按鈕;
(1)John點(diǎn)擊“接受”按鈕,則調(diào)用的代碼:
//如果視頻呼叫,則在接受呼叫之前,需要先設(shè)置視頻通話顯示的view ECDevice.getECVoIPSetupManager().setVideoView(view, localView); //view 顯示遠(yuǎn)端視頻的surfaceview //localView本地顯示視頻的view ECDevice.getECVoIpCallManager().acceptCall(mCurrentCallId);
(2)John點(diǎn)擊“拒絕”按鈕,音視頻拒絕的代碼是一致的,調(diào)用的代碼是:
ECDevice.getECVoIpCallManager().rejectCall(mCurrentCallId,”拒絕的原因,傳入整形值”);
? 處理回調(diào)事件 — Tony在呼叫John的過程中,會有若干狀態(tài)返回,都在回調(diào)onCallEvents中處理,其監(jiān)聽的設(shè)置已經(jīng)在sdk初始化的回調(diào)onInitialized中設(shè)置過。代碼示例如下:
注意:在集成音視頻通話的時候,當(dāng)結(jié)束當(dāng)前通話的時候,需要在處理回調(diào)事件的onCallEvents中調(diào)用一下releaseCall方法,以保證當(dāng)前通話占用的資源都釋放了,避免在下次呼叫的時候出現(xiàn)線路被占用現(xiàn)象。(android、ios均需這樣操作),Android的調(diào)用地方,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接受了呼叫應(yīng)答”); break; case ECCALL_FAILED:// Log(” 呼叫失敗”); break; case ECCALL_RELEASED: //無論是Tony還是John主動結(jié)束通話,雙方都會進(jìn)入到此回調(diào) Log(” 結(jié)束當(dāng)前通話”); break; default: break; } } }
? 處理回調(diào)事件 — Tony和John的通話過程中,任何一方想結(jié)束呼叫,則都可以調(diào)用如下代碼:
ECDevice.getECVoIpCallManager().releaseCall(mCurrentCallId);
(1)設(shè)置揚(yáng)聲器狀態(tài)
ECDevice. getECVoIPSetupManager().enableLoudSpeaker( boolean on); 功能: 設(shè)置揚(yáng)聲器的狀態(tài); 參數(shù):on:true是開啟,false則為關(guān)閉。
(2)獲取揚(yáng)聲器狀態(tài)
ECDevice. getECVoIPSetupManager().getLoudSpeakerStatus(); 功能:獲取當(dāng)前揚(yáng)聲器的狀態(tài) 參數(shù):無 返回值:true是開啟,false則為關(guān)閉。
(3)設(shè)置靜音
ECDevice. getECVoIPSetupManager().setMute(boolean on); 功能:設(shè)置通話靜音狀態(tài) 參數(shù):on:傳入true則對方聽不到說話,false則對方可以聽到說話。 返回值:無
(4)獲取靜音的狀態(tài)
ECDevice.getECVoIPSetupManager().getMuteStatus(); 功能:獲取當(dāng)前通話靜音狀態(tài) 參數(shù):無 返回值:返回true則是靜音狀態(tài),false則不是靜音狀態(tài).
(5)設(shè)置視頻通話顯示的窗口
ECDevice.getECVoIPSetupManager().setVideoView( SurfaceView view, SurfaceView localView); 功能:設(shè)置視頻通話過程中顯示的視圖 參數(shù):view對方顯示的視圖,localView本地顯示的視圖。 返回值:無
(6)創(chuàng)建一個用于繪制視頻圖像的ECOpenGlView控件
ECOpenGlView mGlView = new ECOpenGlView(this); // 設(shè)置預(yù)覽類型為本地預(yù)覽、可以顯示于其他SurfaceView之上 mGlView.setGlType(ECOpenGlView.RenderType.RENDER_PREVIEW); // 或者設(shè)置為遠(yuǎn)端繪制 mGlView.setGlType(ECOpenGlView.RenderType.RENDER_REMOTE); // 設(shè)置當(dāng)前圖像填充方式(根據(jù)中心區(qū)域顯示,填充屏幕并剪切) mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.CROP); // 按照圖像的比例顯示(分辨率和圖像分辨率不等時上下、左右會出現(xiàn)一種黑邊情況) mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.FIT); // 按照View的寬高拉伸圖像 mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.FILL);
(7)設(shè)置遠(yuǎn)端視頻圖像顯示View為ECOpenGlView
ECVoIPSetupManager setUpMgr = ECDevice.getECVoIPSetupManager(); if(setUpMgr != null) { setUpMgr.setVideoView(mGlView , mCaptureView); }
(8)設(shè)置本地/遠(yuǎn)端視頻圖像顯示View為ECOpenGlView
// 創(chuàng)建一個本地圖像顯示控件 ECOpenGlView mSelfGlView = new ECOpenGlView(this); // 設(shè)置預(yù)覽類型為本地預(yù)覽、可以顯示于其他SurfaceView之上 mSelfGlView.setGlType(ECOpenGlView.RenderType.RENDER_PREVIEW); // 設(shè)置當(dāng)前圖像填充方式(根據(jù)中心區(qū)域顯示,填充屏幕并剪切) mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.CROP); // 創(chuàng)建一個遠(yuǎn)端圖像顯示控件 ECOpenGlView mRemoteGlView = new ECOpenGlView(this); // 設(shè)置預(yù)覽類型為遠(yuǎn)端、可以顯示于其他SurfaceView之下 mRemoteGlView.setGlType(ECOpenGlView.RenderType.RENDER_PREVIEW); // 設(shè)置當(dāng)前圖像填充方式(根據(jù)中心區(qū)域顯示,填充屏幕并剪切) mRemoteGlView.setAspectMode(ECOpenGlView.AspectMode.CROP); // 調(diào)用SDK接口設(shè)置圖像顯示View ECVoIPSetupManager setUpMgr = ECDevice.getECVoIPSetupManager(); if(setUpMgr != null) { // 設(shè)置圖像采集 setUpMgr.setCaptureView(new ECCaptureView(this)); // 設(shè)置本地遠(yuǎn)端圖像顯示View setUpMgr.setGlDisplayWindow(mSelfGlView , mRemoteGlView); }
(9)動態(tài)切換本地/遠(yuǎn)端圖像(對換本地遠(yuǎn)端圖像顯示位置)
mSelfGlView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ECVoIPSetupManager setUpMgr = ECDevice.getECVoIPSetupManager(); if(setUpMgr != null) { // 設(shè)置當(dāng)前遠(yuǎn)端圖像顯示為全屏/小屏幕 mMaxSizeRemote = !mMaxSizeRemote; // 調(diào)用接口對換View位置 if(mMaxSizeRemote) { setUpMgr.setGlDisplayWindow(mSelfGlView , mRemoteView); } else { setUpMgr.setGlDisplayWindow(mRemoteView , mSelfGlView); } } } });
(10)視頻會議使用ECOpenGlView顯示成員圖像
// 創(chuàng)建一個圖像顯示控件View ECOpenGlView mGlView = new ECOpenGlView(this); mGlView.setGlType(ECOpenGlView.RenderType.RENDER_REMOTE); mSelfGlView.setAspectMode(ECOpenGlView.AspectMode.CROP); // 獲取會議管理API接口 ECMeetingManager meetMgr = ECDevice.getECMeetingManager(); // 使用接口設(shè)置圖像顯示View meetMgr.requestMemberVideoInVideoMeeting("conf0000", null, "yuntx", mGlView , "ip", 8080, null);
(11)獲取手機(jī)攝像頭參數(shù)
ECDevice.getECVoIPSetupManager().getCameraInfos(); 功能: 獲取手機(jī)攝像頭參數(shù)信息(攝像頭個數(shù),名稱、以及攝像頭所持有的分辨率) 參數(shù):無。 返回值:手機(jī)攝像頭參數(shù)信息
(12)切換前置和后置攝像頭
/** * 選擇攝像頭。可以在通話過程中選擇;如果不調(diào)用,底層將使用系統(tǒng)默認(rèn)攝像頭 * @param cameraIndex CameraInfo的index值 * @param capabilityIndex CameraCapability的index值。范圍[0,capabilityCount-1] * @param fps 最大幀數(shù) * @param rotate 旋轉(zhuǎn)的角度( {ROTATE_AUTO,ROTATE_0,ROTATE_90,ROTATE_180,ROTATE_270};中的值) * @param force 是否強(qiáng)制啟動本SDK調(diào)用的攝像頭。默認(rèn)選false * @param scale 縮放 * @return 是否成功 0:成功; 非0失敗 */ ECDevice.getECVoIPSetupManager().selectCamera(int cameraIndex, int capabilityIndex, int fps, Rotate rotate, boolean force,float scale);
(13)設(shè)置VoIP呼叫透傳信息
// 創(chuàng)建一個個人信息參數(shù)對象 VoIPCallUserInfo mUserInfo = new VoIPCallUserInfo(); mUserInfo.setNickName("nickname"); mUserInfo.setPhoneNumber("PhoneNumber"); // 調(diào)用VoIP設(shè)置接口注入VoIP呼叫透傳參數(shù) ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); setupManager.setVoIPCallUserInfo(mUserInfo);
(14)設(shè)置是否啟用來去電鈴聲播放
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 設(shè)置來電響鈴(v5.1.8r版本以及以前) setupManager.setIncomingSoundEnabled(true); // 查詢是否來電響鈴(v5.1.8r版本以及以前) setupManager.isIncomingSoundEnabled(); // 設(shè)置VoIP呼叫是否播放回鈴音(v5.1.8r版本以及以前) setupManager.setOutgoingSoundEnabled(true); // 查詢是否啟用呼叫播放回鈴音(v5.1.8r版本以及以前) setupManager.isOutgoingSoundEnabled(); // 設(shè)置VoIP呼叫是否播放呼叫失敗提示音(v5.1.8r版本以及以前) setupManager.setDisconnectSoundEnabled(true); // 查詢是否啟用呼叫失敗提示音(v5.1.8r版本以及以前) setupManager.isDisconnectSoundEnabled(); v5.1.9r版本開始通過如下接口設(shè)置: // 設(shè)置VOIP 自定義鈴聲路徑 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); if(setupManager != null) { // 目前支持下面三種路徑查找方式 // 1、如果是assets目錄則設(shè)置為前綴[assets://] setupManager.setInComingRingUrl(true, "assets://phonering.mp3"); setupManager.setOutGoingRingUrl(true, "assets://phonering.mp3"); setupManager.setBusyRingTone(true, "assets://played.mp3"); // 2、如果是raw目錄則設(shè)置為前綴[raw://] // 3、如果是SDCard目錄則設(shè)置為前綴[file://] }
(15)設(shè)置音頻處理開關(guān),在通話前調(diào)用
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 比如設(shè)置開啟回音消除模式 setupManager.setAudioConfigEnabled(ECVoIPSetupManager.AudioType.AUDIO_EC , true , ECVoIPSetupManager.AudioMode.EC_Conference);
(16)查詢相關(guān)的音頻處理參數(shù)
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 比如是否啟用回音消除 setupManager.getAudioConfig(ECVoIPSetupManager.AudioType.AUDIO_EC); // 查詢回音消除模式 setupManager.getAudioConfigMode(ECVoIPSetupManager.AudioType.AUDIO_EC);
(17)設(shè)置視頻通話碼流(需要在通話前使用)
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 比如:將視頻通話碼流設(shè)置成150 setupManager.setVideoBitRates(150);
(18)設(shè)置SDK支持的編解碼方式,默認(rèn)全部支持
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 比如:設(shè)置當(dāng)前通話使用 G729編碼傳輸 setupManager.setCodecEnabled(ECVoIPSetupManager.Codec.Codec_G729 , true); // 查詢制定編解碼是否支持 setupManager.getCodecEnabled(ECVoIPSetupManager.Codec.Codec_G729);
(19)實(shí)時獲取通話中的統(tǒng)計(jì)數(shù)據(jù)
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 比如:獲取音頻通話信息 // 具體參數(shù)信息可以參考API文檔CallStatisticsInfo CallStatisticsInfo statistics = setupManager.getCallStatistics("callId", false);
(20)獲取VoIP、視頻、實(shí)時對講、聊天室、會議上下行流量
// 獲取一個VoIP設(shè)置接口對象 ECVoIPSetupManager setupManager = ECDevice.getECVoIPSetupManager(); // 具體參數(shù)信息可以參考API文檔NetworkStatistic NetworkStatistic networkStatistic = setupManager.getNetworkStatistic("callId");
(21)獲取服務(wù)器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)獲取用戶在線狀態(tài)
ECDevice.getUsersState(new String[]{userId}, new OnGetUsersStateListener() { @Override public void onGetUsersState(ECError error, ECUserState... userState) { //查詢多個用戶狀態(tài)回調(diào) 可變數(shù)組 userState } });
(23)單應(yīng)用多證書
/** * ECDevice類 * 多證書設(shè)置 * @param pushCerKey 推送證書標(biāo)識,與服務(wù)器上傳證書保持一致 */ ECDevice.setPushCerKey("xxxx");
(24)設(shè)置網(wǎng)絡(luò)代理
/** * ECDevice類 * 設(shè)置網(wǎng)絡(luò)代理。需要走代理時登錄前設(shè)置,不支持ssl;socks5代理支持im和點(diǎn)對點(diǎn)(底層將關(guān)閉媒體流內(nèi)網(wǎng)打洞),http代理支持im * @param proxyHost 代理服務(wù)器地址,最大長度255。當(dāng)設(shè)置空時,取消代理 * @param proxyPort 代理端口 * @param authType 鑒權(quán)類型。 目前支持 0 不鑒權(quán);2 用戶名密碼鑒權(quán) * @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日