最近会话

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

最近会话 RecentContact ,也可称作会话列表或者最近联系人列表,它记录了与用户最近有过会话的联系人信息,包括联系人帐号、联系人类型、最近一条消息的时间、消息状态、消息内容、未读条数等信息。

RecentContact 接口说明:

返回值 RecentContact 接口 说明
MsgAttachment getAttachment() 如果最近一条消息是扩展消息类型,获取消息的附件内容
String getContactId() 获取最近联系人的 ID(好友帐号,群 ID 等)
String getContent() 获取最近一条消息的缩略内容
Map getExtension() 获取扩展字段
String getFromAccount() 获取与该联系人的最后一条消息的发送方的帐号
String getFromNick() 获取与该联系人的最后一条消息的发送方的昵称
MsgStatusEnum getMsgStatus() 获取最近一条消息状态
MsgTypeEnum getMsgType() 获取最近一条消息的消息类型
String getRecentMessageId() 最近一条消息的消息 ID, 即 IMMessage#getUuid()
SessionTypeEnum getSessionType() 获取会话类型
long getTag() 获取标签
long getTime() 获取最近一条消息的时间,单位为 ms
int getUnreadCount() 获取该联系人的未读消息条数
void setExtension(Map extension) 设置扩展字段,可用于做群@等扩展用途
void setMsgStatus(MsgStatusEnum msgStatus) 设置最近一条消息的状态
void setTag(long tag) 设置一个标签,用于做联系人置顶、最近会话列表排序等扩展用途。

某些场景下,开发者可能需要手动向最近会话列表中插入一条会话项(即插入一个最近联系人),例如:在创建完高级群时,需要在最近会话列表中显示该群的会话项。由创建高级群完成时并不会收到任何消息, SDK 并不会立即更新最近会话,此时要满足需求,可以在创建群成功的回调中,插入一条本地消息, 即调用 MsgService#saveMessageToLocal。

注意:最近会话是本地的,不会漫游。漫游与消息相关,与最近会话无关。

获取最近会话列表

异步版本:

/**
 * 查询最近联系人列表数据
 *
 * @return InvocationFuture
 */
public InvocationFuture<List<RecentContact>> queryRecentContacts();

同步版本:

/**
 * 查询最近联系人列表数据(同步版本)
 *
 * @return InvocationFuture
 */
public List<RecentContact> queryRecentContactsBlock();
 NIMClient.getService(MsgService.class).queryRecentContacts()
     .setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
       @Override
       public void onResult(int code, List<RecentContact> recents, Throwable e) {
            // recents参数即为最近联系人列表(最近会话列表)
       }
    });

监听最近会话变更

在收发消息的同时,SDK 会更新对应聊天对象的最近联系人资料。当有消息收发时,SDK 会发出最近联系人更新通知。

/**
 * 注册/注销最近联系人列表变化观察者
 * @param observer 观察者,参数为变化的最近联系人列表
 * @param register true为注册,false为注销
 */
public void observeRecentContact(Observer<List<RecentContact>> observer, boolean register);
//  创建观察者对象
Observer<List<RecentContact>> messageObserver =
    new Observer<List<RecentContact>>() {
        @Override
        public void onEvent(List<RecentContact> messages) {
        }
    }
//  注册/注销观察者
NIMClient.getService(MsgServiceObserve.class)
    .observeRecentContact(messageObserver, register);

获取会话未读数总数

1. 通过接口直接获取

/**
 * 获取未读数总数
 */
public int getTotalUnreadCount();
int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount();

2. 对最近联系人列表中的每个最近联系人的未读数进行求和:

int unreadNum = 0;
for (RecentContact r : items) {
    unreadNum += r.getUnreadCount();
}

说明:多端同时登录时,在其他端进行查看,客户端不会进行未读数清零操作。

设置当前会话

如果用户在开始聊天时,开发者调用了 setChattingAccount 接口,SDK会自动管理消息的未读数。当收到新消息时,自动将未读数清零。如果第三方 APP 需要不进入聊天窗口,就需要将未读数清零,可以通过调用 MsgService#clearUnreadCount 接口来实现。

/**
 * 将指定最近联系人的未读数清零(标记已读)。
 * 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)} 通知
 *
 * @param account     聊天对象帐号
 * @param sessionType 会话类型
 */
public void clearUnreadCount(String account, SessionTypeEnum sessionType);
参数 说明
account 聊天对象帐号
sessionType 会话类型
// 触发 MsgServiceObserve#observeRecentContact(Observer, boolean) 通知,
// 通知中的 RecentContact 对象的未读数为0
NIMClient.getService(MsgService.class).clearUnreadCount(account, sessionType);

如果需要在最近联系人列表界面显示当前消息状态,还需要增加消息状态监听,操作见消息收发 章节的子章节多媒体消息接收中的监听消息状态。

移除最近会话列表中的项

MsgService 提供了两种方法: deleteRecentContact 和 deleteRecentContact2,区别在于后者会触发 MsgServiceObserve#observeRecentContactDeleted 通知。

不触发观察者通知版本:

/**
 * 从最近联系人列表中删除一项。
 * 调用这个接口删除数据后,不会引发观察者通知。
 *
 * @param recent 待删除的最近联系人项
 */
public void deleteRecentContact(RecentContact recent);

触发观察者通知版本:

/**
 * 删除最近联系人记录。
 * 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContactDeleted(Observer, boolean)}通知
 *
 * @param account
 * @param sessionType
 */
public void deleteRecentContact2(String account, SessionTypeEnum sessionType);

不触发观察者通知版本:

NIMClient.getService(MsgService.class).deleteRecentContact(recent);

触发观察者通知版本:

// 以P2P类型为例
NIMClient.getService(MsgService.class).deleteRecentContact2(account, SessionTypeEnum.P2P);

删除指定最近联系人的漫游消息

不删除本地消息,但如果在其他端登录,当前时间点该会话已经产生的消息不漫游。

/**
 * 删除指定最近联系人的漫游消息。
 * 不删除本地消息,但如果在其他端登录,当前时间点该会话已经产生的消息不漫游。
 *
 * @return InvocationFuture 可设置回调函数,监听删除结果。
 */
public InvocationFuture<Void> deleteRoamingRecentContact(String contactId, SessionTypeEnum sessionTypeEnum);
参数 说明
contactId 最近联系人的 ID(好友帐号,群 ID 等)
sessionTypeEnum 会话类型
NIMClient.getService(MsgService.class)
    .deleteRoamingRecentContact(contactId, sessionTypeEnum)
    .setCallback(new RequestCallback<Void>() { ... });

最近会话自定义方案

最近会话自定义 在某些特殊场景下,用户有对最近会话有较强的定制需求,本质上,网易云通信SDK就是提供数据及数据的管理,如果上层业务有自定义的需要,那么要做组合使用(抽象+组合)。 网易云通信Android最近联系人列表如何自定义

导入最近会话列表

导入最近会话列表适用于从别处迁移数据到云信的场景,需要手动构建初始的最近会话列表时使用。

/**
 * 导入最近会话,批量导入,仅支持 contactId 和 sessionType 两个字段
 * 
 * @param sessions
 * @return
 */
public InvocationFuture<Void> importRecentSessions(List<Pair<String, SessionTypeEnum>> sessions);
参数 说明
sessions 最近会话列表
Pair contactId 和 sessionType 的 Pair 对象
List<Pair<String, SessionTypeEnum>> list = new ArrayList<>();
list.add(new Pair<>("lucy", SessionTypeEnum.P2P));
list.add(new Pair<>("lily", SessionTypeEnum.P2P));
NIMClient.getService(MsgService.class).importRecentSessions(list).setCallback(new RequestCallback<Void>() { ... });