最近会话
更新时间: 2022/09/21 11:15:08
功能描述
最近会话 ,即最近联系人列表,它记录了与用户最近有过会话的联系人信息,包括联系人帐号、联系人类型、最近一条消息的时间、消息状态、消息内容、未读条数等信息。
最近会话列表由 SDK 维护并提供查询、监听变化的接口,只要与某个用户或者群组有产生聊天(自己发送消息或者收到消息), SDK 会自动更新最近会话列表并通知上层,开发者无需手动更新。
某些场景下,开发者可能需要手动向最近会话列表中插入一条会话项(即插入一个最近联系人),例如:在创建完高级群时,需要在最近会话列表中显示该群的会话项。由创建高级群完成时并不会收到任何消息, SDK 并不会立即更新最近会话,此时要满足需求,可以在创建群成功的回调中,插入一条本地消息,以实现插入会话的目的。
需要注意的是,最近会话是本地的,不会漫游。在新设备登录后,最近会话列表会根据当前的漫游消息、离线消息等自动生成。
主要方法
SDK 封装的会话类实体 RecentContact
。下表为 RecentContact
提供的主要方法。
方法名称 | 返回值 | 说明 |
---|---|---|
getAttachment() | MsgAttachment | 获取最近一条消息的附件内容 |
getContactId() | String | 获取最近联系人的 ID(好友帐号,群 ID 等) |
getContent() | String | 获取最近一条消息的缩略内容 |
getExtension() | Map | 获取最近会话对象的扩展字段 |
getFromAccount() | String | 获取最近一条消息的发送方的帐号 |
getFromNick() | String | 获取与该联系人的最近一条消息的发送方的昵称 |
getMsgStatus() | MsgStatusEnum | 获取最近一条消息状态 |
getMsgType() | MsgTypeEnum | 获取最近一条消息的消息类型 |
getRecentMessageId() | String | 获取最近一条消息的客户端ID, 即 IMMessage#getUuid() |
getSessionType() | SessionTypeEnum | 获取会话类型,是单聊还是群聊等 |
getTag() | long | 获取标签属性 |
getTime() | long | 获取最近一条消息的时间,单位为 ms |
getUnreadCount() | int | 获取未读消息条数 |
getUnreadCountBySessionType () | int | 获取指定会话类型的总未读数 |
setExtension(Map extension) | void | 设置最近会话对象的扩展字段 |
setMsgStatus(MsgStatusEnum msgStatus) | void | 设置最近一条消息的状态 |
setTag(long tag) | void | 设置一个标签,用于做联系人置顶、最近会话列表排序等扩展用途。 |
获取最近会话
获取最近会话列表,一般用于首页显示会话列表
获取最近会话列表
- 异步接口:
/**
* 查询最近联系人列表数据
*
* @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参数即为最近联系人列表(最近会话列表)
}
});
获取最近会话列表(自定义)
过滤指定消息类型
当希望返回的会话的最近一条消息不是某一类消息时,可以使用以下过滤接口。
如希望最近一条消息为非文本消息时,使用该接口的返回的会话,将取最近的一条非文本的消息作为最近一条消息。
- 异步接口:
/**
* 查询最近联系人列表数据
*
* @return InvocationFuture
*/
public InvocationFuture<List<RecentContact>> queryRecentContacts(MsgTypeEnum filterMsgType);
- 同步接口:
/**
* 查询最近联系人列表数据, 过滤指定消息类型(同步接口)
*
* @return InvocationFuture
*/
public List<RecentContact> queryRecentContactsBlock(MsgTypeEnum filterMsgType);
- 示例
NIMClient.getService(MsgService.class).queryRecentContacts(MsgTypeEnum.text)
.setCallback(new RequestCallbackWrapper<List<RecentContact>>() {
@Override
public void onResult(int code, List<RecentContact> recents, Throwable e) {
// recents参数即为最近联系人列表(最近会话列表)
}
});
获取少量会话
可以获取指定数量的最近会话:
- 异步接口
/**
* 查询最近联系人会话列表数据, 可以设置limit, 防止本地会话过多时,导致第一次加载慢
*
* @param limit 获取本地会话的数量,最大100,超过100修正到100
* @return InvocationFuture
*/
InvocationFuture<List<RecentContact>> queryRecentContacts(int limit);
- 同步接口
/**
* 查询最近联系人会话列表数据(同步接口),可以设置limit, 防止本地会话过多时,导致第一次加载慢
*
* @param limit 获取本地会话的数量,最大100,超过100修正到100
*/
List<RecentContact> queryRecentContactsBlock(int limit);
- 示例
NIMClient.getService(MsgService.class).queryRecentContacts(10);
分页获取最近会话列表
SDK提供可以根据锚点查询最新会话列表的接口,根据提供的方向 (direction),查询比 anchor(锚点会话) 更老 (QUERY_OLD) 或更新 (QUERY_NEW) 的最靠近 anchor 的 limit 条数据,结果使用 time 作为排序字段。 每次使用查询到的最近联系人会话列表中最后一个会话作为下一次查询的锚点即可实现分页查询。
- 异步接口
/**
* 查询最近联系人会话列表数据,可按时间逆序或者正序查询指定数量的最新会话列表数据
* @param anchor 查询最近联系人会话列表的锚点
* 如果首次查询传null即可;
* 如果首次查询,当查询方向direction为QUERY_NEW时,则时间按0开始查询;
* 如果首次查询,当查询方向direction为QUERY_OLD时,则时间按当前系统时间开始查询;
* 如果想查询下一页数据,传入上一页数据的最后一个RecentContact即可
* @param direction 查询方向
* QUERY_OLD查询在时间在anchor之前的数据,逆序排列;
* QUERY_NEW查询时间在anchor之后的数据,正序排列
* @param limit 获取本地会话的数量
* 最大100,超过100修正到100
* @return InvocationFuture
*/
InvocationFuture<List<RecentContact>> queryRecentContacts(RecentContact anchor,QueryDirectionEnum direction,int limit);
- 同步接口
/**
* 查询最近联系人会话列表数据(同步版本),可按时间逆序或者正序查询指定数量的最新会话列表数据
* @param anchor 查询最近联系人会话列表的锚点
* 如果首次查询传null即可;
* 如果首次查询,当查询方向direction为QUERY_NEW时,则时间按0开始查询;
* 如果首次查询,当查询方向direction为QUERY_OLD时,则时间按当前系统时间开始查询;
* 如果想查询下一页数据,传入上一页数据的最后一个RecentContact即可
* @param direction 查询方向
* QUERY_OLD查询在时间在queryTime之前的数据,逆序排列;
* QUERY_NEW查询时间在queryTime之后的数据,正序排列
* @param limit 获取本地会话的数量
* 最大100,超过100修正到100
* @return 最近联系人会话列表,列表不包含锚点
*/
List<RecentContact> queryRecentContactsBlock(RecentContact anchor,QueryDirectionEnum direction,int limit);
- 参数说明
参数 | 说明 |
---|---|
anchor | 查询最近联系人会话列表的锚点 |
direction | 查询方向 |
limit | 查询结果的条数限制,最大100,超过100修正到100 |
anchor参数表示查询锚点,也就是作为查询起点的那条会话,查询结果不包含锚点。null表示查询第一页,当查询方向direction为QUERY_NEW时,则时间按0开始查询;当查询方向direction为QUERY_OLD时,则时间按当前系统时间开始查询。
direction表示查询方向,QueryDirectionEnum.QUERY_OLD表示比锚点更旧的会话,查询的结果按照时间逆序排序;QueryDirectionEnum.QUERY_NEW表示比锚点更新的会话,查询的结果按照时间正序排序。
limit是查询结果的条数限制,最大100,如果传入值超过100,SDK内部会修正到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) {
// recents参数即为最近联系人列表(最近会话列表)
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) {
// recents参数即为最近联系人列表(最近会话列表)
recentContactList.addAll(recents);
}
});
获取指定的最近会话
v5.9.0版本开始,支持通过会话id获取对应的会话。
/**
* 查询最近联系人会话列表数据(同步接口),可以设置limit, 防止本地会话过多时,导致第一次加载慢
* @param contactId - 会话id ,对方帐号或群组id。
* @param sessionType - 会话类型。
*/
RecentContact queryRecentContact(java.lang.String contactId, SessionTypeEnum sessionType);
创建最近会话
- 创建一个空的最近会话:
/**
* 创建一条空的联系人会话
*
* @param contactId 会话id ,对方帐号或群组id。
* @param sessionType 会话类型
* @param tag 会话tag , eg:置顶标签(UIKit中的实现: RECENT_TAG_STICKY) ,用户参照自己的tag 实现即可, 如不需要,传 0 即可。<br/>
* @param time 会话时间 ,单位为ms。
* @param saveToDB 是否需要将会话保存在DB中,注意以下两点:<br/>
* 1,如果已经存在相同的会话(contactId 、sessionType 一样),则不会保存在db中; <br/>
* 2,如果之前不存在相同的会话,且needSaveToDB为true 会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)}通知;
* <b/>
* @return InvocationFuture<RecentContact>
*/
RecentContact createEmptyRecentContact(String contactId, SessionTypeEnum sessionType, long tag, long time,
boolean saveToDB);
- 支持配置是否从本地数据库搜索最后一条消息填入的接口
/**
* 创建一条空的联系人会话
*
* @param contactId 会话id ,对方帐号或群组id。
* @param sessionType 会话类型
* @param tag 会话tag , eg:置顶标签(UIKit中的实现: RECENT_TAG_STICKY) ,用户参照自己的tag 实现即可, 如不需要,传 0 即可。<br/>
* @param time 会话时间 ,单位为ms。
* @param saveToDB 是否需要将会话保存在DB中,注意以下两点:<br/>
* 1,如果已经存在相同的会话(contactId 、sessionType 一样),则不会保存在db中; <br/>
* 2,如果之前不存在相同的会话,且needSaveToDB为true 会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)}通知;
* <b/>
* @param withLastMsg 是否放入最后一条消息的相关信息
* @return InvocationFuture<RecentContact>
*/
RecentContact createEmptyRecentContact(String contactId, SessionTypeEnum sessionType, long tag, long time,
boolean saveToDB, boolean withLastMsg);
此外,当某条消息无对应的本地最近会话时,可以使用以下接口根据消息创建本地最近会话。
/**
* @param message - 消息。
* @param needNotify - 是否需要触发MsgServiceObserve.observeRecentContact(Observer, boolean)的通知
*/
void updateRecentByMessage(IMMessage message, boolean needNotify);
更新最近会话
更新最近会话
/**
* 更新一条最近联系人会话的属性。目前可设置的属性有:tag, extension。
* @param recent - 待更新的最近联系人会话数据
*/
void updateRecent(RecentContact recent);
如果想收到 MsgServiceObserve.observeRecentContact(Observer, boolean) 的通知, 可使用以下接口进行更新:
/**
* 更新一条最近联系人会话的属性。目前可设置的属性有:tag, extension。
* @param recent - 待更新的最近联系人会话数据
*/
void updateRecentAndNotify(RecentContact recent);
监听最近会话变更
当最近会话对象以及其属性发生变更时,SDK 会更新对应聊天对象的最近联系人资料,并发出最近联系人更新通知。
- API 原型
/**
* 注册/注销最近联系人列表变化观察者
* @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);
未读数
获取未读数
获取总未读数
/**
* 获取总未读数
*/
public int getTotalUnreadCount();
示例
int unreadNum = NIMClient.getService(MsgService.class).getTotalUnreadCount();
支持根据免打扰状态获取总未读数
/**
* 获取总未读数
* @param notify true表示只查询排除免打扰之外的消息总未读数,false表示只查询免打扰的消息总未读数
* @return 总未读数
*/
public int getTotalUnreadCount(boolean notify);
当用户选择 true 为入参时(即查询除免打扰外的消息总未读数),性能耗时会倍增。所以在本地会话过多的情况下,不建议用户使用 true 为参数调用该方法。
获取单个会话未读数
通过 RecentContact - getUnreadCount()
方法获取。
获取指定会话类型的总未读数
您可通过 getUnreadCountBySessionType () 方法获取指定会话类型的总未读数。
- 接口原型
/**
* 获取指定会话类型的总未读数
*/
int getUnreadCountBySessionType(SessionTypeEnum sessionType);
- 示例代码
int unreadNum = NIMClient.getService(MsgService.class).getUnreadCountBySessionType(sessionType);
获取指定会话未读消息列表
- 异步接口:
/**
* 根据会话ID和会话类型查找未读消息列表
* @param sessionId 会话ID
* @param sessionType 会话类型
* @return 未读消息列表
*/
InvocationFuture<List<IMMessage>> queryUnreadMessageList(String sessionId,SessionTypeEnum sessionType);
- 同步接口:
/**
* 根据会话ID和会话类型查找未读消息列表(同步版本)
* @param sessionId 会话ID
* @param sessionType 会话类型
* @return 未读消息列表
*/
List<IMMessage> queryUnreadMessageListBlock(String sessionId,SessionTypeEnum 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(String, SessionTypeEnum)
将正在聊天对象的未读数清零。如果有新消息到达,且消息来源是正在聊天的对象,其未读数也不会递增。
/**
* 设置当前会话
* @param account, - 聊天对象帐号,或者以下两个值:MSG_CHATTING_ACCOUNT_ALL与MSG_CHATTING_ACCOUNT_NONE。
* @param sessionType 会话类型。如果account不是具体的对象,该参数将被忽略
*/
void setChattingAccount(java.lang.String account, SessionTypeEnum sessionType);
一般在退出聊天界面时,需要恢复更新未读数:
// 恢复更新未读数
NIMClient.getService(MsgService.class).setChattingAccount(MsgService.MSG_CHATTING_ACCOUNT_NONE, SessionTypeEnum.None);
如果需要不进入聊天窗口就将未读数清零,可以调用如下接口来实现:
/**
* 将指定最近联系人的未读数清零(标记已读)。<br>
* 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)} 通知
*
* @param account 聊天对象帐号
* @param sessionType 会话类型
* @return 发送ack的结果
*/
InvocationFuture<Void> clearUnreadCount(String account, SessionTypeEnum sessionType);
/**
* 将指定最近联系人的未读数清零(标记已读)。<br>
* 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)} 通知
*
* @param sessionKeyList 聊天对象帐号列表,{@link Pair}的第一项为会话ID,第二项为会话类型
* 会话类型支持传入{@link SessionTypeEnum#P2P}和{@link SessionTypeEnum#Team}
* @return 发送ack的结果,列表中元素为失败的部分
*/
InvocationFuture<List<SessionAckInfo>> clearUnreadCount(List<Pair<String, SessionTypeEnum>> sessionKeyList);
/**
* 将指定会话类型的未读数清零(标记已读)。<br>
* 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)} 通知
*
* @param sessionType 会话类型,支持传入{@link SessionTypeEnum#P2P}和{@link SessionTypeEnum#Team}
*/
InvocationFuture<List<SessionAckInfo>> clearUnreadCount(SessionTypeEnum sessionType);
/**
* 将所有联系人的未读数清零(标记已读)
* 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContact(Observer, boolean)} 通知
*/
void clearAllUnreadCount();
未读数多端同步
开启会话的未读数多端同步后,在其中一个客户端读过的会话在其它端也会被标记为已读。
开启方法:设置 SDKOptions - sessionReadAck
属性为 true 。
删除最近会话
删除最近会话
SDK 支持删除指定的本地和云端最近会话。但会保留会话内的消息。调用时,总未读消息数会减去当前会话的未读数。
- API 介绍
MsgService 提供了三种方法: 其中deleteRecentContact(RecentContact) 和 deleteRecentContact2(String, SessionTypeEnum)的区别在于后者会触发 MsgServiceObserve#observeRecentContactDeleted 通知。另一个接口不会触发MsgServiceObserve#observeRecentContactDeleted,而且可以配置是否同时删除漫游消息
- API 原型
不触发观察者通知版本:
/**
* 从最近联系人列表中删除一项。
* 调用这个接口删除数据后,不会引发观察者通知。
*
* @param recent 待删除的最近联系人项
*/
public void deleteRecentContact(RecentContact recent);
触发观察者通知版本:
/**
* 删除最近联系人记录。
* 调用该接口后,会触发{@link MsgServiceObserve#observeRecentContactDeleted(Observer, boolean)}通知
*
* @param account
* @param sessionType
*/
public void deleteRecentContact2(String account, SessionTypeEnum sessionType);
可配置版本:
/**
* 删除最近联系人记录。<br>
*
* @param account 会话ID
* @param sessionType 会话类型,只能选{@link SessionTypeEnum#P2P}和{@link SessionTypeEnum#Team}会删漫游消息
* @param deleteType 删除类型,决定是否删除本地记录和漫游记录,
* 如果为null,视为{@link DeleteTypeEnum#REMAIN}
* @param sendAck 如果参数合法,是否向其他端标记此会话为已读
*/
InvocationFuture<Void> deleteRecentContact(String account, SessionTypeEnum sessionType, DeleteTypeEnum deleteType, boolean sendAck);
- 示例
// 不触发观察者通知版本
NIMClient.getService(MsgService.class).deleteRecentContact(recent);
//触发观察者通知版本
NIMClient.getService(MsgService.class).deleteRecentContact2(account, SessionTypeEnum.P2P);
// 可配置版本,配置既删本地会话,也删除漫游消息。而且要发送ACK
NIMClient.getService(MsgService.class).deleteRecentContact(sessionId, sessionType, DeleteTypeEnum.LOCAL_AND_REMOTE, true)
.setCallback(deleteRecentCallback);
删除漫游消息
SDK 支持删除指定联系人的漫游消息,可以通过以下方法实现:
- API 原型
/**
* 删除指定最近联系人的漫游消息。
* 不删除本地消息,但如果在其他端登录,当前时间点该会话已经产生的消息不漫游。
*
* @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>() { ... });