历史记录

本地记录

查询消息历史

SDK 提供了一个根据锚点查询本地消息历史记录的接口,根据提供的方向 (direct),查询比 anchor 更老 (QUERY_OLD) 或更新 (QUERY_NEW) 的最靠近anchor 的 limit 条数据。调用者可使用 asc 参数指定结果排序规则,结果使用 time 作为排序字段。

当进行首次查询时,锚点可以用使用 MessageBuilder#createEmptyMessage 接口生成。查询结果不包含锚点。

/**
 * 根据锚点和方向从本地消息数据库中查询消息历史。
 * 根据提供的方向(direct),查询比anchor更老(QUERY_OLD)或更新(QUERY_NEW)的最靠近anchorlimit条数据。
 * 调用者可使用asc参数指定结果排序规则,结果使用time作为排序字段。
 * 注意:查询结果不包含锚点。
 *
 * @return 调用跟踪,可设置回调函数,接收查询结果
 */
public InvocationFuture<List<IMMessage>> queryMessageListEx(IMMessage anchor, QueryDirectionEnum direction, int limit, boolean asc);
参数 说明
anchor 查询锚点
direction 查询方向
limit 查询结果的条数限制
asc 查询结果的排序规则,如果为 true,结果按照时间升序排列,如果为 false,按照时间降序排列

QueryDirectionEnum 属性说明:

QueryDirectionEnum 属性 说明
QUERY_NEW 查询比锚点时间更晚的消息
QUERY_OLD 查询比锚点时间更早的消息
// 查询比 anchor时间更早的消息,查询20条,结果按照时间降序排列
NIMClient.getService(MsgService.class).queryMessageListEx(anchor, QueryDirectionEnum.QUERY_OLD,
    20, false).setCallback(new RequestCallbackWrapper<List<IMMessage>>() {
@Override
public void onResult(int code, List<IMMessage> result, Throwable exception) {
   ...
}
});

包含起止时间的消息历史查询

该接口使用方法与 queryMessageListEx 类似,增加了一个参数 toTime 作为查询方向上的的截止时间,当方向为 QUERY_OLD 时,toTime 应小于 anchor.getTime();当方向为 QUERY_NEW 时,toTime 应大于 anchor.getTime()。

查询结果的范围由 toTime 和 limit 共同决定,以先到为准。如果从 anchor 到 toTime 之间消息大于 limit 条,返回 limit 条记录,如果小于 limit 条,返回实际条数。

/**
 * 根据起始、截止时间点以及查询方向从本地消息数据库中查询消息历史。
 * 根据提供的方向 (direction),以 anchor 为起始点,往前或往后查询由 anchortoTime 之间靠近 anchorlimit 条消息。
 * 查询范围由 toTime 和 limit 共同决定,以先到为准。如果到 toTime 之间消息大于 limit 条,返回 limit 条记录,如果小于 limit 条,返回实际条数。
 * 查询结果排序规则:direction 为 QUERY_OLD 时 按时间降序排列,direction 为 QUERY_NEW 时按照时间升序排列。
 * 注意:查询结果不包含锚点。
 *
 * @return 调用跟踪,可设置回调函数,接收查询结果
 */
public InvocationFuture<List<IMMessage>> queryMessageListExTime(IMMessage anchor, long toTime, QueryDirectionEnum direction, int limit);
参数 说明
anchor 查询锚点
toTime 查询截止时间,若方向为 QUERY_OLD,toTime 应小于 anchor.getTime()。
方向为 QUERY_NEW,toTime 应大于 anchor.getTime()
direction 查询方向
limit 查询结果的条数限制
// 以P2P类型为例,testAccount为测试帐号
IMMessage msg = MessageBuilder.createEmptyMessage("testAccount", SessionTypeEnum.P2P, System.currentTimeMillis());

// 查询anchor往前10s的数据,10条
NIMClient.getService(MsgService.class).queryMessageListExTime(msg, System.currentTimeMillis() - 10000, QueryDirectionEnum.QUERY_OLD, 10).setCallback(...);

根据消息 uuid 查询消息

异步版本:

/**
 * 通过uuid批量获取IMMessage
 *
 * @param uuids 消息的uuid列表
 * @return
 */
public InvocationFuture<List<IMMessage>> queryMessageListByUuid(List<String> uuids);

同步版本:

/**
 * 通过uuid批量获取IMMessage(同步版本)
 *
 * @param uuids 消息的uuid列表
 * @return
 */
public List<IMMessage> queryMessageListByUuidBlock(List<String> uuids);
// 通过uuid批量获取IMMessage(异步版本)
List<String> uuids = new ArrayList<>();
uuids.add(message.getUuid());
NIMClient.getService(MsgService.class).queryMessageListByUuid(uuids);

// 通过uuid批量获取IMMessage(同步版本)
NIMClient.getService(MsgService.class).queryMessageListByUuidBlock(uuids);

根据消息类型查询消息历史

通过消息类型从本地消息数据库中查询消息历史。查询范围由 msgTypeEnum 参数和 anchor 的 sessionId 决定。该接口查询方向为从后往前。以锚点 anchor 作为起始点(不包含锚点),往前查询最多 limit 条消息。

/**
 * 通过消息类型从本地消息数据库中查询消息历史。查询范围由msgTypeEnum参数和anchor的sessionId决定
 * 该接口查询方向为从后往前。以锚点anchor作为起始点(不包含锚点),往前查询最多limit条消息。
 *
 */
public InvocationFuture<List<IMMessage>> queryMessageListByType(MsgTypeEnum msgTypeEnum, IMMessage anchor, int limit);
参数 说明
msgTypeEnum 消息类型
anchor 搜索的消息锚点
limit 搜索结果的条数限制
NIMClient.getService(MsgService.class).queryMessageListByType(msgTypeEnum, anchor, limit);

插入本地消息

保存消息到本地数据库,但不发送到服务器端。有两种接口可供调用。

1. 不可设置保存时间

/**
 * 保存消息到本地数据库,但不发送到服务器端。用于第三方APP保存本地提醒一类的消息。
 * 该接口将消息保存到数据库后,如果需要通知到UI,可将notify设置为true,此时会触发{@link MsgServiceObserve#observeReceiveMessage(Observer, boolean)}通知。
 *
 * @param msg    待保存的消息对象
 * @param notify 是否要通知UI更新界面
 * @return InvocationFuture 可以设置回调函数。在消息存入数据库后,就会回调。
 */
public InvocationFuture<Void> saveMessageToLocal(IMMessage msg, boolean notify);
参数 说明
msg 待保存的消息对象
notify 是否要通知UI更新界面
// 向群里插入一条Tip消息,使得该群能立即出现在最近联系人列表(会话列表)中,满足部分开发者需求。
Map<String, Object> content = new HashMap<>(1);
content.put("content", "成功创建高级群");
// 创建tip消息,teamId需要开发者已经存在的team的teamId
IMMessage msg = MessageBuilder.createTipMessage(teamId, SessionTypeEnum.Team);
msg.setRemoteExtension(content);
// 自定义消息配置选项
CustomMessageConfig config = new CustomMessageConfig();
// 消息不计入未读
config.enableUnreadCount = false;
msg.setConfig(config);
// 消息发送状态设置为success
msg.setStatus(MsgStatusEnum.success);
// 保存消息到本地数据库,但不发送到服务器
NIMClient.getService(MsgService.class).saveMessageToLocal(msg, true);

2. 可设置保存时间

/**
 * 保存消息到本地数据库,但不发送到服务器端。可设置保存消息的时间
 * 用于第三方APP保存本地提醒一类的消息。
 * 该接口将消息保存到数据库后,如果需要通知到UI,可将notify设置为true,此时会触发{@link MsgServiceObserve#observeReceiveMessage(Observer, boolean)}通知。
 *
 * @param msg       待保存的消息对象
 * @param notify    是否要通知UI更新界面
 * @param time      保存消息的时间, 使用{@link IMMessage#getTime()}
 * @return InvocationFuture 可以设置回调函数。在消息存入数据库后,就会回调。
 */
public InvocationFuture<Void> saveMessageToLocalEx(IMMessage msg, boolean notify, long time);
参数 说明
msg 待保存的消息对象
notify 是否要通知UI更新界面
time 保存消息的时间, 使用 IMMessage#getTime()
// 创建一条tip消息,并保存到本地数据库,时间设置为当前时间10秒之前
IMMessage message = MessageBuilder.createTipMessage("testAccount", SessionTypeEnum.P2P);
message.setContent("保存一条本地消息");
message.setStatus(MsgStatusEnum.success);
long time = System.currentTimeMillis() - 10000;
NIMClient.getService(MsgService.class).saveMessageToLocalEx(message, true, time);

云端记录

1. 获取云端记录详细接口

网易云通信还提供云端消息记录的功能,根据应用选择的套餐类型,保存不同时间长度范围的云端消息记录。SDK 提供了查询云端消息历史的接口,查询以锚点 anchor 作为起始点(不包含锚点),根据 direction 参数,往前或往后查询由锚点到 toTime 之间的最多 limit 条消息。查询范围由 toTime 和 limit 共同决定,以先到为准。如果到 toTime 之间消息大于 limit 条,返回 limit 条记录,如果小于 limit 条,返回实际条数。当已经查询到头时,返回的结果列表的 size 可能会比 limit 小。当进行首次查询时,锚点可以用使用 MessageBuilder#createEmptyMessage 接口生成。查询结果不包含锚点。该接口的最后一个参数可用于控制是否要将拉取到的消息记录保存到本地,如果选择保存到了本地,在使用拉取本地消息记录的接口时,也能取到这些数据。

 /**
 * 从服务器拉取消息历史记录。以锚点anchor作为起始点(不包含锚点),根据direction参数,往前或往后查询由锚点到toTime之间的最多limit条消息。
 * 查询范围由toTime和limit共同决定,以先到为准。如果到toTime之间消息大于limit条,返回limit条记录,如果小于limit条,返回实际条数。
 * 当已经查询到头时,返回的结果列表的size可能会比limit小
 *
 * @param anchor    起始时间点的消息,不能为null。
 *                  设置自定义锚点时,使用 {@link MessageBuilder#createEmptyMessage(String, SessionTypeEnum, long)} 创建一个空对象即可
 * @return InvocationFuture
 */
public InvocationFuture<List<IMMessage>> pullMessageHistoryEx(IMMessage anchor, long toTime, int limit, QueryDirectionEnum direction, boolean persist);
参数 说明
anchor 起始时间点的消息,不能为 null。
设置自定义锚点时,使用 MessageBuilder#createEmptyMessage 创建一个空对象即可
toTime 结束时间点单位毫秒
limit 本次查询的消息条数上限(最多 100 条)
direction 查询方向,QUERY_OLD 按结束时间点逆序查询,逆序排列;
QUERY_NEW 按起始时间点正序起查,正序排列
persist 通过该接口获取的漫游消息记录,要不要保存到本地消息数据库。
// 服务端拉取历史消息100条
long newTime = System.currentTimeMillis();
long oldTime = newTime - 1000 * 60 * 60; // 一小时前
IMMessage anchor = MessageBuilder.createEmptyMessage("testAccount", SessionTypeEnum.P2P, newTime);
NIMClient.getService(MsgService.class).pullMessageHistoryEx(anchor, oldTime, 100, QueryDirectionEnum.QUERY_OLD, false);

2. 获取云端记录简单接口

上面是一个全接口,参数比较复杂。如果只需要类似于在聊天窗口下拉刷新的效果,可以使用下面这个简单版本。


/**
 * 从服务器拉取消息历史记录。该接口查询方向为从后往前。以锚点anchor作为起始点(不包含锚点),往前查询最多limit条消息。
 * 当已经查询到头时,返回的结果列表的size可能会比limit小
 *
 * @param anchor  查询锚点。
 *                首次查询,使用 {@link MessageBuilder#createEmptyMessage(String, SessionTypeEnum, long)} 创建一个空对象即可
 * @param limit   本次查询的消息条数上限(最多100条)
 * @param persist 通过该接口获取的漫游消息记录,要不要保存到本地消息数据库。
 * @return InvocationFuture
 */
public InvocationFuture<List<IMMessage>> pullMessageHistory(IMMessage anchor, int limit, boolean persist);
参数 说明
anchor 查询锚点。
首次查询,使用 MessageBuilder#createEmptyMessage 创建一个空对象即可
limit 本次查询的消息条数上限(最多 100 条)
persist 通过该接口获取的漫游消息记录,要不要保存到本地消息数据库。
// 以测试帐号 testAccount,查询100条消息
IMMessage anchor = MessageBuilder.createEmptyMessage("testAccount", SessionTypeEnum.P2P, System.currentTimeMillis());

NIMClient.getService(MsgService.class).pullMessageHistory(anchor, 100, false);

3. 从服务器拉取历史消息,可以指定查询的消息类型

/**
 * 从服务器拉取消息历史记录,可以指定查询的消息类型,结果不存本地消息数据库。
 *
 * 以锚点anchor作为起始点(不包含锚点),根据direction参数,往前或往后查询由锚点到toTime之间的最多limit条消息。<br>
 * 查询范围由toTime和limit共同决定,以先到为准。如果到toTime之间消息大于limit条,返回limit条记录,如果小于limit条,返回实际条数。
 * 当已经查询到头时,返回的结果列表的size可能会比limit小
 *
 * @param anchor    起始时间点的消息,不能为null。<br>
 *                  设置自定义锚点时,使用 {@link MessageBuilder#createEmptyMessage(String, SessionTypeEnum, long)} 创建一个空对象即可<br>
 * @param toTime    结束时间点单位毫秒
 * @param limit     本次查询的消息条数上限(最多100条)
 * @param direction 查询方向,QUERY_OLD按结束时间点逆序查询,逆序排列;QUERY_NEW按起始时间点正序起查,正序排列
 * @param msgTypes  消息类型,数组。消息类型仅支持 0:文本,1:图片,2:语音,3:视频,4:地理位置,5:通知,6:文件,10:提示,11:Robot,100:自定义,其它为非法参数
 *
 * @return InvocationFuture
 */
public InvocationFuture<List<IMMessage>> pullMessageHistoryExType(IMMessage anchor, long toTime, int limit, QueryDirectionEnum direction, MsgTypeEnum[] msgTypes);

本地消息搜索

根据关键字搜索消息历史

SDK 提供了按照关键字搜索聊天记录的功能,可以对指定的聊天对象,输入关键字进行消息内容搜索。查询方向为从后往前。以锚点 anchor 作为起始点开始查询,返回最多 limit 条匹配 keyword 的记录。该接口目前仅搜索文本类型的消息,匹配规则为文本内容包含 keyword,目前仅支持精确匹配,不支持模糊匹配和拼音匹配。

由于 SDK 并不存储用户数据,因此 keyword 不会匹配用户资料。如果调用者希望查询指定用户的说话记录,可提供 fromAccounts 参数。如果提供的 fromAccounts 参数不为空,那么 anchor 对应的会话 (由 sessionId 和 sessionType 决定) 的消息记录中,凡是消息说话者在 fromAccounts 列表中的记录,也会被当做匹配结果,加入搜索结果中。

/**
 * 从本地消息数据库搜索消息历史。查询范围由anchor的sessionId和sessionType决定。
 * 该接口查询方向为从后往前。以锚点anchor作为起始点开始查询,返回最多limit条匹配key的记录。
 * 该接口目前仅搜索文本类型的消息,匹配规则为文本内容包含keyword,仅支持精确匹配,不支持模糊匹配和拼音匹配。
 * 由于sdk并不存储用户数据,因此keyword不会匹配用户资料。如果调用者希望查询指定用户的说话记录,可提供fromAccounts参数。
 * 如果提供的fromAccounts参数不为空,那么anchor对应的会话(sessionId和sessionType)的消息记录中,
 * 凡是消息说话者在fromAccounts列表中的记录,也会被当做匹配结果,加入搜索结果中。
 * 注意:搜索结果不包含anchor
 *
 * @return InvocationFuture
 */
public InvocationFuture<List<IMMessage>> searchMessageHistory(String keyword, List<String> fromAccounts, IMMessage anchor, int limit);
参数 说明
keyword 文本消息的搜索关键字
fromAccounts 消息说话者帐号列表,如果消息说话在该列表中,那么无需匹配 keyword,
对应的消息记录会直接加入搜索结果集中。
anchor 搜索的消息锚点
limit 搜索结果的条数限制
// 搜索『关键字』20条
NIMClient.getService(MsgService.class).searchMessageHistory("关键字", fromAccounts, anchor, 20)
     .setCallback(new RequestCallbackWrapper<List<IMMessage>>(){ ... });

根据时间点搜索消息历史

SDK 还提供了按照关键字全局搜索聊天记录的接口:MsgService#searchAllMessageHistory,用法与上述类似。目前暂不提供索引方式的全文检索功能,该全局搜索接口需要开发者评估大数据情况下的性能开销。

根据时间点搜索消息历史。该接口查询方向以某个时间点为基准从后往前,返回最多 limit 条匹配 key 的记录。该接口目前仅搜索文本类型的消息,匹配规则为文本内容包含 keyword,仅支持精确匹配,不支持模糊匹配和拼音匹配。 由于 sdk 并不存储用户数据,因此 keyword 不会匹配用户资料。如果调用者希望查询指定用户的说话记录,可提供 fromAccounts 参数。如果提供的 fromAccounts 参数不为空,那么凡是消息说话者在 fromAccounts 列表中的记录,也会被当做匹配结果,加入搜索结果中。

/**
 * 从本地消息数据库搜索消息历史。
 * 该接口查询方向以某个时间点为基准从后往前,返回最多limit条匹配key的记录。
 * 该接口目前仅搜索文本类型的消息,匹配规则为文本内容包含keyword,仅支持精确匹配,不支持模糊匹配和拼音匹配。
 * 由于sdk并不存储用户数据,因此keyword不会匹配用户资料。如果调用者希望查询指定用户的说话记录,可提供fromAccounts参数。
 * 如果提供的fromAccounts参数不为空,那么凡是消息说话者在fromAccounts列表中的记录,也会被当做匹配结果,加入搜索结果中。
 *
 * @return InvocationFuture
 */
public InvocationFuture<List<IMMessage>> searchAllMessageHistory(String keyword, List<String> fromAccounts, long time, int limit);
参数 说明
keyword 文本消息的搜索关键字
fromAccounts 消息说话者帐号列表,如果消息说话在该列表中,那么无需匹配 keyword,
对应的消息记录会直接加入搜索结果集中。
time 查询范围时间点,比 time 小(从后往前查)
limit 搜索结果的条数限制
NIMClient.getService(MsgService.class).searchAllMessageHistory(keyword, fromAccounts, time, limit)
    .setCallback(new RequestCallbackWrapper<List<IMMessage>>(){ ... });

删除消息记录

删除单条消息记录

/**
 * 删除一条消息记录
 *
 * @param message 待删除的消息记录
 */
public void deleteChattingHistory(IMMessage message);
// 删除单条消息
NIMClient.getService(MsgService.class).deleteChattingHistory(message);

删除与某个对象的全部消息记录

/**
 * 清除与指定用户的所有消息记录
 *
 * @param account     聊天对象ID,群id 或者 用户account,与sessionType 一一对应
 * @param sessionType 聊天类型,群聊或者P2P
 */
public void clearChattingHistory(String account, SessionTypeEnum sessionType);
// 删除与某个聊天对象的全部消息记录
NIMClient.getService(MsgService.class).clearChattingHistory(account, sessionType);

注意:当调用 MsgService#clearChattingHistory 接口删除与某个对象的全部聊天记录后,最近会话列表(最近联系人列表)中对应的项不会被移除,但会清空最近的消息内容,包括消息的时间显示(但 RecentContact 的 tag, extension 字段作为开发者的扩展字段,不会被清除。开发者可使用 tag, extension 进行最近会话列表显示定制)。如果需要移除最近会话项,请调用 MsgService#deleteRecentContact 接口。