消息透传服务器,消息 [IM开发文档]

消息

消息:IM 交互实体,在 SDK 中对应的类型是 EMMessage,EMMessage 可以由多个符合 协议的 body 组成,但是,推荐使用一个 body,多个 body 有 bug,正在优化。

以下的讲解以一个 body 为例:

构造消息

构造文字消息

EMChatText *txtChat = [[EMChatText alloc] initWithText:@"要发送的消息"];

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:txtChat];

// 生成message

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造图片消息

EMChatImage *imgChat = [[EMChatImage alloc] initWithUIImage:img displayName:@"displayName"];

EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithChatObject:imgChat];

// 生成message

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造位置消息

EMChatLocation *locChat = [[EMChatLocation alloc] initWithLatitude:35.1 longitude:35.1 address:@"地址"];

EMLocationMessageBody *body = [[EMLocationMessageBody alloc] initWithChatObject:locChat];

// 生成message

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造语音消息

EMChatVoice *voice = [[EMChatVoice alloc] initWithFile:recordPath displayName:@"audio"];

voice.duration = aDuration;

EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithChatObject:voice];

// 生成message

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造视频消息

EMChatVideo *videoChat = [[EMChatVideo alloc] initWithFile:localPath displayName:@"displayName"];

EMVideoMessageBody *body = [[EMVideoMessageBody alloc] initWithChatObject:videoChat];

// 生成message。 6001,环信id,消息接收方。

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造文件消息

EMChatFile *fileChat = [[EMChatFile alloc] initWithFile:localPath displayName:@"displayName"];

EMFileMessageBody *body = [[EMFileMessageBody alloc] initWithChatObject:fileChat];

// 生成message。 6001,环信id,消息接收方。

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造透传消息

SDK 提供的一种特殊类型的消息,即 CMD,不会存 db,也不会走 APNS 推送,类似一种指令型的消息,比如您的服务器要通知客户端做某些操作,您可以服务器和客户端提前约定好某个字段,当客户端收到约定好的字段时,执行某种特殊操作。

EMChatCommand *cmdChat = [[EMChatCommand alloc] init];

cmdChat.cmd = @"reason";

EMCommandMessageBody *body = [[EMCommandMessageBody alloc] initWithChatObject:cmdChat];

// 生成message。 6001,环信id,消息接收方。

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

构造扩展消息

有时候需要在消息中携带一些扩展内容,用来实现特殊需求,比如阅后即焚等。EMMessage 提供了 ext 属性,撰文用来存放扩展内容。ext 属性是 NSDictionary 类型,key 和 value 必须是基本类型,且不能是 JSON。

可以这样使用

EMChatText *txt = [[EMChatText alloc] initWithText:@"test1"];

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:txt];

// 6001,环信id,消息接收方。

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.ext = @{@"key":@"value"};

ext 是message的属性,所有消息类型的message都有该属性

插入消息

EMChatText *txt = [[EMChatText alloc] initWithText:@"test1"];

EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:txt];

// 6001,环信id,消息接收方。

EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]];

message.messageType = eMessageTypeChat; // 设置为单聊消息

//message.messageType = eConversationTypeGroupChat;// 设置为群聊消息

//message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息

message.deliveryState = eMessageDeliveryState_Delivered;

[[EaseMob sharedInstance].chatManager insertMessageToDB:message];

更新消息属性

/*!

@method

@brief 更新消息发送状态

@result 是否更新成功

*/

- (BOOL)updateMessageDeliveryStateToDB;

/*!

@method

@brief 更新消息扩展属性

@result 是否更新成功

*/

- (BOOL)updateMessageExtToDB;

/*!

@method

@brief 更新消息的消息体

@result 是否更新成功

*/

- (BOOL)updateMessageBodiesToDB;

/*!

@method

@brief 修改当前 message 的发送状态,下载状态为 failed(crash 时或者 terminate)

@return 是否更新成功

*/

- (BOOL)updateMessageStatusFailedToDB;

会话

会话:操作聊天消息 EMMessage 的容器,在 SDK 中对应的类型是 EMConversation。

新建/获取一个会话

根据 chatter 创建一个 conversation。

EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:@"8001" conversationType:eConversationTypeChat];conversationForChatter: 获取或创建与8001的会话

conversationType: 会话类型

删除会话

删除单个会话

[[EaseMob sharedInstance].chatManager removeConversationByChatter:@"8001" deleteMessages:YES append2Chat:YES];removeConversationByChatter: 删除与8001的会话

deleteMessages: 删除会话中的消息

append2Chat: 是否更新内存中内容

批量删除会话

根据 chatter 批量删除会话。

[[EaseMob sharedInstance].chatManager removeConversationsByChatters:chatters deleteMessages:YES append2Chat:YES];removeConversationsByChatters: 要删除的 chatters

deleteMessages: 删除会话中的消息

append2Chat: 是否更新内存中内容

删除所有会话

// deleteMessage,是否删除会话中的message,YES为删除

[[EaseMob sharedInstance].chatManager removeAllConversationsWithDeleteMessages:YES append2Chat:YES];

获取会话列表

SDK 中提供了三种获取会会话列表的方法。

获取或创建

EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:@"8001" conversationType:eConversationTypeChat];conversationForChatter: 获取或创建与8001的会话

isGroup: 会话类型

获取内存中所有会话

NSArray *conversations = [[EaseMob sharedInstance].chatManager conversations];

获取 DB 中的所有会话

NSArray *conversations = [[EaseMob sharedInstance].chatManager loadAllConversationsFromDatabaseWithAppend2Chat:YES];

获取会话未读消息数

[conversation unreadMessagesCount];

聊天

登录成功之后才能进行聊天操作。发消息时,单聊和群聊调用的是统一接口,区别只是要设置下 message.isGroup 属性。坚决不推荐多 body。

发送消息

/*!

@method

@brief 发送一条消息

@discussion 待发送的消息对象和发送后的消息对象是同一个对象,在发送过程中对象属性可能会被更改

@param message 消息对象(包括from、to、body列表等信息)

@param progress 发送多媒体信息时的progress回调对象

@param pError 错误信息

@result 发送完成后的消息对象

*/

- (EMMessage *)sendMessage:(EMMessage *)message

progress:(id)progress

error:(EMError **)pError;

/*!

@method

@brief 异步方法,发送一条消息

@discussion 待发送的消息对象和发送后的消息对象是同一个对象,在发送过程中对象属性可能会被更改。在发送过程中,willSendMessage:error:和didSendMessage:error:这两个回调会被触发

@param message 消息对象(包括from、to、body列表等信息)

@param progress 发送多媒体信息时的progress回调对象

@result 发送的消息对象(因为是异步方法,不能作为发送完成或发送成功失败与否的判断)

*/

- (EMMessage *)asyncSendMessage:(EMMessage *)message

progress:(id)progress;

/*!

@method

@brief 异步方法,发送一条消息

@discussion 待发送的消息对象和发送后的消息对象是同一个对象,在发送过程中对象属性可能会被更改

@param message 消息对象(包括from、to、body列表等信息)

@param progress 发送多媒体信息时的progress回调对象

@param prepare 将要发送消息前的回调block

@param aPrepareQueue 回调block时的线程

@param completion 发送消息完成后的回调

@param aCompletionQueue 回调block时的线程

@result 发送的消息对象(因为是异步方法,不能作为发送完成或发送成功失败与否的判断)

*/

- (EMMessage *)asyncSendMessage:(EMMessage *)message

progress:(id)progress

prepare:(void (^)(EMMessage *message, EMError *error))prepare

onQueue:(dispatch_queue_t)aPrepareQueue

completion:(void (^)(EMMessage *message, EMError *error))completion

onQueue:(dispatch_queue_t)aCompletionQueue;

接收离线消息

离线普通消息会走以下回调:

/*!

@method

@brief 将要接收离线消息的回调

@discussion

@result

*/

- (void)willReceiveOfflineMessages;

/*!

@method

@brief 接收到离线非透传消息的回调

@discussion

@param offlineMessages 接收到的离线列表

@result

*/

- (void)didReceiveOfflineMessages:(NSArray *)offlineMessages;

/*!

@method

@brief 离线非透传消息接收完成的回调

@discussion

@param offlineMessages 接收到的离线列表

@result

*/

- (void)didFinishedReceiveOfflineMessages;

离线透传消息会走以下回调:

/*!

@method

@brief 接收到离线透传消息的回调

@discussion

@param offlineCmdMessages 接收到的离线透传消息列表

@result

*/

- (void)didReceiveOfflineCmdMessages:(NSArray *)offlineCmdMessages;

/*!

@method

@brief 离线透传消息接收完成的回调

@discussion

@param offlineCmdMessages 接收到的离线透传消息列表

@result

*/

- (void)didFinishedReceiveOfflineCmdMessages;

接收在线消息

在线普通消息会走以下回调:

/*!

@method

@brief 收到消息时的回调

@param message 消息对象

@discussion 当EMConversation对象的enableReceiveMessage属性为YES时,会触发此回调

针对有附件的消息,此时附件还未被下载。

附件下载过程中的进度回调请参考didFetchingMessageAttachments:progress:,

下载完所有附件后,回调didMessageAttachmentsStatusChanged:error:会被触发

*/

- (void)didReceiveMessage:(EMMessage *)message;

透传(cmd)在线消息会走以下回调:

/*!

@method

@brief 收到消息时的回调

@param cmdMessage 消息对象

@discussion 当EMConversation对象的enableReceiveMessage属性为YES时,会触发此回调

*/

- (void)didReceiveCmdMessage:(EMMessage *)cmdMessage;

消息未读数变化

/*!

@method

@brief 未读消息数改变时的回调

@discussion 当EMConversation对象的enableUnreadMessagesCountEvent为YES时,会触发此回调

@result

*/

- (void)didUnreadMessagesCountChanged;

解析普通消息

// 收到消息的回调,带有附件类型的消息可以用 SDK 提供的下载附件方法下载(后面会讲到)

-(void)didReceiveMessage:(EMMessage *)message

{

id msgBody = message.messageBodies.firstObject;

switch (msgBody.messageBodyType) {

case eMessageBodyType_Text:

{

// 收到的文字消息

NSString *txt = ((EMTextMessageBody *)msgBody).text;

NSLog(@"收到的文字是 txt -- %@",txt);

}

break;

case eMessageBodyType_Image:

{

// 得到一个图片消息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.attachmentDownloadStatus);

// 缩略图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 eMessageBodyType_Location:

{

EMLocationMessageBody *body = (EMLocationMessageBody *)msgBody;

NSLog(@"纬度-- %f",body.latitude);

NSLog(@"经度-- %f",body.longitude);

NSLog(@"地址-- %@",body.address);

}

break;

case eMessageBodyType_Voice:

{

// 音频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.attachmentDownloadStatus);

NSLog(@"音频的时间长度 -- %lu" ,body.duration);

}

break;

case eMessageBodyType_Video:

{

EMVideoMessageBody *body = (EMVideoMessageBody *)msgBody;

NSLog(@"视频remote路径 -- %@" ,body.remotePath);

NSLog(@"视频local路径 -- %@" ,body.localPath); // 需要使用SDK提供的下载方法后才会存在

NSLog(@"视频的secret -- %@" ,body.secretKey);

NSLog(@"视频文件大小 -- %lld" ,body.fileLength);

NSLog(@"视频文件的下载状态 -- %lu" ,body.attachmentDownloadStatus);

NSLog(@"视频的时间长度 -- %lu" ,body.duration);

NSLog(@"视频的W -- %f ,视频的H -- %f", body.size.width, body.size.height);

// 缩略图sdk会自动下载

NSLog(@"缩略图的remote路径 -- %@" ,body.thumbnailRemotePath);

NSLog(@"缩略图的local路径 -- %@" ,body.thumbnailRemotePath);

NSLog(@"缩略图的secret -- %@" ,body.thumbnailSecretKey);

NSLog(@"缩略图的下载状态 -- %lu" ,body.thumbnailDownloadStatus);

}

break;

case eMessageBodyType_File:

{

EMFileMessageBody *body = (EMFileMessageBody *)msgBody;

NSLog(@"文件remote路径 -- %@" ,body.remotePath);

NSLog(@"文件local路径 -- %@" ,body.localPath); // 需要使用SDK提供的下载方法后才会存在

NSLog(@"文件的secret -- %@" ,body.secretKey);

NSLog(@"文件文件大小 -- %lld" ,body.fileLength);

NSLog(@"文件文件的下载状态 -- %lu" ,body.attachmentDownloadStatus);

}

break;

default:

break;

}

}

解析透传消息

-(void)didReceiveCmdMessage:(EMMessage *)cmdMessage{

EMCommandMessageBody *body = (EMCommandMessageBody *)cmdMessage.messageBodies.lastObject;

NSLog(@"收到的action是 -- %@",body.action);

}

解析消息扩展属性

-(void)didReceiveCmdMessage:(EMMessage *)cmdMessage{

// cmd消息中的扩展属性

NSDictionary *ext = cmdMessage.ext;

NSLog(@"cmd消息中的扩展属性是 -- %@",ext);

}

// 收到消息回调

-(void)didReceiveMessage:(EMMessage *)message{

// 消息中的扩展属性

NSDictionary *ext = message.ext;

NSLog(@"消息中的扩展属性是 -- %@",ext);

}

自动下载消息中的附件

SDK 接收到消息后,会默认下载:图片消息的缩略图,语音消息的语音,视频消息的视频第一帧。

请先判断你要下载附件没有下载成功之后,在调用以下下载方法,否则 SDK 下载方法会再次从服务器上获取附件。

SDK中提供了三种方法。

1. 同步方法

EMError *error = nil;

EMMessage *aMessage = [[EaseMob sharedInstance].chatManager fetchMessageThumbnail:message progress:nil error:&error];

if (!error) {

NSLog(@"缩略图下载成功,下载后的message -- %@",aMessage);

}

2. block 异步方法

[[EaseMob sharedInstance].chatManager asyncFetchMessageThumbnail:message progress:nil completion:^(EMMessage *aMessage, EMError *error) {

if (!error) {

NSLog(@"缩略图下载成功");

}

} onQueue:nil];

3. IChatManagerDelegate 异步方法

接口调用:

// 当收到消息时,SDK会自动调用下载缩略图。此处在这里调用只是为了演示用。

[[EaseMob sharedInstance].chatManager asyncFetchMessageThumbnail:message progress:nil];

回调监听:

// 当收到图片或视频时,SDK会自动下载缩略图,并回调该方法,如果下载失败,可以通过

// asyncFetchMessageThumbnail:progress 方法主动获取

-(void)didFetchMessageThumbnail:(EMMessage *)aMessage error:(EMError *)error{

if (!error) {

NSLog(@"下载缩略图成功,下载后的message是 -- %@",aMessage);

}

}

下载消息中的原始附件

SDK 中提供了三种方法。

1. 同步方法

EMError *error = nil;

EMMessage *aMessage = [[EaseMob sharedInstance].chatManager fetchMessage:message progress:nil error:&error];

if (!error) {

NSLog(@"下载成功,下载后的message是 -- %@",aMessage);

}

2. block 回调方法

[[EaseMob sharedInstance].chatManager asyncFetchMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *error) {

if (!error) {

NSLog(@"下载成功,下载后的message是 -- %@",aMessage);

}

} onQueue:nil];

3. IChatManagerDelegate 异步方法

接口调用:

// 当message中带有附件的时候执行下载(如图片、音频、视频、文件)

[[EaseMob sharedInstance].chatManager asyncFetchMessage:message progress:nil];

回调监听:

/*!

@method

@brief 收取消息体对象后的回调

@discussion 当获取完消息体对象后,此回调会被触发;如果此消息体所在的消息对象在服务器端已被加密,那么下载完成后会自动进行解压

@param aMessage 要获取的消息对象

@param error 错误信息

*/

- (void)didFetchMessage:(EMMessage *)aMessage error:(EMError *)error;

消息已送达回执

该回调缺省是关闭的,需要您调用打开方法(只需要在SDK初始化后调用一次即可)。

/*!

@property

@brief 开启消息送达通知(默认是不开启的)

@discussion

*/

[[EaseMob sharedInstance].chatManager enableDeliveryNotification];

SDK提供了已送达回执,当对方收到您的消息后,您会收到以下回调:

/*!

@method

@brief 收到"已送达回执"时的回调方法

@discussion 发送方收到接收方发送的一个收到消息的回执,但不意味着接收方已阅读了该消息

@param resp 收到的"已送达回执"对象,包括 from、to、chatId等

@result

*/

- (void)didReceiveHasDeliveredResponse:(EMReceipt *)resp;

消息已读回执

已读回执需要开发者主动调用的。当用户读取消息后,由开发者主动调用方法。

发送已读回执

// 发送已读回执。在这里写只是为了演示发送,在APP中具体在哪里发送需要开发者自己决定。

[[EaseMob sharedInstance].chatManager sendHasReadResponseForMessage:message];

接收已读回执

/*!

@method

@brief 收到"已读回执"时的回调方法

@discussion 发送方收到接收方发送的一个收到消息的回执,意味着接收方已阅读了该消息

@param resp 收到的"已读回执"对象,包括 from、to、chatId等

@result

*/

- (void)didReceiveHasReadResponse:(EMReceipt *)resp;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值