IM 即时通讯
Android
开发指南

最近会话

更新时间: 2024/01/03 10:36:23

最近会话,即本地会话,记录了与用户最近有过会话的联系人信息,包括联系人帐号、联系人类型、最近一条消息的时间、消息状态、消息内容、未读消息数等信息。

最近会话列表由 SDK 维护并提供查询、监听变化的接口,只要与某个用户或者群组发生聊天,SDK 会自动更新最近会话列表并通知,开发者无需手动更新。

特定场景下,开发者需要手动向最近会话列表中插入一条会话项(即插入一个最近联系人),例如:创建高级群后,SDK 不会更新最近会话,开发者可以在创建群回调中插入一条本地消息,实现在最近会话列表中显示该群的会话项。

最近会话为本地而非漫游。在新设备登录后,最近会话列表会根据当前的漫游消息、离线消息等自动生成。

技术原理

网易云信 NIM SDK 的 RecentContact 提供最近会话相关接口,帮助您快速实现和使用最近会话功能。

前提条件

已实现登录 IM

监听最近会话相关事件

在进行最近会话相关操作前,您可以提前注册监听相关事件。监听后,当最近会话对象或其属性发生变更时,SDK 会更新对应聊天对象的用户资料,并触发最近会话更新通知。

接口:

示例代码:

//  创建观察者对象
Observer<List<RecentContact>> recentContactChangeObserver = new Observer<List<RecentContact>>() {
     @Override
     public void onEvent(List<RecentContact> recentContactList) {
          //更新最近联系人列表
     }
};
// 注册最近联系人列表的观察者
NIMClient.getService(MsgServiceObserve.class).observeRecentContact(recentContactChangeObserver, true);

Observer<RecentContact> recentContactDeleteObserver = new Observer<RecentContact>() {
     @Override
     public voidonEvent(RecentContact recentContact) {
          //更新最近联系人列表
     }
};
NIMClient.getService(MsgServiceObserve.class).observeRecentContactDeleted(recentContactDeleteObserver, true);

创建最近会话

参数 说明
contactId 会话 ID,聊天对象账号或群组 ID。
sessionType 会话类型。
tag 会话 tag,即置顶标签,如不需要则传 0。
time 会话时间,单位毫秒。
saveToDB 是否需要将会话保存在数据库中:
  • 如果已经存在相同的会话(contactId 、sessionType 相同),则不保存在数据库中
  • 如果不存在相同的会话,且 needSaveToDBtrue,则会触发 observeRecentContact 通知。
  • withLastMsg 是否填入最后一条消息的相关信息
    • 示例代码:
    //创建一条与账号test的单聊会话
    RecentContact test = NIMClient.getService(MsgService.class)
         .createEmptyRecentContact("test", SessionTypeEnum.P2P, 0, System.currentTimeMillis(), true);
    ……
    
    //创建一条与账号test2的单聊会话,同时将数据库中test2的单聊会话的最后一条消息内容设置为test2的内容
    RecentContact test2 = NIMClient.getService(MsgService.class)
         .createEmptyRecentContact("test2", SessionTypeEnum.P2P, 0, System.currentTimeMillis(), true,true);
    String lastMessageContent = test2.getContent();
    

    获取最近会话

    获取最近会话列表,一般用于在首页显示。

    获取所有最近会话列表

    NIMClient.getService(MsgService.class).queryRecentContacts()
    	 .setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
    	   @Override
           public void onResult(int code, List<RecentContact> recents, Throwable e) {
                // recents参数即为最近联系人列表(最近会话列表)
           }
        });
    

    过滤指定消息类型的会话列表

    过滤指定消息类型的会话,例如过滤文本消息,则返回最近一条非文本消息的会话。

     NIMClient.getService(MsgService.class).queryRecentContacts(MsgTypeEnum.text)
    	 .setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
    	   @Override
           public void onResult(int code, List<RecentContact> recents, Throwable e) {
                // recents参数即为最近联系人列表(最近会话列表)
           }
        });
    

    获取指定数量的最近会话列表

    获取指定数量的最近会话,建议第一次获取会话时调用该接口。

    NIMClient.getService(MsgService.class).queryRecentContacts(10);
    

    分页获取最近会话列表

    根据锚点查询最近会话列表,可按时间逆序或者正序查询指定数量的最新会话列表数据。

    每次使用查询到的最近联系人会话列表中最后一个会话作为下一次查询的锚点即可实现分页查询。

    参数 说明
    anchor 查询的锚点。
  • 传入当页数据的最后一个 RecentContact 即可实现分页查询。
  • 首次查询传 null,当查询方向为 QUERY_NEW 时,则从 0 开始查询,当查询方向为 QUERY_OLD 时,则按当前系统时间开始查询。
  • direction 查询的方向。
  • QUERY_OLD:查询在时间在 queryTime 之前的数据,逆序排列
  • QUERY_NEW:查询时间在 queryTime 之后的数据,正序排列。
  • limit 查询的条数限制。最大为 100,超过 100 则默认为 100。
    • 示例代码:

    查询第一页的 100 条最近会话列表,逆序查询。

    NIMClient.getService(MsgService.class).queryRecentContacts(null,QueryDirectionEnum.QUERY_OLD,100)
    	 .setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
    	   @Override
           public void onResult(int code, List<RecentContact> recents, Throwable e) {
                // 传入最近会话列表
                recentContactList.addAll(recents);
           }
        });
    

    查询下一页的 100 条最近会话列表,逆序查询。

    NIMClient.getService(MsgService.class).queryRecentContacts(recentContactList.get(recentContactList.size()-1),QueryDirectionEnum.QUERY_OLD,100)
    	 .setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
    	   @Override
           public void onResult(int code, List<RecentContact> recents, Throwable e) {
                // 传入最近会话列表
                recentContactList.addAll(recents);
           }
        });
    

    获取指定 ID 和类型的最近会话

    自 v5.9.0 起,支持通过会话 ID 获取对应的会话。

    参数 说明
    contactId 会话 ID,聊天对象账号或群组 ID。
    sessionType 会话类型。
    • 示例代码:
    //查询单聊会话,会话ID为test的会话
    RecentContact recentContact = NIMClient.getService(MsgService.class).queryRecentContact("test", SessionTypeEnum.P2P);
    

    更新最近会话

    更新最近会话

    Map<String, Object> extension = recentContact.getExtension();
    
    if (extension == null) {
         extension = new HashMap<>();
    }
    
    Iterator<IMMessage> iterator = messages.iterator();
    while (iterator.hasNext()) {
         IMMessage msg = iterator.next();
         buildAitExtensionByMessage(extension, msg);
    }
    
    recentContact.setExtension(extension);
    //更新会话
    NIMClient.getService(MsgService.class).updateRecent(recentContact);
    

    更新最近会话并通知

    更新后会触发 observeRecentContact 通知。

    Map<String, Object> extension = recentContact.getExtension();
    
    if (extension == null) {
         extension = new HashMap<>();
    }
    
    Iterator<IMMessage> iterator = messages.iterator();
    while (iterator.hasNext()) {
         IMMessage msg = iterator.next();
         buildAitExtensionByMessage(extension, msg);
    }
    
    recentContact.setExtension(extension);
    //更新会话并触发会话更新observeRecentContact通知
    NIMClient.getService(MsgService.class).updateRecentAndNotify(recentContact);
    

    根据消息更新最近会话

    参数 说明
    message IMMessage 消息体
    needNotify boolean 类型,是否需要触发 observeRecentContact 的通知
    • 示例代码:
    NIMClient.getService(MsgService.class).updateRecentByMessage(currentMessage,true);
    

    消息未读数

    获取消息未读数

    获取总未读数

    int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount();
    

    根据免打扰状态获取总未读数

    本地会话过多的情况下不建议在主线程调用该接口,请使用 getTotalUnreadCount [1/2] 作为替代,否则可能引起数据库阻塞。

    参数 说明
    notify boolean 类型,true 表示只查询排除免打扰之外的消息总未读数,false 表示只查询免打扰的消息总未读数。
    • 示例代码:
    boolean notify = true;
    //只查询排除免打扰之外的消息总未读数
    int unreadCount = NIMClient.getService(MsgService.class).getTotalUnreadCount(notify);
    

    获取单个会话的消息未读数

    //查询单聊会话,会话ID为test的会话
    RecentContact recentContact = NIMClient.getService(MsgService.class).queryRecentContact("test", SessionTypeEnum.P2P);
    //查询该会话的未读数
    int unreadCount = recentContact.getUnreadCount();
    

    获取指定类型的会话的消息未读数

    int unreadNum = NIMClient.getService(MsgService.class).getUnreadCountBySessionType(sessionType);
    

    获取指定会话的未读消息列表

    参数 说明
    sessionId 会话 ID,聊天对象账号或群组 ID。
    sessionType 会话类型
    • 示例代码:
    NIMClient.getService(MsgService.class).queryUnreadMessageList(getSessionId(),getSessionType())
    	 .setCallback(new RequestCallbackWrapper<List<IMMessage>>() {
    	   @Override
           public void onResult(int code, List<IMMessage> result, Throwable exception) {
                // result参数即为未读消息列表
           }
        });
    

    重置未读数

    调用以下接口重置当前会话,SDK 会自动管理消息的未读数。调用该接口的同时会自动调用clearUnreadCount 将当前聊天对象的未读数清零。如果有新消息到达,且消息来源是正在聊天的对象,其未读数也不会递增。

    参数 说明
    account 聊天对象账号,如果当前没有聊天对象,则为 MSG_CHATTING_ACCOUNT_ALLMSG_CHATTING_ACCOUNT_NONE
    sessionType 会话类型。如果当前没有聊天对象,该忽略该参数。
    • 示例代码:

      一般在退出聊天界面时,需要重置未读数:

      // 重置未读数
      NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, SessionTypeEnum.None);
      

    未读数清零(标记已读)

    如果需要不进入聊天窗口就将未读数清零,可以调用如下接口来实现。

    将指定单个联系人的会话未读数清零(标记已读)

    调用该接口后,会触发 observeRecentContact 通知。

    参数 说明
    account 聊天对象账号,如果当前没有聊天对象,则为 MSG_CHATTING_ACCOUNT_ALLMSG_CHATTING_ACCOUNT_NONE
    sessionType 会话类型。如果当前没有聊天对象,该忽略该参数。
    • 示例代码:
    NIMClient.getService(MsgService.class).clearUnreadCount(currentRecentContact.getContactId(),
                currentRecentContact.getSessionType()).setCallback(new RequestCallback<Void>() {
                @Override
                public void onSuccess(Void param) {
                    String msg = "清除未读数成功";
                    ToastHelper.showToast(MainActivity.this, msg);
                }
    
                @Override
                public void onFailed(int code) {
                    String msg = "清除未读数失败,code=" + code;
                    ToastHelper.showToast(MainActivity.this, msg);
                }
    
                @Override
                public void onException(Throwable exception) {
                    String msg = "清除未读数错误,e=" + exception;
                    ToastHelper.showToast(MainActivity.this, msg);
                }
            });
    

    将指定联系人列表的会话未读数清零(标记已读)

    调用该接口后,会触发 observeRecentContact 通知。

    参数 说明
    sessionKeyList 聊天对象帐号列表。Pair 的第一项为会话 ID,第二项为会话类型。
    • 示例代码:
    List<Pair<String, SessionTypeEnum>> list = new ArrayList<>();
    for (RecentContact recent : recentLists) {
         list.add(new Pair<>(recent.getContactId(), recent.getSessionType()));
    }
    NIMClient.getService(MsgService.class).clearUnreadCount(list).setCallback(new RequestCallback<List<SessionAckInfo>>() {
         @Override
         public void onSuccess(List<SessionAckInfo> param) {
              String msg = "批量清除未读数成功, param=" + CollectionUtil.toString(param, ", ", info -> {
              return String.format("{sessionId: %s, sessionType: %s, time: %s}", info.getSessionId(), info.getSessionType(), info.getTime());
              });
              ToastHelper.showToast(MainActivity.this, msg);
         }
    
         @Override
         public void onFailed(int code) {
              String msg = "批量清除未读数失败,code=" + code;
              ToastHelper.showToast(MainActivity.this, msg);
         }
    
         @Override
         public void onException(Throwable exception) {
              String msg = "批量清除未读数错误,e=" + exception;
              ToastHelper.showToast(MainActivity.this, msg);
         }
    });
    

    将指定类型的会话的未读数清零(标记已读)

    调用该接口后,会触发 observeRecentContact 通知。

    参数 说明
    sessionType 会话类型
    • 示例代码:
     SessionTypeEnum sessionType = getSessionType();
    NIMClient.getService(MsgService.class).clearUnreadCount(sessionType).setCallback(new RequestCallback<List<SessionAckInfo>>() {
         @Override
         public void onSuccess(List<SessionAckInfo> param) {
              String msg = "批量清除未读数成功, param=" + CollectionUtil.toString(param, ", ", info -> {
              return String.format("{sessionId: %s, sessionType: %s, time: %s}", info.getSessionId(), info.getSessionType(), info.getTime());
              });
              ToastHelper.showToast(MainActivity.this, msg);
         }
    
         @Override
         public void onFailed(int code) {
              String msg = "批量清除未读数失败,code=" + code;
              ToastHelper.showToast(MainActivity.this, msg);
         }
    
         @Override
         public void onException(Throwable exception) {
              String msg = "批量清除未读数错误,e=" + exception;
              ToastHelper.showToast(MainActivity.this, msg);
         }
    });
    

    未读数多端同步

    初始化时设置 SDKOptions#sessionReadAcktrue 开启会话的未读数多端同步后,在其中一个客户端已读的会话在其它端也会被标记为已读。

    删除最近会话

    支持删除指定的本地和云端最近会话,但会保留会话内的消息。调用以下方法后,总未读消息数会减去当前会话的未读数。

    删除指定会话

    从最近会话列表中删除一项,包括本地和漫游。调用该接口删除数据后,不会触发 observeRecentContactDeleted 通知。

    参数 说明
    recent 待删除的 RecentContact 对象
    • 示例代码:
    // 不触发观察者通知版本
    NIMClient.getService(MsgService.class).deleteRecentContact(recent);
    

    删除指定联系人的会话

    删除指定联系人的会话。调用该接口删除数据后,不会触发 observeRecentContactDeleted 通知。

    参数 说明
    account 聊天对象账号。
    sessionType 会话类型。只能设置为 P2PTeam
    deleteType 会话类型。删除类型,包括本地记录和云端漫游,默认为不删除。
    sendAck boolean 类型,是否向本账号的其他端清除未读数。
    • 示例代码:
    NIMClient.getService(MsgService.class).deleteRecentContact(sessionId, sessionType, DeleteTypeEnum.LOCAL_AND_REMOTE, true)
                        .setCallback(deleteRecentCallback);
    

    删除指定联系人的会话并通知

    删除指定联系人的会话,包括本地和漫游。调用该接口删除数据后,SDK 会触发 observeRecentContactDeleted 通知。

    参数 说明
    account 聊天对象账号。
    sessionType 会话类型。只能设置为 P2PTeam
    • 示例代码:
    NIMClient.getService(MsgService.class).deleteRecentContact2(account, SessionTypeEnum.P2P);
    

    删除漫游消息

    删除指定最近联系人的漫游消息,不删除本地消息。可通过 InvocationFuture 设置回调函数,监听删除结果。

    参数 说明
    contactId 最近联系人 ID,即聊天对象帐号或群 ID
    sessionTypeEnum 会话类型
    • 示例代码:
    NIMClient.getService(MsgService.class)
    	     .deleteRoamingRecentContact(contactId, sessionTypeEnum)
    	     .setCallback(new RequestCallback<Void>() { ... });
    
    此文档是否对你有帮助?
    有帮助
    去反馈
    • 技术原理
    • 前提条件
    • 监听最近会话相关事件
    • 创建最近会话
    • 获取最近会话
    • 获取所有最近会话列表
    • 过滤指定消息类型的会话列表
    • 获取指定数量的最近会话列表
    • 分页获取最近会话列表
    • 获取指定 ID 和类型的最近会话
    • 更新最近会话
    • 更新最近会话
    • 更新最近会话并通知
    • 根据消息更新最近会话
    • 消息未读数
    • 获取消息未读数
    • 获取总未读数
    • 根据免打扰状态获取总未读数
    • 获取单个会话的消息未读数
    • 获取指定类型的会话的消息未读数
    • 获取指定会话的未读消息列表
    • 重置未读数
    • 未读数清零(标记已读)
    • 将指定单个联系人的会话未读数清零(标记已读)
    • 将指定联系人列表的会话未读数清零(标记已读)
    • 将指定类型的会话的未读数清零(标记已读)
    • 未读数多端同步
    • 删除最近会话
    • 删除指定会话
    • 删除指定联系人的会话
    • 删除指定联系人的会话并通知
    • 删除漫游消息