環信音視頻功能學習總結

集成iOS SDk前的準備:

(如果需要推送消息,則要到蘋果官網上製作證書,再到環信後臺製作推送證書http://www.easemob.com/docs/ios/IOSSDKPrepare/#registerDeveloper)

註冊環信開發者賬號並創建後臺應用,

登陸地址:https://console.easemob.com/?comeFrom=easemobHome

註冊模式爲開放註冊,填寫對應信息後得到AppKey

 

需要用到的內容:

EMCallManagerDelegate語音視頻代理

AVFoundation音頻輸出

EMCallSession會話信息

 

音視頻集成過程:

1、在環信官網申請一個AppKey

2、導入SDK

環信官方下載SDK和官方Demo,打開Xcode工程將下載的iOS_IM_SDK_V3.6.0文件夾下的EaseUI(UI框架)文件夾與HyphenateFullSDK(包含實時通話)文件夾或HyphenateSDK(不包含實時通話功能的SDK)添加到項目工程中(注意勾選Copy items if needed、Create groups與Add to targets)

用cocoapods添加HyphenateSDK(不包含實時通話功能的SDK)、HyphenateFullSDK(包含實時通話的SDK)和EaseUI(集成sdk到項目中)

#Lite版本(不帶實時音視頻通話功能) 

pod 'HyphenateLite' 

#Full版本(帶實時音視頻通話功能) 

pod 'Hyphenate'

在Podfile目錄下執行指令pod install

注:用到一些Demo中的內容3rdparty、chatSDK、ChatUI

3、設置工程屬性:

選擇工程名-->TARGETS-->General-->Embedded Binaries添加Hyphenate.framework

HyphenateLite.framework

向General→Linked Frameworks andLibraies 中添加

HyphenateLite.framework(將【Required】改爲【Optional】)

Hyphenate.framework(將【Required】改爲【Optional】)

向Build Phases →Link Binary With Libraries 中添加依賴庫:

CoreMedia.framework

AudioToolbox.framework

AVFoundation.framework

MobileCoreServices.framework

ImageIO.framework

libc++.dylib

libz.dylib

libstdc++.6.0.9.dylib

libsqlite3.dylib

libiconv.dylib

官方漏掉了的系統庫:

CoreMotion.framework  

UserNotifications.framework 

AssetsLibrary.framework

MapKit.framework

Photos.framework

libbz2.1.0.dylib

後端雲LeanCloud需要引入的依賴庫:

libicucore.dylib

SystemConfiguration.framework

CoreTelephony.framework

CoreLocation.framework

(如果使用的是xcode7+,後綴爲tbd)

(SDK不支持bitcode,Build Settings → 搜索bitcode →Enable Bitcode 中設置NO,此時編譯不報錯,集成成功)

4、編寫頁面邏輯,會話列表+聊天界面(環信有提供列表頁,在EaseUI的子文件夾EMUIKit的子文件夾ViewController就已經包含了UI頁面,找到EMiOSDemo→Class→Call+EMDemoHelper添加到自己的工程中,修改對應的EMDemoHelper工具類中的報錯)

提醒:在集成時必須向工程導入Helper模塊,然後在根據需求導入其他模塊。

環信UI模塊依賴於以下三方庫:

pod 'Bugly'

pod 'Masonry'

pod 'MJRefresh'

pod 'MBProgressHUD', '~> 1.1.0'

pod 'SDWebImage', '~> 4.0'

pod 'SDWebImage/GIF'

pod 'FLAnimatedImage', '~> 1.0'

pod 'Hyphenate'

5、增加隱私權限,在工程info.plist文件裏面添加隱私權限,用於Chat聊天模塊發送圖片,語音,視頻,位置消息使用

Privacy - Photo Library Usage Description 需要訪問您的相冊

Privacy - Microphone Usage Description 需要訪問您的麥克風(是否允許此使用你的麥克風

Privacy - Camera Usage Description 需要訪問您的相機(是否允許使用你的相機)

Privacy - Location Always Usage Description 需要您的同意,才能在使用期間訪問位置

Privacy - Location When In Use Usage Description 需要您的同意,才能始終訪問位置

6、.pch配置(從官方的Demo中的.pch中粘貼即可)

#ifdef __OBJC__

#import <UIKit/UIKit.h>

#import <Foundation/Foundation.h>

//包含實時音視頻功能SDK 的頭文件

#import <Hyphenate/Hyphenate.h>

// UI 頭文件

#import "EMHeaders.h"

#endif

#ifdef __OBJC__

#import <UIKit/UIKit.h>

#import <Foundation/Foundation.h>

//不包含實時音視頻功能SDK 的頭文件

#import <HyphenateLite/HyphenateLite.h>

// UI 頭文件

#import "EMHeaders.h"

#endif

7、初始化SDK及登錄環信服務器

設置Appdelegate,參考Appdelegate.m文件即可

在Appdelegate中導入#import <Hyphenate/Hyphenate.h>頭文件,然後在

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

方法中使用如下代碼實現初始化即可:

// appkey替換成自己在環信管理後臺註冊應用中的appkey

EMOptions *options = [EMOptions optionsWithAppkey:@"appkey"];

// apnsCertName是證書名稱,可以先傳nil,等後期配置apns推送(蘋果推送通知服務)時在傳入證書名稱

options.apnsCertName = nil;

[[EMClient sharedClient] initializeSDKWithOptions:options];

例如:

 EMOptions *options = [EMOptions optionsWithAppkey:@"douser#istore"];

 options.apnsCertName = @"istore_dev";

 [[EMClient sharedClient] initializeSDKWithOptions:options];

// APP進入後臺

- (void)applicationDidEnterBackground:(UIApplication *)application

{

    [[EMClient sharedClient] applicationDidEnterBackground:application];

}

// APP將要從後臺返回

- (void)applicationWillEnterForeground:(UIApplication *)application

{

    [[EMClient sharedClient] applicationWillEnterForeground:application];

}

註冊模式分兩種,開放註冊和授權註冊。

只有開放註冊時,纔可以客戶端註冊。開放註冊是爲了測試使用,正式環境中不推薦使用該方式註冊環信賬號。

授權註冊的流程應該是您服務器通過環信提供的REST API 註冊,之後保存到您的服務器或返回給客戶端。

EMError *error = [[EMClient sharedClient] registerWithUsername:@"8001" password:@"111111"];

if (error==nil) {

    NSLog(@"註冊成功");

}

登錄環信服務器:調用SDK 的登錄接口進行的操作。

//傳入在應用(appkey)下注冊的IM用戶8001,密碼111111,用於登錄環信服務器

EMError *error = [[EMClient sharedClient] loginWithUsername:@"8001" password:@"111111"];

if (!error) {

    NSLog(@"登錄成功");

}

如果在集成調試階段,可以在初始化環信SDK 完成之後,就調用登錄方法。

如果項目上線,建議開發者在登錄自己服務器成功之後,再調用環信SDK 登錄方法使用用戶綁定的環信id登錄環信服務器(開發者給自己用戶在自己服務器創建賬號的同時,調用環信的rest 接口在給用戶授權註冊一個環信id,一起返回給app 端,app 端拿到用戶的賬號密碼以及環信id 密碼分別登錄自己的服務器以及環信服務器)。

8、初始化聊天界面

向工程導入Chat文件

// ConversationId接收消息方的環信ID:@"user2"

// type聊天類型:EMConversationTypeChat    單聊類型

// createIfNotExist 如果會話不存在是否創建會話:YES

EMChatViewController *chatController = [[EMChatViewController alloc] initWithConversationId:@"user2" type:EMConversationTypeChat createIfNotExist:YES];

[self.navigationController pushViewController:chatController animated:YES];

有導航的話,可以用push 方式跳轉到聊天頁面發消息測試,也就是用登錄的user1 給user2 發消息,沒有導航的話,可以用present 方式跳轉到聊天頁面。

集成實時音視頻通話

9、集成實時音視頻通話

向工程導入Chat文件

在初始化SDK 完成之後,在初始化SDK所在的類引入頭文件:

#import "DemoCallManager.h"  // 1v1實時通話功能的頭文件

#import "DemoConfManager.h"  // 多人實時通話功能的頭文件

 添加:

 [DemoCallManager sharedManager];  // 初始化1v1實時通話功能的單例

 [DemoConfManager sharedManager];  // 初始化多人實時通話功能的單例

提醒:在主控制器中添加[EMDemoHelper shareHelper].mainVC = self;

在聊天頁面中下方,點擊語音,視頻通話圖標按鈕即可使用。

10、1V1實時通話

配置屬性

進行音視頻之前,設置全局的音視頻屬性,具體屬性有哪些請查看頭文件*EMCallOptions*

EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];

//當對方不在線時,是否給對方發送離線消息和推送,並等待對方迴應

options.isSendPushIfOffline = NO;

//設置視頻分辨率:自適應分辨率、352 * 288、640 * 480、1280 * 720

options.videoResolution = EMCallVideoResolutionAdaptive;

//最大視頻碼率,範圍50 < videoKbps < 5000, 默認0, 0爲自適應,建議設置爲0

options.maxVideoKbps = 0;

//最小視頻碼率

options.minVideoKbps = 0;

//是否固定視頻分辨率,默認爲NO

options.isFixedVideoResolution = NO;

[[EMClient sharedClient].callManager setCallOptions:options];

具體實現可以參考Demo: DemoCallManager 和EMCallViewController

發起實時通話

用戶可以調用發起語音或者視頻API 向在線用戶發起實時通話。

/*!

 *  發起實時會話

 *

 * @param aType            通話類型

 * @param aRemoteName      被呼叫的用戶(不能與自己通話)

 * @param aExt             通話擴展信息,會傳給被呼叫方

 * @param aCompletionBlock 完成的回調

 */

- (void)startCall:(EMCallType)aType

       remoteName:(NSString *)aRemoteName

              ext:(NSString *)aExt

       completion:(void (^)(EMCallSession *aCallSession, EMError *aError))aCompletionBlock;

示例代碼:創建視頻通話

void (^completionBlock)(EMCallSession *, EMError *) = ^(EMCallSession *aCallSession, EMError *aError){

    //創建通話實例是否成功

    //TODO: code 

};  

[[EMClient sharedClient].callManager startCall:EMCallTypeVideo remoteName:aUsername record:ext:nil completion:^(EMCallSession *aCallSession, EMError *aError) {

    completionBlock(aCallSession, aError);

}];

被叫方同意實時通話

接收到通話時調用此API 同意實時通話。

/*!

 *  接收方同意通話請求

 *

 * @param  aCallId     通話ID

 *

 * @result 錯誤信息

 */

- (EMError *)answerIncomingCall:(NSString *)aCallId;

//調用:

//EMError *error = nil;

//error = [[EMClient sharedClient].callManager answerIncomingCall:@"sessionId"];                           

結束實時通話

根據不同場景可以選擇結束會話的原因。

例如:拒接選擇EMCallEndReasonDecline,主動掛斷選擇EMCallEndReasonHangup。

typedef enum{

    EMCallEndReasonHangup   = 0,   /*! 對方掛斷*/

    EMCallEndReasonNoResponse,      /*! 對方沒有響應*/

    EMCallEndReasonDecline,         /*! 對方拒接*/

    EMCallEndReasonBusy,            /*! 對方佔線*/

    EMCallEndReasonFailed,          /*! 失敗*/

    EMCallEndReasonUnsupported,     /*! 功能不支持*/

}EMCallEndReason;

/*!

 *  結束通話

 *

 * @param aCallId     通話的ID

 * @param aReason     結束原因

 *

 * @result 錯誤

 */

- (EMError *)endCall:(NSString *)aCallId

              reason:(EMCallEndReason)aReason;

//調用:

//[[EMClient sharedClient].callManager endCall:@"sessionId" reason:aReason];

創建通話頁面

SDK提供了用於顯示本地視頻的頁面類*EMCallLocalView*,顯示對方視頻的頁面類*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)];

//設置視頻頁面縮放方式

callSession.remoteVideoView.scaleMode = EMCallViewScaleModeAspectFill;

[self.view addSubview:_callSession.remoteVideoView];

實時通話相關API

暫停恢復實時通話的數據傳輸相關API。

/*!

 *  暫停語音數據傳輸

 *

 * @result 錯誤

 */

- (EMError *)pauseVoice;

/*!

 *  恢復語音數據傳輸

 *

 * @result 錯誤

 */

- (EMError *)resumeVoice;

/*!

 *  暫停視頻圖像數據傳輸

 *

 * @result 錯誤

 */

- (EMError *)pauseVideo;

/*!

 *  恢復視頻圖像數據傳輸

 *

 * @result 錯誤

 */

- (EMError *)resumeVideo;

實時通話前後攝像頭切換相關API

#pragma mark - Camera

/*!

 *  設置使用前置攝像頭還是後置攝像頭,默認使用前置攝像頭

 *

 * @param  aIsFrontCamera    是否使用前置攝像頭, YES使用前置, NO使用後置

 */

- (void)switchCameraPosition:(BOOL)aIsFrontCamera;

實時通話相關的回調

註冊實時通話回調

//註冊實時通話回調

[[EMClient sharedClient].callManager addDelegate:self delegateQueue:nil];

//移除實時通話回調

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

相關回調說明:

/*!

 *  用戶A撥打用戶B,用戶B會收到這個回調

 *

 * @param aSession  會話實例

 */

- (void)callDidReceive:(EMCallSession *)aSession;

/*!

 *  通話通道建立完成,用戶A和用戶B都會收到這個回調

 *

 * @param aSession  會話實例

 */

- (void)callDidConnect:(EMCallSession *)aSession;

/*!

 *  用戶B同意用戶A撥打的通話後,雙方都會收到這個回調

 *

 * @param aSession  會話實例

 */

- (void)callDidAccept:(EMCallSession *)aSession;

/*!

 *  1. 用戶A或用戶B結束通話後,對方會收到該回調

 *  2. 通話出現錯誤,雙方都會收到該回調

 *

 * @param aSession  會話實例

 * @param aReason   結束原因

 * @param aError    錯誤

 */

- (void)callDidEnd:(EMCallSession *)aSession

            reason:(EMCallEndReason)aReason

             error:(EMError *)aError;

/*!

 *  用戶A和用戶B正在通話中,用戶A中斷或者繼續數據流傳輸時,用戶B會收到該回調

 *

 * @param aSession  會話實例

 * @param aType     改變類型

 */

- (void)callStateDidChange:(EMCallSession *)aSession

                     type:(EMCallStreamingStatus)aType;

弱網檢測

通過回調通知應用當前實時通話網絡狀態。

typedef enum{

    EMCallNetworkStatusNormal = 0,  /*! 正常*/

    EMCallNetworkStatusUnstable,    /*! 不穩定*/

    EMCallNetworkStatusNoData,      /*! 沒有數據*/

}EMCallNetworkStatus;

/*!

 *  用戶A和用戶B正在通話中,用戶A的網絡狀態出現不穩定,用戶A會收到該回調

 *

 * @param aSession  會話實例

 * @param aStatus   當前狀態

 */

- (void)callNetworkDidChange:(EMCallSession *)aSession

                     status:(EMCallNetworkStatus)aStatus

離線發推送

配置屬性

EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];

//當對方不在線時,是否給對方發送離線消息和推送,並等待對方迴應

options.isSendPushIfOffline = NO;

[[EMClient sharedClient].callManager setCallOptions:options];

監聽回調

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

處理回調

- (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];

}

自定義視頻數據

配置屬性

//進行1v1自定義視頻之前,必須設置EMCallOptions.enableCustomizeVideoData=YES

EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];

options.enableCustomizeVideoData = YES;

[[EMClient sharedClient].callManager startCall:aType remoteName:aUsername ext:@"123" completion:^(EMCallSession *aCallSession, EMError *aError) {

        completionBlock(aCallSession, aError);

}];

//進行默認1v1視頻之前,必須設置EMCallOptions.enableCustomizeVideoData=NO

EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];

options.enableCustomizeVideoData = NO;

[[EMClient sharedClient].callManager startCall:aType remoteName:aUsername ext:@"123" completion:^(EMCallSession *aCallSession, EMError *aError) {

        completionBlock(aCallSession, aError);

}];

自定義攝像頭數據

設置EMCallOptions.enableCustomizeVideoData=YES 後,必須自定義攝像頭數據。

接口

/*!

 * \~chinese

 *  自定義本地視頻數據

 *

 * @param aSampleBuffer      視頻採樣緩衝區

 * @param aRotation          旋轉方向

 * @param aCallId            1v1會話實例ID,即[EMCallSession callId]

 * @param aCompletionBlock   完成後的回調

 */

- (void)inputVideoSampleBuffer:(CMSampleBufferRef)aSampleBuffer

                     rotation:(UIDeviceOrientation)aRotation

                        callId:(NSString *)aCallId

                    completion:(void (^)(EMError *aError))aCompletionBlock;

/*!

 * \~chinese

 *  自定義本地視頻數據

 *

 * @param aPixelBuffer      視頻像素緩衝區

 * @param aCallId           1v1會話實例ID,即[EMCallSession callId]

 * @param aTime             視頻原始數據時間戳,CMTime time = CMSampleBufferGetPresentationTimeStamp((CMSampleBufferRef)sampleBuffer);

 * @param aRotation         旋轉方向

 * @param aCompletionBlock  完成後的回調

 */

- (void)inputVideoPixelBuffer:(CVPixelBufferRef)aPixelBuffer

             sampleBufferTime:(CMTime)aTime

                    rotation:(UIDeviceOrientation)aRotation

                       callId:(NSString *)aCallId

                   completion:(void (^)(EMError *aError))aCompletionBlock;

11、集成其他模塊

會話列表

向工程中導入Conversation 文件

頭文件:#import “EMConversationsViewController.h”

初始化頁面跳轉(導航跳轉示例):

EMConversationsViewController *conversationVC = [[EMConversationsViewController alloc] init];

[self.navigationController pushViewController:conversationVC animated:YES];

好友列表

向工程中導入Contact 文件

頭文件:#import “EMContactsViewController.h”

初始化頁面跳轉(導航跳轉示例):

EMContactsViewController *contactVC= [[EMContactsViewController alloc] init];

[self.navigationController pushViewController:contactVC animated:YES];

羣組

向工程中導入Group 文件

頭文件:#import “EMGroupsViewController.h”

初始化頁面跳轉(導航跳轉示例):

EMGroupsViewController *groupVC= [[EMContactsViewController alloc] init];

[self.navigationController pushViewController:groupVC animated:YES];

聊天室

向工程中導入Chatroom 文件

頭文件:#import “EMChatroomsViewController.h”

初始化頁面跳轉(導航跳轉示例):

EMChatroomsViewController *chatRoomVC= [[EMChatroomsViewController alloc] init];

[self.navigationController pushViewController:chatRoomVC animated:YES];

12、集成動態庫上傳AppStore

由於iOS 編譯的特殊性,爲了方便開發者使用,我們將i386, x86_64, armv7, arm64 幾個平臺都合併到了一起,所以使用動態庫上傳appstore 時需要將i386 , x86_64 兩個平臺刪除後,才能正常提交審覈

在SDK 當前路徑下執行以下命令刪除i386, x86_64兩個平臺

bak文件是備份目錄,上傳appstore之後需要替換回bak 目錄下的SDK

實時音視頻版本Hyphenate.framework

mkdir ./bak

cp -r Hyphenate.framework ./bak

lipo Hyphenate.framework/Hyphenate -thin armv7 -output Hyphenate_armv7

lipo Hyphenate.framework/Hyphenate -thin arm64 -output Hyphenate_arm64

lipo -create Hyphenate_armv7 Hyphenate_arm64 -output Hyphenate

mv Hyphenate Hyphenate.framework/

不包含實時音視頻版本HyphenateLite.framework

mkdir ./bak

cp -r HyphenateLite.framework ./bak

lipo HyphenateLite.framework/HyphenateLite -thin armv7 -output HyphenateLite_armv7

lipo HyphenateLite.framework/HyphenateLite -thin arm64 -output HyphenateLite_arm64

lipo -create HyphenateLite_armv7 HyphenateLite_arm64 -output HyphenateLite

mv HyphenateLite HyphenateLite.framework/

。。。。

 

EMiOSDemo說明:

Account:主要是demo 的註冊,登錄

AppDelegate:主要是demo 中初始化環信SDK,註冊推送等

Call:demo的實時語音視頻通話功能模塊(包含1v1 實時通話以及多人實時通話的功能) 

Chat:demo的聊天功能模塊

Contact:demo的好友列表功能模塊

Conversation:demo的會話列表功能模塊

EMDemoHelper:demo的單例類,主要是全局監聽接收消息,好友,羣組,聊天室等相關事件的回調,從而進行對應的處理

Group:demo的羣組功能模塊

Helper:demo的功能性文件,自定義庫和頁面,第三方庫,全局通用的配置模塊

Home:demo的根控制器頁面

Notification:demo的好友,羣組相關請求通知的頁面

Settings:demo的功能設置頁面

Chatroom:聊天室模塊

 

補充內容:

1、添加代理方法爲:

 [[EMClient sharedClient].callManager addDelegate:self delegateQueue:nil];

使用到的代理方法主要有:

- (void)callDidReceive:(EMCallSession *)aSession 

//用戶A撥打用戶B用戶B會收到這個回調、你希望在哪個頁面可以監聽被呼叫就把這個方法寫在裏面,記得遵守協議;

- (void)callDidConnect:(EMCallSession *)aSession //通話通道完成,可以在這裏創建音頻輸出設備和環境AVAudioSession

- (void)callDidAccept:(EMCallSession *)aSession //用戶B同意用戶A的通話請求後,用戶A會收到這個回調

- (void)callDidEnd:(EMCallSession )aSession reason:(EMCallEndReason)aReason error:(EMError )aError //用戶A或用戶B掛斷後對方會收到這個回調。或者通話出現錯誤、雙方都會收到該回調

2、創建一個語音或視頻通話:

/*

*  @param aType            通話類型

 * @param aRemoteName      被呼叫的用戶(不能與自己通話)

 * @param aExt             通話擴展信息,會傳給被呼叫方

 *  @param aCompletionBlock 完成的回調

*/

[[EMClient sharedClient].callManager startCall:aType remoteName:aRemoteName ext:aExt completion:^(EMCallSession *aCallSession, EMError *aError) {

            if (!aError) {//創建成功

            }else{

            }

        }];

同意別人的會話邀請:

/*

_callSession.callId會話ID

*/

 [[EMClient sharedClient].callManager answerIncomingCall:_callSession.callId];

結束通話:

/*

_callSession.callId會話ID

aReason     掛斷原因 (EMCallEndReason)

*/

[[EMClient sharedClient].callManager endCall:_callSession.callId reason:aReason];

3、對方掛斷語言,可能要發送相應的消息(對方拒接  掛斷等)在結束實時通話的回調中

- (void)callDidEnd:(EMCallSession *)aSession

reason:(EMCallEndReason)aReason

error:(EMError *)aError 

根據EMCallEndReason這個枚舉看通話結束的原因,去發送NSNotification通知

然後在聊天頁面EaseMessageViewController.m中去監聽這個通知,然後在通知方法中去插入消息,可參考以下代碼:

NSString *insertStr = @"對方已掛斷";

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:insertStr];

NSString *from = [[EMClient sharedClient] currentUsername];

//生成Message

EMMessage *message = [[EMMessage alloc] initWithConversationID:self.conversation.conversationId from:from to:self.conversation.conversationId body:body ext:nil];

message.chatType = EMChatTypeChat;// 設置爲單聊消息

message.status = EMMessageStatusSucceed;

message.direction = callEnder;

[self addMessageToDataSource:message progress:nil];

[self.conversation insertMessage:message error:nil];

4、二次封裝:

init方法重寫(實時通話的代理註冊EMChatManagerDelegate, EMCallManagerDelegate)

攝像頭捕捉畫面需要進行OutputAudioPort設置

如果要撥打語音通話可以修改撥打方法,添加通話類型參數

 

相關鏈接:

iOS接入環信單聊(+實時音視頻):https://www.jianshu.com/p/fb1c1262f129

iOS環信視頻語音 細節處理(掛斷電話邏輯處理):https://www.imgeek.org/article/825309145

iOS如何集成環信實現即時通訊:https://jingyan.baidu.com/article/b87fe19e543a55521835681e.html

iOS環信視頻通話的二次封裝:https://www.jianshu.com/p/bafc400632f3

iOS基於環信SDK實現即時通訊-語音、視頻聊天:https://blog.csdn.net/create_pro/article/details/64438747

IOS快速集成環信IM - 基於官方的Demo優化,5分鐘集成環信IM功能:https://www.imgeek.org/article/825307886

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章