频道未读数管理
更新时间: 2024/03/14 16:36:32
如果您的应用 UI 上需要展示频道未读数,可参考本文介绍的流程获取频道内的消息未读信息并管理其变化。
游客接收到的消息无已读未读逻辑。不支持对游客展示消息未读数。
未读信息定义
NIM SDK 中的QChatUnreadInfo
类定义了圈组频道的未读信息,其内置方法如下:
单击展开查看 QChatUnreadInfo 的内置方法
内置方法 | 返回类型 | 说明 |
---|---|---|
getServerId |
long | 获取频道所属的服务器的 ID |
getTime |
long | 获取服务器当前时间 |
getChannelId |
long | 获取频道的 ID |
getUnreadCount |
int | 获取频道的消息未读数 |
getMentionedCount |
int | 获取频道的@消息的未读数 |
getAckTimeTag |
long | 获取已读时间戳(Unix 时间戳), 该时间戳对应的消息和早于该时间戳的消息都为已读消息 |
getMaxCount |
int | 获取最大消息未读数 |
getLastMsgTime |
long | (可选)获取最后一条消息的时间戳 (Unix 时间戳) |
您可通过多个方式获取QChatUnreadInfo
,具体方法参见本文的实现频道未读数持续监听和实现频道未读数的直接获取。
前提条件
开始集成前,请确保:
- 已注册
observeUnreadInfoChanged
新未读通知接收观察者,监听未读信息变更事件(QChatUnreadInfoChangedEvent
),该事件信息中包含未读信息QChatUnreadInfo
。 - 已在频道内发送消息。
使用限制
频道未读数管理存在如下与未读数相关的限制:
- 所有未读消息(包括@消息)的消息阈值默认为 99 条。
- @消息的未读数的有效期,默认为 7 天,即默认存储 7 天。
若需要扩展上限,可在控制台配置圈组子功能项(未读的@消息数-周期 和 所有未读消息(包括@)的消息计数-阈值),具体请参考开通和配置圈组功能。
实现流程
实现频道未读数持续监听
本文通过以下 UI 简图的场景为例,说明如何完成频道 1 未读数的监听、未读数的清零以及清零后的持续监听。
步骤1: 监听未读数
您需要订阅 频道 1 的未读数才能实现监听。完成如下两个子步骤后,当有新的消息下发到频道 1 ,SDK 将触发未读数变化监听事件 QChatUnreadInfoChangedEvent
并上报。
订阅的频道仅在当前登录期间有效(因网络波动导致的断线自动重连除外)。如您调用logout
方法登出后,需要重新订阅。
-
进入服务器 1 后,调用
getChannelsByPage
方法刷新频道列表,得到频道 1、频道 2、频道 3 和 频道 4。 -
调用
subscribeChannel
方法订阅频道 1。 调用该方法时入参配置如下:参数 说明 channelIdInfos
频道 ID:传入您需要订阅的频道 ID 与该频道所属的服务器的 ID 组成的未读信息列表。格式为 { channelId: string; serverId: string }[]
。operateType
操作类型: SUB
:订阅UN_SUB
:取消订阅
type
订阅类型,具体类型见 QChatSubscribeType
,本场景下需传入CHANNEL_MSG_UNREAD_COUNT
订阅频道的未读数。该两步的示例代码如下:
long serverId = 943445L; long searchTime = System.currentTimeMillis(); int limit = 100; NIMClient.getService(QChatChannelService.class) .getChannelsByPage(new QChatGetChannelsByPageParam(serverId,searchTime,limit)) .setCallback( new RequestCallback<QChatGetChannelsByPageResult>() { @Override public void onSuccess(QChatGetChannelsByPageResult result) { //查询Channel列表成功 List<QChatChannel> channels = result.getChannels(); if(channels != null && channels.size() > 0){ List<QChatChannelIdInfo> channelIdInfos = new ArrayList<>(); for (QChatChannel channel : channels) { channelIdInfos.add(new QChatChannelIdInfo(channel.getServerId(),channel.getChannelId())); } //订阅channel NIMClient.getService(QChatChannelService.class) .subscribeChannel(new QChatSubscribeChannelParam(QChatSubscribeType.CHANNEL_MSG, QChatSubscribeOperateType.SUB,channelIdInfos)) .setCallback(new RequestCallback<QChatSubscribeChannelResult>() { @Override public void onSuccess(QChatSubscribeChannelResult result) { //订阅成功,返回订阅Channel的未读信息 List<QChatUnreadInfo> unreadInfoList = result.getUnreadInfoList(); } @Override public void onFailed(int code) { //订阅失败,返回错误code } @Override public void onException(Throwable exception) { //订阅异常 } }); } } @Override public void onFailed(int code) { //查询Channel列表l失败,返回错误code } @Override public void onException(Throwable exception) { //查询Channel列表异常 } }); }
步骤2:清除未读数
以下说明以清除频道 1 的未读数为例,介绍在完成步骤1: 监听未读数后,如何清除频道未读数以及清除后对未读数进行持续监听。
-
进入频道 1 后,记住您应用中“代表该频道的属性”(假设为
currentChannel
)。 -
调用
markMessageRead
方法,调用时传time
参数为已读的最新消息的时间戳(Unix 时间戳),进行未读数的清零操作。未读数清零时,SDK 触发
QChatUnreadInfoChanged
事件,该事件包含的未读数参数unreadCount
为0
。- 针对同一个频道,调用
markMessageRead
方法存在频控限制,300 ms 内只能调用一次。 - 如果调用
markMessageRead
时传ackTimestamp
参数为0
,会将频道内所有消息标记为未读。
示例代码如下:
NIMClient.getService(QChatMessageService.class) .markMessageRead(new QChatMarkMessageReadParam(currentChannel.getServerId(),currentChannel.getChannelId(),System.currentTimeMillis())) .setCallback( new RequestCallback<Void>() { @Override public void onSuccess(Void param) { //标记已读成功 } @Override public void onFailed(int code) { //标记已读失败,返回错误code } @Override public void onException(Throwable exception) { //标记已读异常 } });
- 针对同一个频道,调用
-
根据您的应用逻辑做出判断和处理:当
currentChannel
与QChatUnreadInfoChanged
事件里的channelId
相同时,每当频道 1 有新消息接收时,仍旧会触发该事件。
实现频道未读数的直接获取
如果您不想订阅某个频道,而只想获取该频道当前的未读数,完成以下操作即可。
-
确保您已在当前频道中。
-
直接调用
getChannelUnreadInfos
查询当前频道未读信息。该方法单次最多查询频道数量为 100。
示例代码:
List<QChatChannelIdInfo> channelIdInfos = new ArrayList<>(); channelIdInfos.add(new QChatChannelIdInfo(currentChannel.getServerId(),currentChannel.getChannelId())); NIMClient.getService(QChatChannelService.class).getChannelUnreadInfos(new QChatGetChannelUnreadInfosParam(channelIdInfos)).setCallback( new RequestCallback<QChatGetChannelUnreadInfosResult>() { @Override public void onSuccess(QChatGetChannelUnreadInfosResult result) { //查询成功,返回订阅Channel的未读信息 List<QChatUnreadInfo> unreadInfoList = result.getUnreadInfoList(); } @Override public void onFailed(int code) { //查询失败,返回错误code } @Override public void onException(Throwable exception) { //查询异常 } });
常见问题
1. 什么操作会导致频道未读数增加?
您当前所在的频道中,有用户通过sendMessage
发送消息或通过updateMessage
更新消息,对应频道中的当前用户未读信息中的未读数会增加。以下特殊情情况除外:
- 消息发送者是自己
- 不存云端消息历史
- 不需要消息计数
- 未订阅当前频道
2. 什么操作会导致频道未读数减少?
您当前所在的频道中,有用户通过deleteMessage
删除消息,对应频道中的当前用户未读信息中的未读数会减少。以下特殊情况除外:
- 删除的是自己发的消息,则未读数不变。
- 未订阅当前频道。
3. 撤回消息和重发消息是否影响未读数?
这两种操作都不影响未读数。
4. 通过markMessageRead
方法标记频道消息已读,对未读数有什么影响?
如果在当前频道通过markMessageRead
标记消息已读,会更新对应频道的未读信息。
调用该方法时传入ackTimestamp
参数(标记消息已读的时间戳),不仅可能减少未读数,还可能增加未读数。例如将ackTimestamp
设为0
时,会标记所有消息未读从而增加未读数。