IM 即时通讯
Android
开发指南

频道未读数管理

更新时间: 2023/09/22 15:36:53

如果您的应用 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,具体方法参见本文的实现频道未读数持续监听实现频道未读数的直接获取

前提条件

开始集成前,请确保:

使用限制

频道未读数管理存在如下与未读数相关的限制:

  • 所有未读消息(包括@消息)的消息阈值默认为 99 条。
  • @消息的未读数的有效期,默认为 7 天,即默认存储 7 天。

若需要扩展上限,可在控制台配置圈组子功能项(未读的@消息数-周期所有未读消息(包括@)的消息计数-阈值),具体请参考开通和配置圈组功能

实现流程

实现频道未读数持续监听

本文通过以下 UI 简图的场景为例,说明如何完成频道 1 未读数的监听、未读数的清零以及清零后的持续监听。

步骤1: 监听未读数

您需要订阅 频道 1 的未读数才能实现监听。完成如下两个子步骤后,当有新的消息下发到频道 1 ,SDK 将触发未读数变化监听事件 QChatUnreadInfoChangedEvent 并上报。

订阅的频道仅在当前登录期间有效(因网络波动导致的断线自动重连除外)。如您调用logout方法登出后,需要重新订阅。

  1. 进入服务器 1 后,调用getChannelsByPage方法刷新频道列表,得到频道 1频道 2频道 3频道 4

  2. 调用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. 进入频道 1 后,记住您应用中“代表该频道的属性”(假设为currentChannel)。

  2. 调用markMessageRead方法,调用时传time参数为已读的最新消息的时间戳(Unix 时间戳),进行未读数的清零操作。

    未读数清零时,SDK 触发QChatUnreadInfoChanged事件,该事件包含的未读数参数unreadCount0

    • 针对同一个频道,调用 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) {
                            //标记已读异常
                        }
                    });
    
  3. 根据您的应用逻辑做出判断和处理:当currentChannelQChatUnreadInfoChanged事件里的channelId相同时,每当频道 1 有新消息接收时,仍旧会触发该事件。

实现频道未读数的直接获取

如果您不想订阅某个频道,而只想获取该频道当前的未读数,完成以下操作即可。

  1. 确保您已在当前频道中。

  2. 直接调用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时,会标记所有消息未读从而增加未读数。

此文档是否对你有帮助?
有帮助
去反馈
  • 未读信息定义
  • 前提条件
  • 使用限制
  • 实现流程
  • 实现频道未读数持续监听
  • 步骤1: 监听未读数
  • 步骤2:清除未读数
  • 实现频道未读数的直接获取
  • 常见问题
  • 1. 什么操作会导致频道未读数增加?
  • 2. 什么操作会导致频道未读数减少?
  • 3. 撤回消息和重发消息是否影响未读数?
  • 4. 通过markMessageRead方法标记频道消息已读,对未读数有什么影响?