1.1、实时音频、实时视频均通过相同的接口进行调用,遵循相同的业务流程。不同的业务通过呼叫接口参数CallType进行区分,VIDEO视频、VOICE音频等。
1.2、接口逻辑:
接口调用是采取异步调用的方式。所有的呼叫相关接口的调用结果通过回调接口ECVoIPCallDelegate中的方法OnCallEvents来接受服务端返回的各种状态。
1.3、业务流程
(1)客户A呼叫客户B发起请求
(2)云通讯服务端收到A请求并把请求转发给B
(3)客户B收到请求并应答
(4)云通讯服务端收到B应答并转发A
(5)A收到应答,通话建立
2.1、呼叫界面处理
self.callID = [[ECDevice sharedInstance].VoIPManager makeCallWithType:VOICE andCalled:@ "John的登录账号"]; if (self.callid.length <= 0)//获取CallID失败,即拨打失败 { } 说明:self.callID如果返回空则代表呼叫失败,可能是参数错误引起。否则返回是一串数字,是当前通话的标识。
[[ECDevice sharedInstance].VoIPManager setVideoView:remoteVideoView andLocalView:localVideoView]; self.callID = [[ECDevice sharedInstance].VoIPManager makeCallWithType:VIDEO andCalled: @ "John的登录号码"]; if (self.callid.length <= 0)//获取CallID失败,即拨打失败 { } 说明:self.callID如果返回空则代表呼叫失败,可能是参数错误引起。否则返回是一串数字,是当前通话的标识。 视频时(包含点对点和会议),设置远端UIView的属性contentMode:(setVideoView:remoteVideoView) UIViewContentModeScaleToFill //view默认值,图像数据显示,填充view,但不等比例拉伸 UIViewContentModeScaleAspectFit //图像等比例拉伸,完全显示内容 UIViewContentModeScaleAspectFill //图像等比例拉伸,填充view,部分内容可能不显示
- (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:@"推送内容" message:str delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil]; [alert show]; NSLog(@"远程推送str:%@",str); NSLog(@"远程推送1:%@",userInfo); NSLog(@"远程推送r:%@",[userInfo objectForKey:@"r"]); NSLog(@"远程推送s:%@",[userInfo objectForKey:@"s"]); self.callid = nil; NSString *userdata = [userInfo objectForKey:@"c"]; NSLog(@"远程推送userdata:%@",userdata); if (userdata) { NSDictionary*callidobj = [NSJSONSerialization JSONObjectWithData:[userdata dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:nil]; NSLog(@"远程推送callidobj:%@",callidobj); if ([callidobj isKindOfClass:[NSDictionary class]]) { self.callid = [callidobj objectForKey:@"callid"]; } } NSLog(@"远程推送 callid=%@",self.callid); } 然后需要实现 /** @brief 需要获取的离线呼叫CallId (用于苹果推送下来的离线呼叫callid) @return 消息数 -1:全部获取 0:不获取 */ - (NSString*)onGetOfflineCallId { NSLog(@"推送 onGetOfflineCallId=%@", [AppDelegate shareInstance].callid); return [AppDelegate shareInstance].callid; }
注意:在集成音视频通话的时候,当结束当前通话的时候,需要在处理回调事件的onCallEvents中调用一下releaseCall方法,以保证当前通话占用的资源都释放了,避免在下次呼叫的时候出现线路被占用现象。(android、ios均需这样操作),Ios的调用地方,onCallEvents中的ECallEnd,代码如下:
//有呼叫,调起对应的界面 - (NSString*)onIncomingCallReceived:(NSString*)callid withCallerAccount:(NSString *)caller withCallerPhone:(NSString *)callerphone withCallerName:(NSString *)callername withCallType:(CallType)calltype;{ //注意:如果Tony呼叫的是John的电话,则John的程序不会收到通知回调,而且直接 //进入PSTN网络,和正常打电话一样了。 if(calltype == VOICE) { NSlog(@“网络音频呼叫,调起音频呼叫的界面”); else if(CallType == VIDEO) { NSLog (@“网络音频呼叫,调起视频呼叫的界面”); } } // 主叫端呼叫的时候,会有多种状态 呼叫事件的回调 (1)需要注册一个通知,告知外部呼叫的状态 - (void)onCallEvents:(VoIPCall*)voipCall { [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_onCallEvent object:voipCall]; } (2)外部成为观察者,并在通知里面监听呼叫的状态 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onCallEvents:) name:KNOTIFICATION_onCallEvent object:nil]; 监听呼叫的状态 -(void)onCallEvents:(NSNotification *)notification { VoIPCall* voipCall = notification.object; if (![self.callID isEqualToString:voipCall.callID]){return;} // 呼叫的状态 ECallProceeding = 0, //外呼,服务器回100Tring ECallAlerting, //外呼对方振铃 ECallFailed, //外呼失败 ECallRing, //呼叫振铃 ECallStreaming, //通话,外呼和来电 ECallReleasing, //释放呼叫请求中 ECallPaused, //呼叫保持 ECallPausedByRemote, //呼叫被保持 ECallResumed, //呼叫恢复 ECallResumedByRemote, //呼叫被恢复 ECallTransfered, //呼叫被转移 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失败的回调"); if( voipCall.reason == ECErrorType_NoResponse) { NSLog(@"网络不给力"); } else if( voipCall.reason == ECErrorType_BadCredentials ) { NSLog(@"鉴权失败"); } 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(@"当前无网络"); } else if( voipCall.reason == ECErrorType_SDKUnSupport) { NSLog(@"该版本不支持此功能"); } else if( voipCall.reason == ECErrorType_CalleeSDKUnSupport ) { NSLog(@"对方版本不支持音频"); } else { NSLog(@"呼叫失败"); } } break; case ECallEnd: { //无论是Tony还是John主动结束通话,双方都会进入到此回调 NSLog(@"挂机"); } break; default: break; } }
2.2、被叫端界面的处理
假设John侧调起来音频或者视频呼入的界面,界面上有“接受”和“拒绝”两个按钮:
(1)John点击“接受”按钮,则调用的代码是 //如果视频呼叫,则在接受呼叫之前,需要先设置视频通话显示的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点击“拒绝”按钮,音视频拒绝的代码是一致的,调用的代码是: 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; 功能:获取当前通话的callid, 参数:无 返回值:当前通话id
(2)发送DTMF
[[ECDevice sharedInstance].VoIPManager sendDTMF:(NSString *)callid dtmf:(NSString *)dtmf; 功能:获取当前通话的callid, 参数:callid-通话id dtmf-键值 - 返回值:当前通话id
(3)设置扬声器状态
[ECDevice sharedInstance] .VoIPManager enableLoudsSpeaker:(BOOL)enable; 功能:免提设置 参数:enable - NO:关闭 YES:打开 返回值:无
(4)获取扬声器状态
[ECDevice sharedInstance].VoIPManager getLoudsSpeakerStatus; 功能:获取当前免提状态 参数:enable - NO:关闭 YES:打开 返回值:无
(5)设置静音
[ECDevice sharedInstance].VoIPManager setMute:(BOOL)on 功能:静音设置 参数:enable - NO:正常 YES:静音 返回值:无
(6)获取静音的状态
[ECDevice sharedInstance].VoIPManager getMuteStatus 功能:获取当前静音状态 参数:enable - NO:正常 YES:静音 返回值:无
(7)接近检测,通话时如果贴近听筒,关闭屏幕(暂缓提供)
[ECDevice sharedInstance].VoIPManager enterVoipCallFlow:(BOOL)status 功能:是否抑制马赛克 参数:NO:关闭 YES:打开 返回值:无
(8)设置视频通话显示的窗口
[ECDevice sharedInstance].VoIPManager setVideoView:(UIView*)view andLocalView:(UIView*)localView 功能:视频通话显示的view, 参数:view-对方显示视图和本地显示视图 返回值:无
(9)获取手机摄像头参数
[ECDevice sharedInstance].VoIPManager getCameraInfo 功能:获取摄像设备信息 参数:无 返回值: 摄像设备信息数组
(10)切换前置和后置摄像头
[[ECDevice sharedInstance].VoIPManager selectCamera:(NSInteger)cameraIndex capability:(NSInteger)capabilityIndex fps:(NSInteger)fps rotate:(ECRotate)rotate force:(BOOL)isForce scale:(CGFloat)scale] 功能:选择使用的摄像设备 参数:cameraIndex-设备index capabilityIndex-能力index fps-帧率 rotate-旋转的角度 isForce 是否强制启动本SDK调用的摄像头,默认使用NO scale 编码缩放,正实数。默认1.0,小于1.0缩小,大于1.0放大 返回值: 摄像设备信息数组
(11)设置编码范式
[ECDevice sharedInstance].VoIPManager setCodecEnabledWithCodec:(ECCodec) codec andEnabled:(BOOL) enabled 功能:设置支持的编解码方式 参数:codec-编解码类型 enabled- NO:不支持 YES:支持 返回值: 无
(12)获取编解码方式是否支持
[ECDevice sharedInstance].VoIPManager getCondecEnabelWithCodec:(ECCodec) codec 功能:获取编解码方式是否支持 参数:codec-编解码类型 返回值: NO:不支持 YES:支持
(13)设置音频处理的类型和对用的处理模式
[ECDevice sharedInstance].VoIPManager setAudioConfigEnabledWithType:(ECAudioType) type andEnabled:(BOOL) enabled andMode:(NSInteger) mode 功能:设置音频处理的开关 参数:type-音频处理类型 enabled-YES:开启,NO:关闭 mode-各自对应的模式: AUDIO_AgcMode、AUDIO_EcMode、AUDIO_NsMode. 返回值: 成功 0 失败 -1
(14)获取音频处理的开关
[ECDevice sharedInstance].VoIPManager getAudioConfigEnabelWithType:(ECAudioType) type 功能:获取音频处理的开关 参数:type-音频处理类型 enabled-YES:开启,NO:关闭 返回值: 成功:音频属性结构 失败:nil
(15)统计通话质量
[ECDevice sharedInstance].VoIPManager getCallStatisticsWithCallid:(NSString*) digid andType:(CallType)type 功能:统计通话质量 返回值: 返回丢包率等通话质量信息对象
(16)获取通话的网络流量信息
[ECDevice sharedInstance].VoIPManager getNetworkStatisticWithCallId:(NSString*) callid 获取通话的网络流量信息 参数:callid :会话ID,会议类传入房间号 返回值:网络流量信息对象
(17)设置视频通话码率
[ECDevice sharedInstance].VoIPManager setVideoBitRates:(NSInteger)bitrates 设置视频通话码率 参数:bitrates 视频码流,kb/s,范围30-300 返回值:无
(18)获取服务器callSid,建议通话建立后获取。
[[ECDevice sharedInstance].VoIPManager getServerIdFromCallId:callid 参数:callid-通话id 返回值:callSid
(19)获取用户在线状态
/** @brief 获取用户在线状态 @brief userAccs 用户账号数组 @param completion 执行结果回调block */ -(void)getUsersState:(NSArray *)userAccs completion:(void(^)(ECError* error, NSArray* usersState)) completion; 例: userAccs = @”用户账号数组”;//每次最多获取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) { //显示他人的在线状态 _stateLabel.text = [NSString stringWithFormat:@"%@-%@", [strongSelf getDeviceWithType:state.deviceType], [strongSelf getNetWorkWithType:state.network]]; } else { //显示他人的不在线状态 _stateLabel.text = @"对方不在线"; } } }];
(20)单应用多证书
/** @brief 多证书设置 @param pushCerKey 推送证书标识,与服务器上传证书保持一致 */ [[ECDevice sharedInstance] setPushCerKey:@"小余6位数字或字母"];
(21)设置网络代理
/** @brief 设置网络代理,需要走代理时登录前设置,不支持ssl;socks5代理支持IM和点对点音视频(关闭p2p),http代理支持IM @param proxyHost 代理服务器地址,最大长度255。当设置空时,取消代理 @param proxyPort 代理端口 @param type 鉴权类型。 目前支持 0 不鉴权;2 用户名密码鉴权 @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日