集成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