初始化 SDK
第 1 步:引入相關頭文件 #import “EMSDK.h”。
第 2 步:在工程的 AppDelegate 中的以下方法中,調用 SDK 對應方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //AppKey:注冊的AppKey,詳細見下面注釋。 //apnsCertName:推送證書名(不需要加后綴),詳細見下面注釋。 EMOptions *options = [EMOptions optionsWithAppkey:@"douser#istore"]; options.apnsCertName = @"istore_dev"; [[EMClient sharedClient] initializeSDKWithOptions:options]; return YES; } // APP進入后台 - (void)applicationDidEnterBackground:(UIApplication *)application { [[EMClient sharedClient] applicationDidEnterBackground:application]; } // APP將要從后台返回 - (void)applicationWillEnterForeground:(UIApplication *)application { [[EMClient sharedClient] applicationWillEnterForeground:application]; }
調用的 SDK 接口參數解釋如下:
-
AppKey: 區別 APP 的標識,參考 開發者注冊及管理后台。
-
apnsCertName: iOS 中推送證書名稱,參考 制作與上傳推送證書。
環信為 IM 部分提供了 APNS 推送功能,如果您要使用,請跳轉到APNS離線推送。
注冊
注冊模式分兩種,開放注冊和授權注冊。
-
只有開放注冊時,才可以客戶端注冊。開放注冊是為了測試使用,正式環境中不推薦使用該方式注冊環信賬號。
-
授權注冊的流程應該是您服務器通過環信提供的 REST API 注冊,之后保存到您的服務器或返回給客戶端。
EMError *error = [[EMClient sharedClient] registerWithUsername:@"8001" password:@"111111"]; if (error==nil) { NSLog(@"注冊成功"); }
登錄
登錄:調用 SDK 的登錄接口進行的操作。
EMError *error = [[EMClient sharedClient] loginWithUsername:@"8001" password:@"111111"]; if (!error) { NSLog(@"登錄成功"); }
自動登錄
自動登錄:即首次登錄成功后,不需要再次調用登錄方法,在下次 APP 啟動時,SDK 會自動為您登錄。並且如果您自動登錄失敗,也可以讀取到之前的會話信息。
SDK 中自動登錄屬性默認是關閉的,需要您在登錄成功后設置,以便您在下次 APP 啟動時不需要再次調用環信登錄,並且能在沒有網的情況下得到會話列表。
EMError *error = [[EMClient sharedClient] loginWithUsername:@"8001" password:@"111111"]; if (!error) { [[EMClient sharedClient].options setIsAutoLogin:YES]; }
自動登錄在以下幾種情況下會被取消:
-
用戶調用了 SDK 的登出動作;
-
用戶在別的設備上更改了密碼,導致此設備上自動登錄失敗;
-
用戶的賬號被從服務器端刪除;
-
用戶從另一個設備登錄,把當前設備上登錄的用戶踢出。
所以,在您調用登錄方法前,應該先判斷是否設置了自動登錄,如果設置了,則不需要您再調用。
BOOL isAutoLogin = [EMClient sharedClient].options.isAutoLogin; if (!isAutoLogin) { EMError *error = [[EMClient sharedClient] loginWithUsername:@"8001" password:@"111111"]; }
SDK 中,如果發生自動登錄,會有以下回調:
/*!
* 自動登錄返回結果
*
* @param aError 錯誤信息
*/
- (void)didAutoLoginWithError:(EMError *)aError //添加回調監聽代理: [[EMClient sharedClient] addDelegate:self delegateQueue:nil];
重連
當掉線時,iOS SDK 會自動重連,只需要監聽重連相關的回調,無需進行任何操作。
/*!
* SDK連接服務器的狀態變化時會接收到該回調
*
* 有以下幾種情況,會引起該方法的調用:
* 1. 登錄成功后,手機無法上網時,會調用該回調
* 2. 登錄成功后,網絡狀態變化時,會調用該回調
*
* @param aConnectionState 當前狀態
*/
- (void)didConnectionStateChanged:(EMConnectionState)aConnectionState;
退出登錄
退出登錄分兩種類型:主動退出登錄和被動退出登錄。
-
主動退出登錄:調用 SDK 的退出接口;
-
被動退出登錄:1. 正在登錄的賬號在另一台設備上登錄;2. 正在登錄的賬號被從服務器端刪除。
logout:YES:是否解除 device token 的綁定,在被動退出時 SDK 內部處理,不需要調用退出方法。
EMError *error = [[EMClient sharedClient] logout:YES]; if (!error) { NSLog(@"退出成功"); }
被動退出登錄
使用回調方法監聽被動退出登錄。
/*! * 當前登錄賬號在其它設備登錄時會接收到該回調 */ - (void)didLoginFromOtherDevice; /*! * 當前登錄賬號已經被從服務器端刪除時會收到該回調 */ - (void)didRemovedFromServer;
消息
消息:IM 交互實體,在 SDK 中對應的類型是 EMMessage。EMMessage 由 EMMessageBody 組成。
構造消息
構造文字消息
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要發送的消息"]; NSString *from = [[EMClient sharedClient] currentUsername]; //生成Message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息
構造圖片消息
EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:data displayName:@"image.png"]; NSString *from = [[EMClient sharedClient] currentUsername]; //生成Message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息
構造位置消息
EMLocationMessageBody *body = [[EMLocationMessageBody alloc] initWithLatitude:39 longitude:116 address:@"地址"]; NSString *from = [[EMClient sharedClient] currentUsername]; // 生成message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息
構造語音消息
EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:@"audioPath" displayName:@"audio"]; body.duration = duration; NSString *from = [[EMClient sharedClient] currentUsername]; // 生成message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息
構造視頻消息
EMVideoMessageBody *body = [[EMVideoMessageBody alloc] initWithLocalPath:@"videoPath" displayName:@"video.mp4"]; NSString *from = [[EMClient sharedClient] currentUsername]; // 生成message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息
構造文件消息
EMFileMessageBody *body = [[EMFileMessageBody alloc] initWithLocalPath:@"filePath" displayName:@"file"]; NSString *from = [[EMClient sharedClient] currentUsername]; // 生成message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息
構造透傳消息
SDK 提供的一種特殊類型的消息,即 CMD,不會存 db,也不會走 APNS 推送,類似一種指令型的消息。比如您的服務器要通知客戶端做某些操作,您可以服務器和客戶端提前約定好某個字段,當客戶端收到約定好的字段時,執行某種特殊操作。
EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:action]; NSString *from = [[EMClient sharedClient] currentUsername]; // 生成message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.messageType = eMessageTypeChat; // 設置為單聊消息 //message.messageType = eConversationTypeGroupChat;// 設置為群聊消息 //message.messageType = eConversationTypeChatRoom;// 設置為聊天室消息
構造擴展消息
當 SDK 提供的消息類型不滿足需求時,開發者可以通過擴展自 SDK 提供的文本、語音、圖片、位置等消息類型,從而生成自己需要的消息類型。
這里是擴展自文本消息,如果這個自定義的消息需要用到語音或者圖片等,可以擴展自語音、圖片消息,亦或是位置消息。
// 以單聊消息舉例
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要發送的消息"]; NSString *from = [[EMClient sharedClient] currentUsername]; //生成Message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息 message.ext = @{@"key":@"value"}; // 擴展消息部分
插入消息
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要發送的消息"]; NSString *from = [[EMClient sharedClient] currentUsername]; //生成Message EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt]; message.chatType = EMChatTypeChat;// 設置為單聊消息 //message.chatType = EMChatTypeGroupChat;// 設置為群聊消息 //message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息 [[EMClient sharedClient].chatManager importMessages:@[message]];
更新消息屬性
/*!
* 更新消息到 DB
*
* @param aMessage 消息
*
* @result 是否成功
*/
- (BOOL)updateMessage:(EMMessage *)aMessage; //調用:[[EMClient sharedClient].chatManager updateMessage:aMessage];
會話
會話:操作聊天消息 EMMessage 的容器,在 SDK 中對應的類型是 EMConversation。
新建/獲取一個會話
根據 conversationId 創建一個 conversation。
[[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES]; //EMConversationTypeChat 單聊會話 //EMConversationTypeGroupChat 群聊會話 //EMConversationTypeChatRoom 聊天室會話
-
getConversation:創建與8001的會話
-
type:會話類型
-
createIfNotExist:不存在是否創建
刪除會話
刪除單個會話
[[EMClient sharedClient].chatManager deleteConversation:@"8001" deleteMessages:YES];
-
deleteConversation: 刪除與8001的會話
-
deleteMessages: 刪除會話中的消息
根據 conversationId 批量刪除會話
[[EMClient sharedClient].chatManager deleteConversations:@[@"8001",@"8002"] deleteMessages:YES];
-
deleteConversations: 要刪除的會話
-
deleteMessages: 刪除會話中的消息
獲取會話列表
SDK中提供了三種獲取會會話列表的方法。
獲取或創建
EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
-
getConversation: 獲取或創建與8001的會話
-
type:EMConversationTypeChat: 會話類型
獲取內存中所有會話
NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
獲取 DB 中的所有會話
NSArray *conversations = [[EMClient sharedClient].chatManager loadAllConversationsFromDB];
獲取會話未讀消息數
[EMConversation unreadMessagesCount];
消息檢索
可以通過關鍵字、消息類型、開始結束時間檢索某個會話中的消息。
/*!
* 從數據庫獲取指定類型的消息,取到的消息按時間排序,如果參考的時間戳為負數,則從最新消息向前取,如果 aLimit 是負數,則獲取所有符合條件的消息
*
* @param aType 消息類型
* @param aTimestamp 參考時間戳
* @param aLimit 獲取的條數
* @param aSender 消息發送方,如果為空則忽略
* @param aDirection 消息搜索方向
*
* @result 消息列表<EMMessage>
*/
- (NSArray *)loadMoreMessagesWithType:(EMMessageBodyType)aType before:(long long)aTimestamp limit:(int)aLimit from:(NSString*)aSender direction:(EMMessageSearchDirection)aDirection; /*! * 從數據庫獲取包含指定內容的消息,取到的消息按時間排序,如果參考的時間戳為負數,則從最新消息向前取,如果 aLimit 是負數,則獲取所有符合條件的消息 * * @param aKeywords 搜索關鍵字,如果為空則忽略 * @param aTimestamp 參考時間戳 * @param aLimit 獲取的條數 * @param aSender 消息發送方,如果為空則忽略 * @param aDirection 消息搜索方向 * * @result 消息列表<EMMessage> */ - (NSArray *)loadMoreMessagesContain:(NSString*)aKeywords before:(long long)aTimestamp limit:(int)aLimit from:(NSString*)aSender direction:(EMMessageSearchDirection)aDirection; /*! * 從數據庫獲取指定時間段內的消息,取到的消息按時間排序,為了防止占用太多內存,用戶應當制定加載消息的最大數 * * @param aStartTimestamp 毫秒級開始時間 * @param aEndTimestamp 結束時間 * @param aMaxCount 加載消息最大數 * * @result 消息列表<EMMessage> * */ - (NSArray *)loadMoreMessagesFrom:(long long)aStartTimestamp to:(long long)aEndTimestamp maxCount:(int)aMaxCount;
聊天
登錄成功之后才能進行聊天操作。發消息時,單聊和群聊調用的是統一接口,區別只是要設置下 message.chatType。
發送消息
/*!
@property
@brief 發送消息
@discussion
異步方法
*/
- (void)asyncSendMessage:(EMMessage *)aMessage progress:(void (^)(int progress))aProgress completion:(void (^)(EMMessage *message, EMError *error))aProgressCompletion; //調用:[[EMClient sharedClient].chatManager asyncSendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {}];
接收消息
注冊消息回調
//消息回調:EMChatManagerChatDelegate
//注冊消息回調 [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil]; //移除消息回調 [[EMClient sharedClient].chatManager removeDelegate:self];
在線普通消息會走以下回調:
/*!
@method
@brief 接收到一條及以上非cmd消息
*/
- (void)didReceiveMessages:(NSArray *)aMessages;
透傳(cmd)在線消息會走以下回調:
/*!
@method
@brief 接收到一條及以上cmd消息
*/
- (void)didReceiveCmdMessages:(NSArray *)aCmdMessages;
解析普通消息
// 收到消息的回調,帶有附件類型的消息可以用 SDK 提供的下載附件方法下載(后面會講到)
- (void)didReceiveMessages:(NSArray *)aMessages { for (EMMessage *message in aMessages) { EMMessageBody *msgBody = message.body; switch (msgBody.type) { case EMMessageBodyTypeText: { // 收到的文字消息 EMTextMessageBody *textBody = (EMTextMessageBody *)msgBody; NSString *txt = textBody.text; NSLog(@"收到的文字是 txt -- %@",txt); } break; case EMMessageBodyTypeImage: { // 得到一個圖片消息body EMImageMessageBody *body = ((EMImageMessageBody *)msgBody); NSLog(@"大圖remote路徑 -- %@" ,body.remotePath); NSLog(@"大圖local路徑 -- %@" ,body.localPath); // // 需要使用sdk提供的下載方法后才會存在 NSLog(@"大圖的secret -- %@" ,body.secretKey); NSLog(@"大圖的W -- %f ,大圖的H -- %f",body.size.width,body.size.height); NSLog(@"大圖的下載狀態 -- %lu",body.downloadStatus); // 縮略圖sdk會自動下載 NSLog(@"小圖remote路徑 -- %@" ,body.thumbnailRemotePath); NSLog(@"小圖local路徑 -- %@" ,body.thumbnailLocalPath); NSLog(@"小圖的secret -- %@" ,body.thumbnailSecretKey); NSLog(@"小圖的W -- %f ,大圖的H -- %f",body.thumbnailSize.width,body.thumbnailSize.height); NSLog(@"小圖的下載狀態 -- %lu",body.thumbnailDownloadStatus); } break; case EMMessageBodyTypeLocation: { EMLocationMessageBody *body = (EMLocationMessageBody *)msgBody; NSLog(@"緯度-- %f",body.latitude); NSLog(@"經度-- %f",body.longitude); NSLog(@"地址-- %@",body.address); } break; case EMMessageBodyTypeVoice: { // 音頻sdk會自動下載 EMVoiceMessageBody *body = (EMVoiceMessageBody *)msgBody; NSLog(@"音頻remote路徑 -- %@" ,body.remotePath); NSLog(@"音頻local路徑 -- %@" ,body.localPath); // 需要使用sdk提供的下載方法后才會存在(音頻會自動調用) NSLog(@"音頻的secret -- %@" ,body.secretKey); NSLog(@"音頻文件大小 -- %lld" ,body.fileLength); NSLog(@"音頻文件的下載狀態 -- %lu" ,body.downloadStatus); NSLog(@"音頻的時間長度 -- %lu" ,body.duration); } break; case EMMessageBodyTypeVideo: { EMVideoMessageBody *body = (EMVideoMessageBody *)msgBody; NSLog(@"視頻remote路徑 -- %@" ,body.remotePath); NSLog(@"視頻local路徑 -- %@" ,body.localPath); // 需要使用sdk提供的下載方法后才會存在 NSLog(@"視頻的secret -- %@" ,body.secretKey); NSLog(@"視頻文件大小 -- %lld" ,body.fileLength); NSLog(@"視頻文件的下載狀態 -- %lu" ,body.downloadStatus); NSLog(@"視頻的時間長度 -- %lu" ,body.duration); NSLog(@"視頻的W -- %f ,視頻的H -- %f", body.thumbnailSize.width, body.thumbnailSize.height); // 縮略圖sdk會自動下載 NSLog(@"縮略圖的remote路徑 -- %@" ,body.thumbnailRemotePath); NSLog(@"縮略圖的local路徑 -- %@" ,body.thumbnailLocalPath); NSLog(@"縮略圖的secret -- %@" ,body.thumbnailSecretKey); NSLog(@"縮略圖的下載狀態 -- %lu" ,body.thumbnailDownloadStatus); } break; case EMMessageBodyTypeFile: { EMFileMessageBody *body = (EMFileMessageBody *)msgBody; NSLog(@"文件remote路徑 -- %@" ,body.remotePath); NSLog(@"文件local路徑 -- %@" ,body.localPath); // 需要使用sdk提供的下載方法后才會存在 NSLog(@"文件的secret -- %@" ,body.secretKey); NSLog(@"文件文件大小 -- %lld" ,body.fileLength); NSLog(@"文件文件的下載狀態 -- %lu" ,body.downloadStatus); } break; default: break; } } }
解析透傳消息
- (void)didReceiveCmdMessages:(NSArray *)aCmdMessages{ for (EMMessage *message in aCmdMessages) { EMCmdMessageBody *body = (EMCmdMessageBody *)message.body; NSLog(@"收到的action是 -- %@",body.action); } }
解析消息擴展屬性
- (void)didReceiveCmdMessages:(NSArray *)aCmdMessages{ for (EMMessage *message in aCmdMessages) { // cmd消息中的擴展屬性 NSDictionary *ext = message.ext; NSLog(@"cmd消息中的擴展屬性是 -- %@",ext) } } // 收到消息回調 - (void)didReceiveMessages:(NSArray *)aMessages{ for (EMMessage *message in aMessages) { // 消息中的擴展屬性 NSDictionary *ext = message.ext; NSLog(@"消息中的擴展屬性是 -- %@",ext); } }
自動下載消息中的附件
SDK 接收到消息后,會默認下載:圖片消息的縮略圖,語音消息的語音,視頻消息的視頻第一幀。
請先判斷你要下載附件沒有下載成功之后,在調用以下下載方法,否則SDK下載方法會再次從服務器上獲取附件。
[[EMClient sharedClient].chatManager asyncDownloadMessageThumbnail:message progress:nil completion:^(EMMessage *message, EMError *error) { if (!error) { NSLog(@"下載成功,下載后的message是 -- %@",aMessage); } }];
下載消息中的原始附件
[[EMClient sharedClient].chatManager asyncDownloadMessageAttachments:message progress:nil completion:^(EMMessage *message, EMError *error) { if (!error) { NSLog(@"下載成功,下載后的message是 -- %@",aMessage); } }];
消息已送達回執
SDK提供了已送達回執,當對方收到您的消息后,您會收到以下回調。
/*!
@method
@brief 接收到一條及以上已送達回執
*/
- (void)didReceiveHasDeliveredAcks:(NSArray *)aMessages;
消息已讀回執
已讀回執需要開發者主動調用的。當用戶讀取消息后,由開發者主動調用方法。
發送已讀回執
// 發送已讀回執。在這里寫只是為了演示發送,在APP中具體在哪里發送需要開發者自己決定。
[[EMClient sharedClient].chatManager asyncSendReadAckForMessage:message];
接收已讀回執
/*! * 接收到一條及以上已讀回執 * * @param aMessages 消息列表<EMMessage> */ - (void)didReceiveHasReadAcks:(NSArray *)aMessages;
好友管理
注:環信不是好友也可以聊天,不推薦使用環信的好友機制。如果你有自己的服務器或好友關系,請自己維護好友關系。
獲取好友列表
獲取好友列表,環信提供了兩種方法。
從服務器獲取所有的好友
EMError *error = nil; NSArray *userlist = [[EMClient sharedClient].contactManager getContactsFromServerWithError:&error]; if (!error) { NSLog(@"獲取成功 -- %@",buddyList); }
從數據庫獲取所有的好友
NSArray *userlist = [[EMClient sharedClient].contactManager getContactsFromDB];
好友申請
發送加好友申請
環信 iOS SDK 提供了添加好友的方法。
注:如果您已經發過,並且對方沒有處理,您將不能再次發送。
EMError *error = [[EMClient sharedClient].contactManager addContact:@"6001" message:@"我想加您為好友"]; if (!error) { NSLog(@"添加成功"); }
監聽加好友請求
當您收到好友請求,如果您沒有處理,請自己保存數據,新協議下不會每次都發送。
//注冊好友回調
[[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil]; //移除好友回調 [[EMClient sharedClient].contactManager removeDelegate:self];
監聽回調
/*!
* 用戶A發送加用戶B為好友的申請,用戶B會收到這個回調
*
* @param aUsername 用戶名
* @param aMessage 附屬信息
*/
- (void)didReceiveFriendInvitationFromUsername:(NSString *)aUsername message:(NSString *)aMessage;
同意加好友申請
EMError *error = [[EMClient sharedClient].contactManager acceptInvitationForUsername:@"8001"]; if (!error) { NSLog(@"發送同意成功"); }
拒絕加好友申請
EMError *error = [[EMClient sharedClient].contactManager declineInvitationForUsername:@"8001"]; if (!error) { NSLog(@"發送拒絕成功"); }
好友申請處理結果回調
監聽回調
/*!
@method
@brief 用戶A發送加用戶B為好友的申請,用戶B同意后,用戶A會收到這個回調
*/
- (void)didReceiveAgreedFromUsername:(NSString *)aUsername; /*! @method @brief 用戶A發送加用戶B為好友的申請,用戶B拒絕后,用戶A會收到這個回調 */ - (void)didReceiveDeclinedFromUsername:(NSString *)aUsername;
刪除好友
// 刪除好友
EMError *error = [[EMClient sharedClient].contactManager deleteContact:@"6001"]; if (!error) { NSLog(@"刪除成功"); }
-
deleteContact: 要刪除的用戶
黑名單
獲取好友黑名單
環信的黑名單體系是獨立的,與好友無任何關系。也就是說,您可以將任何人加入黑名單,不論他是否與您是好友關系。同時,如果您將好友好友加入黑名單,則他仍然是您的好友,只不過同時也在黑名單中。
查詢黑名單列表,環信提供了兩種方法。
同步方法
EMError *error = nil; NSArray *blacklist = [[EMClient sharedClient].contactManager getBlackListFromServerWithError:&error]; if (!error) { NSLog(@"獲取成功 -- %@",blockedList); }
從數據庫獲取黑名單列表
NSArray *blockList = [[EMClient sharedClient].contactManager getBlackListFromDB];
加入黑名單
接口調用
// 將6001加入黑名單
EMError *error = [[EMClient sharedClient].contactManager addUserToBlackList:@"6001" relationshipBoth:YES]; if (!error) { NSLog(@"發送成功"); }
移出黑名單
接口調用
// 將6001移除黑名單 EMError *error = [[EMClient sharedClient].contactManager removeUserFromBlackList:@"6001"]; if (!error) { NSLog(@"發送成功"); }
群組管理
群組分為四種類型。
/*!
@enum
@brief 群組類型
@constant EMGroupStylePrivateOnlyOwnerInvite 私有群組,創建完成后,只允許 Owner 邀請用戶加入
@constant EMGroupStylePrivateMemberCanInvite 私有群組,創建完成后,只允許 Owner 和群成員邀請用戶加入
@constant EMGroupStylePublicJoinNeedApproval 公開群組,創建完成后,只允許 Owner 邀請用戶加入; 非群成員用戶需發送入群申請,Owner 同意后才能入組
@constant EMGroupStylePublicOpenJoin 公開群組,創建完成后,允許非群組成員加入,不需要管理員同意
@discussion
eGroupStyle+Private:私有群組,只允許群組成員邀請人進入
eGroupStyle+Public: 公有群組,允許非群組成員加入
*/
typedef NS_ENUM(NSInteger, EMGroupStyle){ EMGroupStylePrivateOnlyOwnerInvite = 0, EMGroupStylePrivateMemberCanInvite, EMGroupStylePublicJoinNeedApproval, EMGroupStylePublicOpenJoin, };
群組操作
創建群組
目前創建群組支持的配置屬性有:
-
群名稱
-
群描述
-
群人數(不支持修改,目前上限為2000人)
-
群類型(即上面提到的四種群組類型)
同步方法:
EMError *error = nil; EMGroupOptions *setting = [[EMGroupOptions alloc] init]; setting.maxUsersCount = 500; setting.style = EMGroupStylePublicOpenJoin;// 創建不同類型的群組,這里需要才傳入不同的類型 EMGroup *group = [[EMClient sharedClient].groupManager createGroupWithSubject:@"群組名稱" description:@"群組描述" invitees:@[@"6001",@"6002"] message:@"邀請您加入群組" setting:setting error:&error]; if(!error){ NSLog(@"創建成功 -- %@",group); }
獲取群詳情
/*!
@method
@brief 獲取群組信息
@param aGroupId 群組ID
@param aIncludeMembersList 是否獲取成員列表
@param pError 錯誤信息
@return 群組
@discussion
同步方法,會阻塞當前線程
*/
- (EMGroup *)fetchGroupInfo:(NSString *)aGroupId includeMembersList:(BOOL)aIncludeMembersList error:(EMError **)pError; //調用: //EMError *error = nil; //EMGroup *group = [[EMClient sharedClient].groupManager fetchGroupInfo:@"groupId" includeMembersList:YES error:&error];
加入群組
群組分4種類型,目前 SDK 不支持自主選擇是否進群。我們將針對每種類型講解加入群組要進行的操作。
-
EMGroupStylePrivateOnlyOwnerInvite: 該類型的群組只允許群主(Owner)添加人進群,其他人無法主動加入。
-
EMGroupStylePrivateMemberCanInvite: (推薦使用)該類型的群組允許所有群成員添加人進群,其他人無法主動加入。
-
EMGroupStylePublicJoinNeedApproval: (推薦使用)該類型的群組只允許群主(Owner)添加人進群;其他人想進入群組的話,需要先發送申請,群主同意申請之后才能進群;其他人無法主動加入。
-
EMGroupStylePublicOpenJoin: (不推薦使用)該類型的群組允許任何人主動加入群組。
添加人進群
注冊群組回調:
//EMChatManagerDelegate
//注冊群組回調 [[EMClient sharedClient].groupManager addDelegate:self delegateQueue:nil]; //移除群組回調 [[EMClient sharedClient].groupManager removeDelegate:self];
被添加的人會收到回調:
/*!
@method
@brief 用戶B設置了自動同意,用戶A邀請用戶B入群,SDK 內部進行同意操作之后,用戶B接收到該回調
*/
- (void)didJoinedGroup:(EMGroup *)aGroup inviter:(NSString *)aInviter message:(NSString *)aMessage;
加人接口如下:
EMError *error = nil; [[EMClient sharedClient].groupManager addOccupants:@[@"user1"] toGroup:@"groupId" welcomeMessage:@"message" error:&error];
發送進群申請
// 申請加入需要審核的公開群組
EMError *error = nil; [[EMClient sharedClient].groupManager applyJoinPublicGroup:@"groupId" message:@"" error:nil];
處理進群申請
只有 Owner 有權限處理進群申請。
1. 收到進群申請。
/*!
@method
@brief 用戶A向群組G發送入群申請,群組G的群主O會接收到該回調
*/
- (void)didReceiveJoinGroupApplication:(EMGroup *)aGroup applicant:(NSString *)aApplicant reason:(NSString *)aReason;
2. 同意進群申請。
/*!
@method
@brief 同意加入群組的申請
@param aGroupId 所申請的群組 ID
@param aGroupname 申請的群組名稱
@param aUsername 申請人的 username
@discussion
需要 Owner 權限
同步方法,會阻塞當前線程
*/
- (EMError *)acceptJoinApplication:(NSString *)aGroupId groupname:(NSString *)aGroupname applicant:(NSString *)aUsername; //調用: //EMError *error = [[EMClient sharedClient].groupManager acceptJoinApplication:@"groupId" groupname:@"subject" applicant:@"user1"];
3. 拒絕加群申請。
EMError *error = [[EMClient sharedClient].groupManager declineJoinApplication:@"groupId" groupname:@"subject" applicant:@"user1" reason:@"拒絕的原因"];
加入 eGroupStyle_PublicOpenJoin 類型的群組
EMError *error = nil; [[EMClient sharedClient].groupManager joinPublicGroup:@"1410329312753" error:&error];
退出群組
群主(Owner)不支持退群操作,只能解散群。
退出群組分為主動退群和被動退群。被動退群即為被 Owner 踢出群組。
主動退群
EMError *error = nil; [[EMClient sharedClient].groupManager leaveGroup:@"1410329312753" error:&error];
被動退群
會通過以下回調通知被踢者。
/*!
@method
@brief 接收到離開群組,群組被銷毀或者被從群中移除
*/
- (void)didReceiveLeavedGroup:(EMGroup *)aGroup reason:(EMGroupLeaveReason)aReason;
解散群組
解散群組需要 Owner 權限。
EMError *error = nil; [[EMClient sharedClient].groupManager destroyGroup:@"groupId" error:&error]; if (!error) { NSLog(@"解散成功"); }
修改群名稱
只有 Owner 有權限修改。
EMError *error = nil; // 修改群名稱 [[EMClient sharedClient].groupManager changeGroupSubject:@"要修改的名稱" forGroup:@"1410329312753" error:&error]; if (!error) { NSLog(@"修改成功"); }
修改群描述
不推薦使用 ,只有 Owner 有權限操作。
EMError *error = nil; // 修改群描述 EMGroup* group = [[EMClient sharedClient].groupManager changeDescription:@"修改的群描述" forGroup:@"1410329312753" error:&error]; if (!error) { NSLog(@"修改成功"); }
群成員管理
移除群成員
只有 Owner 權限才能調用。
/*!
@method
@brief 將群成員移出群組
@param aOccupants 要請出群組的人的用戶名列表
@param aGroupId 群組ID
@param pError 錯誤信息
@result 返回群組對象
@discussion
此操作需要 Owner 權限
同步方法,會阻塞當前線程
*/
- (EMGroup *)removeOccupants:(NSArray *)aOccupants fromGroup:(NSString *)aGroupId error:(EMError **)pError; //調用: //EMError *error = nil; //[[EMClient sharedClient].groupManager removeOccupants:@[@"user1"] fromGroup:@"1410329312753" error:&error];
加入群黑名單
只有 Owner 權限才能調用該接口,並且只有 Owner 權限的才能查看群黑名單。
可以將群成員和非群成員的人加入群黑名單。
/*!
@method
@brief 將某些人加入群組黑名單
@param aOccupants 要加入黑名單的用戶名列表
@param aGroupId 群組ID
@param pError 錯誤信息
@result 返回群組對象
@discussion
此操作需要 Owner 權限。被加入黑名單的人,不會再被允許進入群組。
同步方法,會阻塞當前線程
*/
- (EMGroup *)blockOccupants:(NSArray *)aOccupants fromGroup:(NSString *)aGroupId error:(EMError **)pError; //調用: //EMError *error = nil; //EMGroup *group = [[EMClient sharedClient].groupManager blockOccupants:@[@"user1"] fromGroup:@"1410329312753" error:&error];
移出群黑名單
只有 Owner 權限才能調用該接口,並且只有 Owner 權限的才能查看群黑名單。
從群黑名單移除出去,該用戶已經不在群組里了,需要重新加入群組。
/*!
@method
@brief 將某些人從群組黑名單中解除
@param aOccupants 要從黑名單中移除的用戶名列表
@param aGroupId 群組ID
@param pError 錯誤信息
@result 返回群組對象
@discussion
此操作需要 Owner 權限。從黑名單中移除后不再是群組成員,需要重新加入。
同步方法,會阻塞當前線程
*/
- (EMGroup *)unblockOccupants:(NSArray *)aOccupants forGroup:(NSString *)aGroupId error:(EMError **)pError; //調用: //EMError *error = nil; //EMGroup *group = [[EMClient sharedClient].groupManager unblockOccupants:@[@"user1"] forGroup:@"1410329312753" error:&error];
群消息
屏蔽/取消屏蔽群組推送
不允許 Owner 權限的調用。
/*!
@method
@brief 屏蔽/取消屏蔽群組推送
@param aGroupId 群組ID
@param aIgnore 是否屏蔽
@result 錯誤信息
@discussion
同步方法,會阻塞當前線程
*/
- (EMError *)ignoreGroupPush:(NSString *)aGroupId ignore:(BOOL)aIgnore; //調用: //EMError *error = [[EMClient sharedClient].groupManager ignoreGroupPush:@"1410329312753" ignore:YES];
管理群組的 APNS 離線推送
獲取與登錄者相關的群組
查看所有當前登錄賬號所在群組,包括創建的和加入的群組,提供了三種方法。
1.從服務器獲取與我相關的群組列表
EMError *error = nil; NSArray *myGroups = [[EMClient sharedClient].groupManager getMyGroupsFromServerWithError:&error]; if (!error) { NSLog(@"獲取成功 -- %@",myGroups); }
2. 獲取數據庫中所有的群組
NSArray *groupList = [[EMClient sharedClient].groupManager loadAllMyGroupsFromDB];
3. 取內存中的值
從內存中獲取所有群組。
NSArray *groupList = [[EMClient sharedClient].groupManager getAllGroups];
獲取公開群組
獲取指定范圍內的公開群。
EMError *error = nil; EMCursorResult *result = [[EMClient sharedClient].groupManager getPublicGroupsFromServerWithCursor:nil pageSize:50 error:&error]; if (!error) { NSLog(@"獲取成功 -- %@",result); }
