消息管理–获取消息的已读回执和送达回执
更新时间:2022-02-28
本文介绍环信即时通讯 IM iOS SDK 从服务器获取消息的已读回执和送达回执。
功能描述
环信即时通讯 IM 消息投递成功将返回送达回执。提供消息已读功能,接收方查看消息后,将返回已读回执。
功能 | 描述 |
---|---|
消息送达回执 | 消息下发成功后,会返回消息送达回执。 |
消息已读回执 | 接收方查看消息后,会返回消息已读回执。 |
单个消息已读回执 | 提供单聊消息已读回执能力。 |
群组消息已读回执 | 提供群组消息已读回执能力。 |
技术原理
使用环信即时通讯 IM iOS SDK 可以实现消息的送达回执与已读回执,主要方法如下:
enableRequireReadAck
开启送达回执;ackConversationRead
发出指定会话的已读回执;sendMessageReadAck
发出指定消息的已读回执;sendGroupMessageReadAck
发出群组消息的已读回执。
前提条件
实现方法
消息送达回执
若想要在消息送达时收到通知,你可以打开消息送达开关,这样在消息到达对方设备时你可以收到通知。
//设置是否需要接受方送达确认,默认 `YES`。
options.enableRequireReadAck = YES;
onMessageDelivered
回调是对方收到消息时的通知,你可以在收到该通知时,显示消息的送达状态。
- (void)messagesDidRead:(NSArray *)aMessages
{
for (EMChatMessage *message in aMessages) {
//做消息已读处理等。
}
}
//记得在不需要的时候移除 delegate,如在 viewController 的 dealloc 时。
[[EMClient sharedClient].chatManager removeDelegate:self];
消息已读回执
消息阅读后,可以发出已读回执,该回执需要你调用 API 实现,这样消息发送方可以知道消息已被阅读。
会话已读回执
会话已读回执用于需要获知接收方是否阅读消息的场景,目前仅适用于单聊(ChatType.Chat)
。
注意
群消息已读回执功能为增值服务,仅旗舰版及以上支持,具体使用参考 群消息已读回执。
发送已读回执消息
推荐进入会话页面,根据会话是否有未读消息,发送会话已读回执(conversation ack)
,有则发送,没有则不再发送。
[[EMClient sharedClient].chatManager ackConversationRead:conversationId completion:nil];
监听已读回执回调
- (void)onConversationRead:(NSString *)from to:(NSString *)to
{
//添加刷新页面通知等逻辑。
}
注意
onConversationRead
中的 from
和 to
与消息 EMChatMessage
中的定义相同。
会话已读回执 onConversationRead
的场景:
(1)消息被接收方阅读,且发送了已读回执 (conversation ack)
;
(2)多端多设备登录场景下,一端发送会话已读回执 (conversation ack)
,服务器端会将未读消息数置为 0,同时其他端会回调此方法。
单个消息的已读回执
注意
消息已读回执功能目前仅适用于单聊(ChatType.Chat)
,推荐使用方案为会话已读回执 (conversation ack)
+单条消息已读回执(read ack)
结合实现,可减少发送 read ack 消息量。群消息已读回执功能为增值服务,仅旗舰版及以上支持,具体使用请参考 群消息已读回执。
发送已读回执消息
建议进入会话首先发送会话已读回执(conversation ack)
。
[[EMClient sharedClient].chatManager sendMessageReadAck:messageId toUser:conversationId completion:nil];
在会话页面,接收到消息时可根据消息类型发送消息已读回执(read ack)
,如下所示:
//接收消息回调。
- (void)messagesDidReceive:(NSArray *)aMessages
{
for (EMChatMessage *message in aMessages) {
//发送消息已读回执。
[self sendReadAckForMessage:message];
}
}
/**
* 发送已读回执。
* @param message
*/
- (void)sendReadAckForMessage:(EMChatMessage *)aMessage
{
//这里是接收的消息,未发送过 read ack 消息且是单聊。
if (aMessage.direction == EMMessageDirectionSend || aMessage.isReadAcked || aMessage.chatType != EMChatTypeChat)
return;
EMMessageBody *body = aMessage.body;
//视频、语音及文件需要点击后再发送,可以根据需求进行调整。
if (body.type == EMMessageBodyTypeFile || body.type == EMMessageBodyTypeVoice || body.type == EMMessageBodyTypeImage)
return;
[[EMClient sharedClient].chatManager sendMessageReadAck:aMessage.messageId toUser:aMessage.conversationId completion:nil];
}
监听单个消息的已读回执
可以调用接口监听某个消息是否已读,示例代码如下:
//接收到已读回执。
- (void)messagesDidRead:(NSArray *)aMessages
{
for (EMChatMessage *message in aMessages) {
//添加刷新页面通知等逻辑。
}
}
群组消息已读回执
对于群消息,消息发送方(目前为管理员和群主)可设置是否需要已读回执。若需要,设置 EMChatMessage
的属性 isNeedGroupAck
为 YES
。
EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:to from:from to:to body:aBody ext:aExt];
message.isNeedGroupAck = YES;
发送群组消息的已读回执
- (void)sendGroupMessageReadAck:(EMChatMessage *)msg
{
if (msg.isNeedGroupAck && !msg.isReadAcked) {
[[EMClient sharedClient].chatManager sendGroupMessageReadAck:msg.messageId toGroup:msg.conversationId content:@"123" completion:^(EMError *error) {
if (error) {
}
}];
}
}
监听群组消息已读回调
群消息已读回调在回调代理 EMChatManagerDelegate
中。
//接收到群组消息的已读回执, 消息的接收方已经阅读此消息。
- (void)groupMessageDidRead:(EMChatMessage *)aMessage groupAcks:(NSArray *)aGroupAcks
{
for (GroupMessageAck *messageAck in aGroupAcks) {
//receive group message read ack
}
}
接收到群组消息已读回执后,发出消息的属性 groupAckCount
会有相应变化;
获取群组消息已读回执详情
如果想实现群消息已读回执的列表显示,可以通过下列接口获取到已读回执的详情。
/**
* 从服务器获取指定群已读回执。
*
* 异步方法
*
* @param aMessageId 要获取的消息 ID。
* @param aGroupId 要获取回执对应的群 ID。
* @param aGroupAckId 要获取的群回执 ID。
* @param aPageSize 获取消息条数。
* @param aCompletionBlock 获取消息结束的回调。
*/
[[EMClient sharedClient].chatManager asyncFetchGroupMessageAcksFromServer:messageId groupId:groupId startGroupAckId:nil pageSize:pageSize completion:^(EMCursorResult *aResult, EMError *error, int totalCount) {
//页面刷新等操作。
}];
推荐使用方案
推荐使用方案为会话已读回执(conversation ack)
+单条消息已读回执(read ack)结合实现,可减少发送已读回执数量。
(1)未启动聊天页面的情况下,有未读消息,点击进入聊天页面,调用会话已读回执 (conversation ack);
(2)已经启动聊天页面内的情况下,接收到消息,即发送单条消息已读回执 (read ack) ,具体实现可参考:发送 read ack 消息。