環信3.0ios客戶端的集成(五)

版本記錄

版本號 時間
V1.0 2017.06.08

前言

很多app種都集成環信做第三方信息通訊工具,這里我們就看一下環信的主要功能和集成方法。先給出環信3.0的地址。
感興趣的可以參考:
1. 環信ios客戶端的集成(一)
2. 環信ios客戶端的集成(二)
3. 環信ios客戶端的集成(三)
4. 環信ios客戶端的集成(四)
這一篇主要說一下環信的消息

一、構造信息

消息分為文字,圖片,聲音等等很多種形式,消息的構造也分很多種,下面就對消息的構造進行說明。

1. 構造文字消息

看代碼

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;// 設置為聊天室消息

2. 構造圖片消息

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;// 設置為群聊消息

3. 構造位置消息

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;// 設置為聊天室消息

4. 構造語音消息

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;// 設置為聊天室消息

5. 構造視頻消息

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;// 設置為聊天室消息

6. 構造文件消息

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;// 設置為聊天室消息

7. 構造透傳消息

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.chatType = EMChatTypeChat;// 設置為單聊消息
//message.chatType = EMChatTypeGroupChat;// 設置為群聊消息
//message.chatType = EMChatTypeChatRoom;// 設置為聊天室消息

8. 構造擴展消息

當 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"}; // 擴展消息部分

9. 插入消息

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] completion:^(EMError *aError) {
    //code
}];

10. 更新消息屬性

/*!
 *  更新消息到 DB
 *
 *  @param aMessage  消息
 *
 *  @result 是否成功
 */
- (BOOL)updateMessage:(EMMessage *)aMessage;

//調用:[[EMClient sharedClient].chatManager updateMessage:aMessage];


二、會話

會話:操作聊天消息 EMMessage 的容器,在 SDK 中對應的類型是 EMConversation。

1. 新建/獲取一個會話

根據 conversationId 創建一個 conversation。

[[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
//EMConversationTypeChat            單聊會話
//EMConversationTypeGroupChat       群聊會話
//EMConversationTypeChatRoom        聊天室會話
  • getConversation:創建與8001的會話
  • type:會話類型
  • createIfNotExist:不存在是否創建

2. 刪除會話

刪除單個會話

[[EMClient sharedClient].chatManager deleteConversation:@"8001" isDeleteMessages:YES completion:^(NSString *aConversationId, EMError *aError){
    //code
}];
  • deleteConversation: 刪除與8001的會話
  • deleteMessages: 刪除會話中的消息

根據 conversationId 批量刪除會話

[[EMClient sharedClient].chatManager deleteConversations:@[@"8001",@"8002"] isDeleteMessages:YES completion:^(EMError *aError){
    //code
}];
  • deleteConversations: 要刪除的會話
  • deleteMessages: 刪除會話中的消息

3. 獲取會話列表

SDK中提供了三種獲取會話列表的方法。

獲取或創建

EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
  • getConversation: 獲取或創建與8001的會話
  • type:EMConversationTypeChat: 會話類型
    獲取所有會話(內存中有則從內存中取,沒有則從db中取)
NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];

4. 獲取會話未讀消息數

[EMConversation unreadMessagesCount];

5. 消息檢索

可以通過關鍵字、消息類型、開始結束時間檢索某個會話中的消息。

/*!
 *  從數據庫獲取指定數量的消息,取到的消息按時間排序,并且不包含參考的消息,如果參考消息的ID為空,則從最新消息取
 *
 *  @param aMessageId       參考消息的ID
 *  @param count            獲取的條數
 *  @param aDirection       消息搜索方向
 *  @param aCompletionBlock 完成的回調
 */
- (void)loadMessagesStartFromId:(NSString *)aMessageId
                          count:(int)aCount
                searchDirection:(EMMessageSearchDirection)aDirection
                     completion:(void (^)(NSArray *aMessages, EMError *aError))aCompletionBlock;

/*!
 *  從數據庫獲取指定類型的消息,取到的消息按時間排序,如果參考的時間戳為負數,則從最新消息取,如果aCount小于等于0當作1處理
 *
 *  @param aType            消息類型
 *  @param aTimestamp       參考時間戳
 *  @param aCount           獲取的條數
 *  @param aUsername        消息發送方,如果為空則忽略
 *  @param aDirection       消息搜索方向
 *  @param aCompletionBlock 完成的回調
 */
- (void)loadMessagesWithType:(EMMessageBodyType)aType
                   timestamp:(long long)aTimestamp
                       count:(int)aCount
                    fromUser:(NSString*)aUsername
             searchDirection:(EMMessageSearchDirection)aDirection
                  completion:(void (^)(NSArray *aMessages, EMError *aError))aCompletionBlock;

/*!
 *  從數據庫獲取包含指定內容的消息,取到的消息按時間排序,如果參考的時間戳為負數,則從最新消息向前取,如果aCount小于等于0當作1處理
 *
 *  @param aKeywords        搜索關鍵字,如果為空則忽略
 *  @param aTimestamp       參考時間戳
 *  @param aCount           獲取的條數
 *  @param aSender          消息發送方,如果為空則忽略
 *  @param aDirection       消息搜索方向
 *  @param aCompletionBlock 完成的回調
 */
- (void)loadMessagesWithKeyword:(NSString*)aKeyword
                      timestamp:(long long)aTimestamp
                          count:(int)aCount
                       fromUser:(NSString*)aSender
                searchDirection:(EMMessageSearchDirection)aDirection
                     completion:(void (^)(NSArray *aMessages, EMError *aError))aCompletionBlock;

/*!
 *  從數據庫獲取指定時間段內的消息,取到的消息按時間排序,為了防止占用太多內存,用戶應當制定加載消息的最大數
 *
 *  @param aStartTimestamp  毫秒級開始時間
 *  @param aEndTimestamp    結束時間
 *  @param aCount           加載消息最大數
 *  @param aCompletionBlock 完成的回調
 */
- (void)loadMessagesFrom:(long long)aStartTimestamp
                      to:(long long)aEndTimestamp
                   count:(int)aCount
              completion:(void (^)(NSArray *aMessages, EMError *aError))aCompletionBlock;


三、聊天

登錄成功之后才能進行聊天操作。發消息時,單聊和群聊調用的是統一接口,區別只是要設置下 message.chatType。

1. 發送消息

/*!
 @property
 @brief 發送消息
 @discussion
    異步方法
 */
- (void)sendMessage:(EMMessage *)aMessage
           progress:(void (^)(int progress))aProgressBlock
         completion:(void (^)(EMMessage *message, EMError *error))aCompletionBlock;

//調用:[[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {}]; 

2. 接收消息

注冊消息回調

//消息回調:EMChatManagerDelegate

//移除消息回調
[[EMClient sharedClient].chatManager removeDelegate:self];

//注冊消息回調
[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

在線普通消息會走以下回調:


/*!
 @method
 @brief 接收到一條及以上非cmd消息
 */
- (void)messagesDidReceive:(NSArray *)aMessages;

透傳(cmd)在線消息會走以下回調:


/*!
 @method
 @brief 接收到一條及以上cmd消息
 */
- (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages;

3. 解析普通消息

// 收到消息的回調,帶有附件類型的消息可以用 SDK 提供的下載附件方法下載(后面會講到)
- (void)messagesDidReceive:(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;
    }
    }
}

4. 解析透傳消息

- (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages 
{
    for (EMMessage *message in aCmdMessages) {
        EMCmdMessageBody *body = (EMCmdMessageBody *)message.body;
         NSLog(@"收到的action是 -- %@",body.action);
    }    
}

5. 解析消息擴展屬性

- (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages {
    for (EMMessage *message in aCmdMessages) {
        // cmd消息中的擴展屬性
        NSDictionary *ext = message.ext;
        NSLog(@"cmd消息中的擴展屬性是 -- %@",ext)
    }    
}
// 收到消息回調
- (void)messagesDidReceive:(NSArray *)aMessages {
    for (EMMessage *message in aMessages) {
        // 消息中的擴展屬性
        NSDictionary *ext = message.ext;
        NSLog(@"消息中的擴展屬性是 -- %@",ext);
    }
}

6. 自動下載消息中的附件

SDK 接收到消息后,會默認下載:圖片消息的縮略圖,語音消息的語音,視頻消息的視頻第一幀。請先判斷你要下載附件沒有下載成功之后,在調用以下下載方法,否則SDK下載方法會再次從服務器上獲取附件。

[[EMClient sharedClient].chatManager downloadMessageThumbnail:message progress:nil completion:^(EMMessage *message, EMError *error) {
    if (!error) {
        NSLog(@"下載成功,下載后的message是 -- %@",aMessage);
    }
}];

7. 下載消息中的原始附件

[EMClient sharedClient].chatManager downloadMessageAttachment:message progress:nil completion:^(EMMessage *message, EMError *error) {
    if (!error) {
        NSLog(@"下載成功,下載后的message是 -- %@",aMessage);
    }
}];

8. 消息已送達回執

SDK提供了已送達回執,當對方收到您的消息后,您會收到以下回調。

/*!
 @method
 @brief 接收到一條及以上已送達回執
 */
- (void)messagesDidDeliver:(NSArray *)aMessages;

9. 消息已讀回執

已讀回執需要開發者主動調用的。當用戶讀取消息后,由開發者主動調用方法。

發送已讀回執

// 發送已讀回執。在這里寫只是為了演示發送,在APP中具體在哪里發送需要開發者自己決定。
[[EMClient sharedClient].chatManager sendMessageReadAck:message completion:^(EMMessage *message, EMError *error) {
    if (!error) {
        NSLog(@"發送成功");
    }
}];

接收已讀回執


/*!
 *  接收到一條及以上已讀回執
 *
 *  @param aMessages  消息列表<EMMessage>
 */
- (void)messagesDidRead:(NSArray *)aMessages;

后記

很多同事都說環信的IM沒有Tencent的做的好,我感覺還可以,文檔相對來說接口好找,比較規范,未完,待續~~

風景照
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容