1.1、實時音頻、實時視頻均通過相同的接口進(jìn)行調(diào)用,遵循相同的業(yè)務(wù)流程。不同的業(yè)務(wù)通過呼叫接口參數(shù)CallType進(jìn)行區(qū)分,VIDEO視頻、VOICE音頻等。
1.2、接口邏輯:
接口調(diào)用是采取異步調(diào)用的方式。所有的呼叫相關(guān)接口的調(diào)用結(jié)果通過回調(diào)接口ECVoIPCallDelegate中的方法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)答,通話建立
2.1、呼叫界面處理
self.callID = [[ECDevice sharedInstance].VoIPManager makeCallWithType:VOICE andCalled:@ "John的登錄賬號"]; if (self.callid.length <= 0)//獲取CallID失敗,即撥打失敗 { } 說明:self.callID如果返回空則代表呼叫失敗,可能是參數(shù)錯誤引起。否則返回是一串?dāng)?shù)字,是當(dāng)前通話的標(biāo)識。
[[ECDevice sharedInstance].VoIPManager setVideoView:remoteVideoView andLocalView:localVideoView]; self.callID = [[ECDevice sharedInstance].VoIPManager makeCallWithType:VIDEO andCalled: @ "John的登錄號碼"]; if (self.callid.length <= 0)//獲取CallID失敗,即撥打失敗 { } 說明:self.callID如果返回空則代表呼叫失敗,可能是參數(shù)錯誤引起。否則返回是一串?dāng)?shù)字,是當(dāng)前通話的標(biāo)識。 視頻時(包含點對點和會議),設(shè)置遠(yuǎn)端UIView的屬性contentMode:(setVideoView:remoteVideoView) UIViewContentModeScaleToFill //view默認(rèn)值,圖像數(shù)據(jù)顯示,填充view,但不等比例拉伸 UIViewContentModeScaleAspectFit //圖像等比例拉伸,完全顯示內(nèi)容 UIViewContentModeScaleAspectFill //圖像等比例拉伸,填充view,部分內(nèi)容可能不顯示
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSError *parseError = nil; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfo options:NSJSONWritingPrettyPrinted error:&parseError]; NSString *str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"推送內(nèi)容" message:str delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil]; [alert show]; NSLog(@"遠(yuǎn)程推送str:%@",str); NSLog(@"遠(yuǎn)程推送1:%@",userInfo); NSLog(@"遠(yuǎn)程推送r:%@",[userInfo objectForKey:@"r"]); NSLog(@"遠(yuǎn)程推送s:%@",[userInfo objectForKey:@"s"]); self.callid = nil; NSString *userdata = [userInfo objectForKey:@"c"]; NSLog(@"遠(yuǎn)程推送userdata:%@",userdata); if (userdata) { NSDictionary*callidobj = [NSJSONSerialization JSONObjectWithData:[userdata dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:nil]; NSLog(@"遠(yuǎn)程推送callidobj:%@",callidobj); if ([callidobj isKindOfClass:[NSDictionary class]]) { self.callid = [callidobj objectForKey:@"callid"]; } } NSLog(@"遠(yuǎn)程推送 callid=%@",self.callid); } 然后需要實現(xiàn) /** @brief 需要獲取的離線呼叫CallId (用于蘋果推送下來的離線呼叫callid) @return 消息數(shù) -1:全部獲取 0:不獲取 */ - (NSString*)onGetOfflineCallId { NSLog(@"推送 onGetOfflineCallId=%@", [AppDelegate shareInstance].callid); return [AppDelegate shareInstance].callid; }
注意:在集成音視頻通話的時候,當(dāng)結(jié)束當(dāng)前通話的時候,需要在處理回調(diào)事件的onCallEvents中調(diào)用一下releaseCall方法,以保證當(dāng)前通話占用的資源都釋放了,避免在下次呼叫的時候出現(xiàn)線路被占用現(xiàn)象。(android、ios均需這樣操作),Ios的調(diào)用地方,onCallEvents中的ECallEnd,代碼如下:
//有呼叫,調(diào)起對應(yīng)的界面 - (NSString*)onIncomingCallReceived:(NSString*)callid withCallerAccount:(NSString *)caller withCallerPhone:(NSString *)callerphone withCallerName:(NSString *)callername withCallType:(CallType)calltype;{ //注意:如果Tony呼叫的是John的電話,則John的程序不會收到通知回調(diào),而且直接 //進(jìn)入PSTN網(wǎng)絡(luò),和正常打電話一樣了。 if(calltype == VOICE) { NSlog(@“網(wǎng)絡(luò)音頻呼叫,調(diào)起音頻呼叫的界面”); else if(CallType == VIDEO) { NSLog (@“網(wǎng)絡(luò)音頻呼叫,調(diào)起視頻呼叫的界面”); } } // 主叫端呼叫的時候,會有多種狀態(tài) 呼叫事件的回調(diào) (1)需要注冊一個通知,告知外部呼叫的狀態(tài) - (void)onCallEvents:(VoIPCall*)voipCall { [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_onCallEvent object:voipCall]; } (2)外部成為觀察者,并在通知里面監(jiān)聽呼叫的狀態(tài) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onCallEvents:) name:KNOTIFICATION_onCallEvent object:nil]; 監(jiān)聽呼叫的狀態(tài) -(void)onCallEvents:(NSNotification *)notification { VoIPCall* voipCall = notification.object; if (![self.callID isEqualToString:voipCall.callID]){return;} // 呼叫的狀態(tài) ECallProceeding = 0, //外呼,服務(wù)器回100Tring ECallAlerting, //外呼對方振鈴 ECallFailed, //外呼失敗 ECallRing, //呼叫振鈴 ECallStreaming, //通話,外呼和來電 ECallReleasing, //釋放呼叫請求中 ECallPaused, //呼叫保持 ECallPausedByRemote, //呼叫被保持 ECallResumed, //呼叫恢復(fù) ECallResumedByRemote, //呼叫被恢復(fù) ECallTransfered, //呼叫被轉(zhuǎn)移 ECallEnd //呼叫釋放 switch (voipCall.callStatus) { case ECallProceeding: { } break; case ECallStreaming: { } break; case ECallAlerting: { } break; case ECallEnd: { } break; case ECallRing: { } break; case ECallPaused: { } break; case ECallPausedByRemote: { } break; case ECallResumed: { } break; case ECallResumedByRemote: { } break; case ECallTransfered: { } break; case ECallFailed: { NSlog(@"Tony收到呼叫John失敗的回調(diào)"); if( voipCall.reason == ECErrorType_NoResponse) { NSLog(@"網(wǎng)絡(luò)不給力"); } else if( voipCall.reason == ECErrorType_BadCredentials ) { NSLog(@"鑒權(quán)失敗"); } else if ( voipCall.reason == ECErrorType_CallBusy || voipCall.reason == ECErrorType_Declined ) { NSLog(@"您撥叫的用戶正忙,請稍后再撥"); } else if( voipCall.reason == ECErrorType_NoResponse) { NSLog(@"對方不在線"); } else if( voipCall.reason == ECErrorType_CallMissed ) { NSLog(@"呼叫超時"); } else if( voipCall.reason == ECErrorType_NoNetwork ) { NSLog(@"當(dāng)前無網(wǎng)絡(luò)"); } else if( voipCall.reason == ECErrorType_SDKUnSupport) { NSLog(@"該版本不支持此功能"); } else if( voipCall.reason == ECErrorType_CalleeSDKUnSupport ) { NSLog(@"對方版本不支持音頻"); } else { NSLog(@"呼叫失敗"); } } break; case ECallEnd: { //無論是Tony還是John主動結(jié)束通話,雙方都會進(jìn)入到此回調(diào) NSLog(@"掛機"); } break; default: break; } }
2.2、被叫端界面的處理
假設(shè)John側(cè)調(diào)起來音頻或者視頻呼入的界面,界面上有“接受”和“拒絕”兩個按鈕:
(1)John點擊“接受”按鈕,則調(diào)用的代碼是 //如果視頻呼叫,則在接受呼叫之前,需要先設(shè)置視頻通話顯示的view [[ECDevice sharedInstance].VoIPManager setVideoView:remoteVideoView andLocalView:localVideoView]; NSInteger ret = [[ECDevice ShareIntance].VoIPManager acceptCall:self.callID withType: VOICE(視頻: VIDEO)]; if (ret == 0)// 音頻或視頻通話界面 { NSLog (@“被叫端接受呼叫成功”); } else { NSlog(@“被叫端接受呼叫失敗”); } (2)John點擊“拒絕”按鈕,音視頻拒絕的代碼是一致的,調(diào)用的代碼是: NSInteger ret = [[ECDevice ShareIntance].VoIPManager rejectCall:self.callID withType: CallType.Voice]; if (ret == 0) { NSLog (@“被叫端拒絕呼叫成功”); } else { NSLog (@“被叫端拒絕呼叫失敗”); }
[[ECDevice ShareIntance].VoIPManager releaseCall:mCurrentID];
(1)獲取通話ID
[[ECDevice sharedInstance].VoIPManager getCurrentCall; 功能:獲取當(dāng)前通話的callid, 參數(shù):無 返回值:當(dāng)前通話id
(2)發(fā)送DTMF
[[ECDevice sharedInstance].VoIPManager sendDTMF:(NSString *)callid dtmf:(NSString *)dtmf; 功能:獲取當(dāng)前通話的callid, 參數(shù):callid-通話id dtmf-鍵值 - 返回值:當(dāng)前通話id
(3)設(shè)置揚聲器狀態(tài)
[ECDevice sharedInstance] .VoIPManager enableLoudsSpeaker:(BOOL)enable; 功能:免提設(shè)置 參數(shù):enable - NO:關(guān)閉 YES:打開 返回值:無
(4)獲取揚聲器狀態(tài)
[ECDevice sharedInstance].VoIPManager getLoudsSpeakerStatus; 功能:獲取當(dāng)前免提狀態(tài) 參數(shù):enable - NO:關(guān)閉 YES:打開 返回值:無
(5)設(shè)置靜音
[ECDevice sharedInstance].VoIPManager setMute:(BOOL)on 功能:靜音設(shè)置 參數(shù):enable - NO:正常 YES:靜音 返回值:無
(6)獲取靜音的狀態(tài)
[ECDevice sharedInstance].VoIPManager getMuteStatus 功能:獲取當(dāng)前靜音狀態(tài) 參數(shù):enable - NO:正常 YES:靜音 返回值:無
(7)接近檢測,通話時如果貼近聽筒,關(guān)閉屏幕(暫緩提供)
[ECDevice sharedInstance].VoIPManager enterVoipCallFlow:(BOOL)status 功能:是否抑制馬賽克 參數(shù):NO:關(guān)閉 YES:打開 返回值:無
(8)設(shè)置視頻通話顯示的窗口
[ECDevice sharedInstance].VoIPManager setVideoView:(UIView*)view andLocalView:(UIView*)localView 功能:視頻通話顯示的view, 參數(shù):view-對方顯示視圖和本地顯示視圖 返回值:無
(9)獲取手機攝像頭參數(shù)
[ECDevice sharedInstance].VoIPManager getCameraInfo 功能:獲取攝像設(shè)備信息 參數(shù):無 返回值: 攝像設(shè)備信息數(shù)組
(10)切換前置和后置攝像頭
[[ECDevice sharedInstance].VoIPManager selectCamera:(NSInteger)cameraIndex capability:(NSInteger)capabilityIndex fps:(NSInteger)fps rotate:(ECRotate)rotate force:(BOOL)isForce scale:(CGFloat)scale] 功能:選擇使用的攝像設(shè)備 參數(shù):cameraIndex-設(shè)備index capabilityIndex-能力index fps-幀率 rotate-旋轉(zhuǎn)的角度 isForce 是否強制啟動本SDK調(diào)用的攝像頭,默認(rèn)使用NO scale 編碼縮放,正實數(shù)。默認(rèn)1.0,小于1.0縮小,大于1.0放大 返回值: 攝像設(shè)備信息數(shù)組
(11)設(shè)置編碼范式
[ECDevice sharedInstance].VoIPManager setCodecEnabledWithCodec:(ECCodec) codec andEnabled:(BOOL) enabled 功能:設(shè)置支持的編解碼方式 參數(shù):codec-編解碼類型 enabled- NO:不支持 YES:支持 返回值: 無
(12)獲取編解碼方式是否支持
[ECDevice sharedInstance].VoIPManager getCondecEnabelWithCodec:(ECCodec) codec 功能:獲取編解碼方式是否支持 參數(shù):codec-編解碼類型 返回值: NO:不支持 YES:支持
(13)設(shè)置音頻處理的類型和對用的處理模式
[ECDevice sharedInstance].VoIPManager setAudioConfigEnabledWithType:(ECAudioType) type andEnabled:(BOOL) enabled andMode:(NSInteger) mode 功能:設(shè)置音頻處理的開關(guān) 參數(shù):type-音頻處理類型 enabled-YES:開啟,NO:關(guān)閉 mode-各自對應(yīng)的模式: AUDIO_AgcMode、AUDIO_EcMode、AUDIO_NsMode. 返回值: 成功 0 失敗 -1
(14)獲取音頻處理的開關(guān)
[ECDevice sharedInstance].VoIPManager getAudioConfigEnabelWithType:(ECAudioType) type 功能:獲取音頻處理的開關(guān) 參數(shù):type-音頻處理類型 enabled-YES:開啟,NO:關(guān)閉 返回值: 成功:音頻屬性結(jié)構(gòu) 失敗:nil
(15)統(tǒng)計通話質(zhì)量
[ECDevice sharedInstance].VoIPManager getCallStatisticsWithCallid:(NSString*) digid andType:(CallType)type 功能:統(tǒng)計通話質(zhì)量 返回值: 返回丟包率等通話質(zhì)量信息對象
(16)獲取通話的網(wǎng)絡(luò)流量信息
[ECDevice sharedInstance].VoIPManager getNetworkStatisticWithCallId:(NSString*) callid 獲取通話的網(wǎng)絡(luò)流量信息 參數(shù):callid :會話ID,會議類傳入房間號 返回值:網(wǎng)絡(luò)流量信息對象
(17)設(shè)置視頻通話碼率
[ECDevice sharedInstance].VoIPManager setVideoBitRates:(NSInteger)bitrates 設(shè)置視頻通話碼率 參數(shù):bitrates 視頻碼流,kb/s,范圍30-300 返回值:無
(18)獲取服務(wù)器callSid,建議通話建立后獲取。
[[ECDevice sharedInstance].VoIPManager getServerIdFromCallId:callid 參數(shù):callid-通話id 返回值:callSid
(19)獲取用戶在線狀態(tài)
/** @brief 獲取用戶在線狀態(tài) @brief userAccs 用戶賬號數(shù)組 @param completion 執(zhí)行結(jié)果回調(diào)block */ -(void)getUsersState:(NSArray *)userAccs completion:(void(^)(ECError* error, NSArray* usersState)) completion; 例: userAccs = @”用戶賬號數(shù)組”;//每次最多獲取50人 [[ECDevice sharedInstance] getUsersState: userAccs completion:^(ECError* error, NSArray* usersState) { __strong __typeof(weakSelf)strongSelf = weakSelf; if ([strongSelf.sessionId isEqualToString:state.userAccs]) {// 判斷是否是本次會話id if (state.isOnline) { //顯示他人的在線狀態(tài) _stateLabel.text = [NSString stringWithFormat:@"%@-%@", [strongSelf getDeviceWithType:state.deviceType], [strongSelf getNetWorkWithType:state.network]]; } else { //顯示他人的不在線狀態(tài) _stateLabel.text = @"對方不在線"; } } }];
(20)單應(yīng)用多證書
/** @brief 多證書設(shè)置 @param pushCerKey 推送證書標(biāo)識,與服務(wù)器上傳證書保持一致 */ [[ECDevice sharedInstance] setPushCerKey:@"小余6位數(shù)字或字母"];
(21)設(shè)置網(wǎng)絡(luò)代理
/** @brief 設(shè)置網(wǎng)絡(luò)代理,需要走代理時登錄前設(shè)置,不支持ssl;socks5代理支持IM和點對點音視頻(關(guān)閉p2p),http代理支持IM @param proxyHost 代理服務(wù)器地址,最大長度255。當(dāng)設(shè)置空時,取消代理 @param proxyPort 代理端口 @param type 鑒權(quán)類型。 目前支持 0 不鑒權(quán);2 用戶名密碼鑒權(quán) @param authName 用戶名,最大長度255。authType=2時有效 @param authPwd 用戶名密碼,最大長度255。authType=2時有效 @param proxyType 代理類型。 目前支持 0 socks5代理;1 http代理 @return 0成功,非0失敗 */ [[ECDevice sharedInstance] setNetworkProxy:(NSString*)proxyHost port:(NSInteger)proxyPort authType:(NSInteger)type name:(NSString*)authName pwd:(NSString*)authPwd ProxyType:(NSInteger)proxyType];
文檔更新時間:2017年12月4日