環(huán)信3.0ios客戶端的集成(九)

版本記錄

版本號(hào) 時(shí)間
V1.0 2017.06.10

前言

很多app種都集成環(huán)信做第三方信息通訊工具,這里我們就看一下環(huán)信的主要功能和集成方法。先給出環(huán)信3.0的地址没宾。
感興趣的可以參考:
1. 環(huán)信ios客戶端的集成(一)
2. 環(huán)信ios客戶端的集成(二)
3. 環(huán)信ios客戶端的集成(三)
4. 環(huán)信ios客戶端的集成(四)
5. 環(huán)信ios客戶端的集成(五)
6. 環(huán)信ios客戶端的集成(六)
7. 環(huán)信ios客戶端的集成(七)
8. 環(huán)信ios客戶端的集成(八)
這一篇主要說一下環(huán)信的 實(shí)時(shí)通話侠讯。

一、實(shí)時(shí)通話的數(shù)據(jù)流量

環(huán)信實(shí)時(shí)通話分為視頻通話和語音通話把介,SDK 提供簡單的 API邑退,方便開發(fā)者簡單的接入實(shí)時(shí)通話功能。

實(shí)時(shí)語音和實(shí)時(shí)視頻通話的數(shù)據(jù)流量如下:

  • 實(shí)時(shí)語音:雙向 170k bytes/minute
  • 實(shí)時(shí)視頻:雙向 2.5M~3M bytes/minute

二劳澄、配置工程

1. 在項(xiàng)目中導(dǎo)入庫

Hyphenate.framework   //包含實(shí)時(shí)音視頻的庫

AVFoundation.framework

2. 在項(xiàng)目中導(dǎo)入頭文件

#import <Hyphenate/Hyphenate.h>

3. 配置屬性

進(jìn)行音視頻之前地技,設(shè)置全局的音視頻屬性,具體屬性有哪些請(qǐng)查看頭文件 EMCallOptions

EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];
//當(dāng)對(duì)方不在線時(shí)秒拔,是否給對(duì)方發(fā)送離線消息和推送莫矗,并等待對(duì)方回應(yīng)
options.isSendPushIfOffline = NO;
[[EMClient sharedClient].callManager setCallOptions:options];

具體實(shí)現(xiàn)可以參考 Demo: DemoCallManager 和 EMCallViewController


三、發(fā)起實(shí)時(shí)通話

用戶可以調(diào)用發(fā)起語音或者視頻 API 向在線用戶發(fā)起實(shí)時(shí)通話砂缩。

/*!
 *  發(fā)起實(shí)時(shí)會(huì)話
 *
 *  @param aType            通話類型
 *  @param aRemoteName      被呼叫的用戶(不能與自己通話)
 *  @param aExt             通話擴(kuò)展信息作谚,會(huì)傳給被呼叫方
 *  @param aCompletionBlock 完成的回調(diào)
 */
- (void)startCall:(EMCallType)aType
       remoteName:(NSString *)aRemoteName
              ext:(NSString *)aExt
       completion:(void (^)(EMCallSession *aCallSession, EMError *aError))aCompletionBlock;

示例代碼:創(chuàng)建視頻通話

void (^completionBlock)(EMCallSession *, EMError *) = ^(EMCallSession *aCallSession, EMError *aError){
    //創(chuàng)建通話實(shí)例是否成功
    //TODO: code 
};
   
[[EMClient sharedClient].callManager startCall:EMCallTypeVideo remoteName:aUsername ext:nil completion:^(EMCallSession *aCallSession, EMError *aError) {
    completionBlock(aCallSession, aError);
}];


四、被叫方同意實(shí)時(shí)通話

接收到通話時(shí)調(diào)用此 API 同意實(shí)時(shí)通話庵芭。

/*!
 *  接收方同意通話請(qǐng)求
 *
 *  @param  aCallId     通話ID
 *
 *  @result 錯(cuò)誤信息
 */
- (EMError *)answerIncomingCall:(NSString *)aCallId;

//調(diào)用:
//EMError *error = nil;
//error = [[EMClient sharedClient].callManager answerIncomingCall:@"sessionId"];   


五妹懒、結(jié)束實(shí)時(shí)通話

根據(jù)不同場(chǎng)景可以選擇結(jié)束會(huì)話的原因。

例如:拒接選擇 EMCallEndReasonDecline双吆,主動(dòng)掛斷選擇 EMCallEndReasonHangup眨唬。

typedef enum{
    EMCallEndReasonHangup   = 0,    /*! 對(duì)方掛斷 */
    EMCallEndReasonNoResponse,      /*! 對(duì)方?jīng)]有響應(yīng) */
    EMCallEndReasonDecline,         /*! 對(duì)方拒接 */
    EMCallEndReasonBusy,            /*! 對(duì)方占線 */
    EMCallEndReasonFailed,          /*! 失敗 */
    EMCallEndReasonUnsupported,     /*! 功能不支持 */
}EMCallEndReason;


/*!
 *  結(jié)束通話
 *
 *  @param aCallId     通話的ID
 *  @param aReason     結(jié)束原因
 *
 *  @result 錯(cuò)誤
 */
- (EMError *)endCall:(NSString *)aCallId
              reason:(EMCallEndReason)aReason;
//調(diào)用:
//[[EMClient sharedClient].callManager endCall:@"sessionId" reason:aReason];


六、創(chuàng)建通話頁面

SDK提供了用于顯示本地視頻的頁面類EMCallLocalView好乐,顯示對(duì)方視頻的頁面類EMCallRemoteView匾竿,建議在同意接通視頻通話之后再初始化 EMCallRemoteView頁面。

//前提:EMCallSession *callSession 存在
CGFloat width = 80;
CGFloat height = self.view.frame.size.height / self.view.frame.size.width * width;
callSession.localVideoView = [[EMCallLocalView alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 90, CGRectGetMaxY(_statusLabel.frame), width, height)];
[self.view addSubview:callSession.localVideoView];
    
//同意接聽視頻通話之后
callSession.remoteVideoView = [[EMCallRemoteView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
//設(shè)置視頻頁面縮放方式
callSession.remoteVideoView.scaleMode = EMCallViewScaleModeAspectFill;
[self.view addSubview:_callSession.remoteVideoView];


七蔚万、擴(kuò)展功能之 錄制和截屏

??EMCallSession中錄制及截屏接口已廢棄岭妖,該功能作為音視頻的插件之一單獨(dú)打成了靜態(tài)庫。錄制和截屏都必須在通話已經(jīng)開始進(jìn)行之后再調(diào)用反璃。
點(diǎn)擊下載靜態(tài)庫

1. 頭文件

EMAVPluginRecorder.h

2. 庫

libbz2.tbd
libHyphenatePluginRecorder.a
libffmpeg-ios-full.a

3. 使用教程

必須在開始通話之前調(diào)用[EMAVPluginRecorder initGlobal]昵慌,該方法為全局方法,只需要調(diào)用一次即可

示例代碼:開始錄制(已經(jīng)開始通話之后再調(diào)用)

NSString *recordPath = NSHomeDirectory();
recordPath = [NSString stringWithFormat:@"%@/Library/appdata/chatbuffer", recordPath];
NSFileManager *fm = [NSFileManager defaultManager];
if(![fm fileExistsAtPath:recordPath]) {
    [fm createDirectoryAtPath:recordPath  withIntermediateDirectories:YES attributes:nil error:nil];
}

[EMAVPluginRecorder startVideoRecord:recordPath];

示例代碼:停止錄制


NSString *filePath = [EMAVPluginRecorder stopVideoRecord];

示例代碼:截屏(已經(jīng)開始通話之后再調(diào)用)

NSString *imgPath = NSHomeDirectory();
imgPath = [NSString stringWithFormat:@"%@/Library/appdata/chatbuffer/img.jpeg", imgPath];
[EMAVPluginRecorder takeRemotePicture:imgPath];


八淮蜈、實(shí)時(shí)通話相關(guān) API

暫驼剩恢復(fù)實(shí)時(shí)通話的數(shù)據(jù)傳輸相關(guān) API。


/*!
 *  暫停語音數(shù)據(jù)傳輸
 *
 *  @result 錯(cuò)誤
 */
- (EMError *)pauseVoice;

/*!
 *  恢復(fù)語音數(shù)據(jù)傳輸
 *
 *  @result 錯(cuò)誤
 */
- (EMError *)resumeVoice;

/*!
 *  暫停視頻圖像數(shù)據(jù)傳輸
 *
 *  @result 錯(cuò)誤
 */
- (EMError *)pauseVideo;

/*!
 *  恢復(fù)視頻圖像數(shù)據(jù)傳輸
 *
 *  @result 錯(cuò)誤
 */
- (EMError *)resumeVideo;

實(shí)時(shí)通話前后攝像頭切換相關(guān)API

#pragma mark - Camera

/*!
 *  設(shè)置使用前置攝像頭還是后置攝像頭,默認(rèn)使用前置攝像頭
 *
 *  @param  aIsFrontCamera    是否使用前置攝像頭, YES使用前置, NO使用后置
 */
- (void)switchCameraPosition:(BOOL)aIsFrontCamera;

九礁芦、實(shí)時(shí)通話相關(guān)的回調(diào)

注冊(cè)實(shí)時(shí)通話回調(diào)

//注冊(cè)實(shí)時(shí)通話回調(diào)
[[EMClient sharedClient].callManager addDelegate:self delegateQueue:nil];
//移除實(shí)時(shí)通話回調(diào)
[[EMClient sharedClient].callManager removeDelegate:self];

相關(guān)回調(diào)說明:

/*!
 *  用戶A撥打用戶B蜻韭,用戶B會(huì)收到這個(gè)回調(diào)
 *
 *  @param aSession  會(huì)話實(shí)例
 */
- (void)callDidReceive:(EMCallSession *)aSession;

/*!
 *  通話通道建立完成悼尾,用戶A和用戶B都會(huì)收到這個(gè)回調(diào)
 *
 *  @param aSession  會(huì)話實(shí)例
 */
- (void)callDidConnect:(EMCallSession *)aSession;

/*!
 *  用戶B同意用戶A撥打的通話后,用戶A會(huì)收到這個(gè)回調(diào)
 *
 *  @param aSession  會(huì)話實(shí)例
 */
- (void)callDidAccept:(EMCallSession *)aSession;

/*!
 *  1. 用戶A或用戶B結(jié)束通話后肖方,對(duì)方會(huì)收到該回調(diào)
 *  2. 通話出現(xiàn)錯(cuò)誤闺魏,雙方都會(huì)收到該回調(diào)
 *
 *  @param aSession  會(huì)話實(shí)例
 *  @param aReason   結(jié)束原因
 *  @param aError    錯(cuò)誤
 */
- (void)callDidEnd:(EMCallSession *)aSession
            reason:(EMCallEndReason)aReason
             error:(EMError *)aError;

/*!
 *  用戶A和用戶B正在通話中,用戶A中斷或者繼續(xù)數(shù)據(jù)流傳輸時(shí)俯画,用戶B會(huì)收到該回調(diào)
 *
 *  @param aSession  會(huì)話實(shí)例
 *  @param aType     改變類型
 */
- (void)callStateDidChange:(EMCallSession *)aSession
                      type:(EMCallStreamingStatus)aType;


十析桥、弱網(wǎng)檢測(cè)

通過回調(diào)通知應(yīng)用當(dāng)前實(shí)時(shí)通話網(wǎng)絡(luò)狀態(tài)。

typedef enum{
    EMCallNetworkStatusNormal = 0,  /*! 正常 */
    EMCallNetworkStatusUnstable,    /*! 不穩(wěn)定 */
    EMCallNetworkStatusNoData,      /*! 沒有數(shù)據(jù) */
}EMCallNetworkStatus;

/*!
 *  用戶A和用戶B正在通話中艰垂,用戶A的網(wǎng)絡(luò)狀態(tài)出現(xiàn)不穩(wěn)定泡仗,用戶A會(huì)收到該回調(diào)
 *
 *  @param aSession  會(huì)話實(shí)例
 *  @param aStatus   當(dāng)前狀態(tài)
 */
- (void)callNetworkDidChange:(EMCallSession *)aSession
                      status:(EMCallNetworkStatus)aStatus


十一、離線發(fā)推送

1.配置屬性

EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];
//當(dāng)對(duì)方不在線時(shí)猜憎,是否給對(duì)方發(fā)送離線消息和推送娩怎,并等待對(duì)方回應(yīng)
options.isSendPushIfOffline = NO;
[[EMClient sharedClient].callManager setCallOptions:options];

2.監(jiān)聽回調(diào)

[[EMClient sharedClient].callManager setBuilderDelegate:self];

3. 處理回調(diào)

- (void)callRemoteOffline:(NSString *)aRemoteName
{
    NSString *text = [[EMClient sharedClient].callManager getCallOptions].offlineMessageText;
    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:text];
    NSString *fromStr = [EMClient sharedClient].currentUsername;
    EMMessage *message = [[EMMessage alloc] initWithConversationID:aRemoteName from:fromStr to:aRemoteName body:body ext:@{@"em_apns_ext":@{@"em_push_title":text}}];
    message.chatType = EMChatTypeChat;
    
    [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil];
}

后記

未完,待續(xù)~~~

風(fēng)景
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胰柑,一起剝皮案震驚了整個(gè)濱河市截亦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柬讨,老刑警劉巖崩瓤,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異踩官,居然都是意外死亡却桶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門蔗牡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颖系,“玉大人,你說我怎么就攤上這事蛋逾〖恚” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵区匣,是天一觀的道長。 經(jīng)常有香客問我蒋院,道長亏钩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任欺旧,我火速辦了婚禮姑丑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辞友。我一直安慰自己栅哀,他們只是感情好震肮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著留拾,像睡著了一般戳晌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痴柔,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天沦偎,我揣著相機(jī)與錄音,去河邊找鬼咳蔚。 笑死豪嚎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谈火。 我是一名探鬼主播侈询,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼糯耍!你這毒婦竟也來了扔字?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤谍肤,失蹤者是張志新(化名)和其女友劉穎啦租,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荒揣,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡篷角,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了系任。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恳蹲。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俩滥,靈堂內(nèi)的尸體忽然破棺而出嘉蕾,到底是詐尸還是另有隱情,我是刑警寧澤霜旧,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布错忱,位于F島的核電站,受9級(jí)特大地震影響挂据,放射性物質(zhì)發(fā)生泄漏以清。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一崎逃、第九天 我趴在偏房一處隱蔽的房頂上張望掷倔。 院中可真熱鬧,春花似錦个绍、人聲如沸勒葱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凛虽。三九已至死遭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涩维,已是汗流浹背殃姓。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瓦阐,地道東北人蜗侈。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像睡蟋,于是被迫代替她去往敵國和親踏幻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1)項(xiàng)目里面不需要環(huán)信SDK的太多功能戳杀,只是想要聊天和好友功能该面,其他都不用,那SDK一定要總是跟著更新么信卡? a.環(huán)...
    DefaultYuan閱讀 26,558評(píng)論 17 59
  • 希望是我的行囊隔缀,風(fēng)兒是我的翅膀。還有遠(yuǎn)方傍菇,我聽見了猾瘸,是你的呼喚。 在路上丢习,知了的叫聲可是最好的慰藉牵触,可以讓陽光,不...
    A區(qū)四十五號(hào)庫閱讀 220評(píng)論 0 2
  • 最近刷劇太多咐低,導(dǎo)致只能回味一些舊劇揽思,尤其曾經(jīng)沉迷一時(shí)的泰劇,泰國三少的電視劇我居然又無聊地刷了一遍见擦。其中钉汗,只出過兩...
    嘗酥品甜閱讀 183評(píng)論 0 0
  • 第一百六十六天。 “黃赤交角是地球公轉(zhuǎn)軌道面與赤道面的交角……約為23°26'……”老師在講臺(tái)上娓娓道來鲤屡。 握著筆...
    阿明sunshine閱讀 183評(píng)論 0 0
  • 第一次作業(yè)模板 1儡湾、什么是教學(xué)服務(wù)?你的理解是什么执俩? 教師用專業(yè)和責(zé)任贏得客戶信任的課堂外服務(wù)。 ...
    Smile_2543閱讀 263評(píng)論 1 1