历史记录

本地记录

提供了比较完善的消息记录管理功能,开发者可本地查阅、在线查阅、删除和清空聊天记录,还可以写入消息记录,导入/导出历史消息(仅能导入当前用户的记录)。此外,还要注意:本地消息历史操作(如删除)及状态变化(如发送失败或成功)会与会话列表里的消息状态自动同步,App 上层需要根据监听会话列表通知回调进行相应通知事件的处理。

全局消息状态变更通知

MessageStatusChanged消息状态变化

参数 字段 说明
int kNIMMsglogStatusChangedKeyStatus 消息状态,详见消息状态
string kNIMMsglogStatusChangedKeyTalkID 会话id
int64_t kNIMMsglogStatusChangedKeyMsgTimetag 临界的消息的时间戳,毫秒
void nim_msglog_reg_status_changed_cb(const char *json_extension, nim_msglog_status_changed_cb_func cb, const void *user_data);
void my_nim_msglog_status_changed_cb_func(int res_code, const char *result, const char *json_extension, const void *user_data)
{
    //result 解析
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isArray())
    {
        int size = values.size();
        for (int i = 0; i < size; i++)
        {
            //解析状态变化字段 MessageStatusChanged;
            Json::Value value = values[i];
            NIMMsgLogStatus status_= (NIMMsgLogStatus)value[kNIMMsglogStatusChangedKeyStatus].asUInt();
            string talk_id = value[kNIMMsglogStatusChangedKeyTalkID].asString();
            int64_t msg_timetag = value[kNIMMsglogStatusChangedKeyMsgTimetag].asInt64();
            ...
        }
    }
    ...
}
//注册全局的消息状态变更通知
nim_msglog_reg_status_changed_cb(0,my_nim_msglog_status_changed_cb_func,0);

查询消息历史

SDK 提供了一个根据锚点查询本地消息历史记录的接口,结果使用 time 作为排序字段(按时间逆序起查,逆序排列)。支持在扩展字段对查询更早或者更晚消息的控制。

void nim_msglog_query_msg_async(const char *account_id, enum NIMSessionType to_type, int limit_count, int64_t anchor_msg_time, const char *json_extension, nim_msglog_query_cb_func cb, const void *user_data);
参数 说明
account_id 会话id,对方的account id或者群组tid
to_type 会话类型
limit_count 一次查询数量,建议20
anchor_msg_time 上次查询最后一条消息的时间戳(按时间逆序起查,即最小的时间戳)
cb 查询结果回调通知,返回消息内容的集合
json_extension 扩展字段,仅支持查询更早或更晚的消息,如{"direction":0},0:查询比锚点时间更早的消息,1:查询比锚点时间更晚的消息
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理

Direction 属性说明:

枚举 说明
kForward 0 查询比锚点时间更早的消息
kBackward 1 查询比锚点时间更晚的消息
void my_nim_msglog_query_cb_func(int res_code, const char *id, NIMSessionType to_type, const char* result, const char* json_extension, const void *user_data)
{
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isObject())
    {
        int count_ = values[kNIMMsglogQueryKeyCount].asUInt();
        int source_ = (NIMMsglogQuerySource)values[kNIMMsglogQueryKeySource].asUInt();
        Json::Value msgs = values[kNIMMsglogQueryKeyContent];
        int len = msgs.size();
        for (int i = 0; i < len; i++)
        {
            //解析为 IMMessage msg;
            //ParseMessage(msgs[i], msg);
            ...
        }
        return true;
    }
}
//测试账号test1
char* session_id = "test1";
my_nim_msglog_query_cb_func(session_id, kNIMSessionTypeP2P, 20, 0, my_nim_msglog_query_cb_func,0);


//控制查询方向,查询更早或者更晚的消息
Json::Value values;
values["direction"] = 1;
my_nim_msglog_query_cb_func(session_id, kNIMSessionTypeP2P, 20, 0,my_nim_msglog_query_cb_func,0),GetJsonStringWithNoStyled(values));

根据消息 uuid 查询消息

void nim_msglog_query_msg_by_id_async(const char *client_msg_id, const char *json_extension,nim_msglog_query_single_cb_func cb, const void *user_data);
参数 说明
client_msg_id 所查询的消息id
cb 查询结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理

void my_nim_msglog_query_single_cb_func(int res_code, const char *msg_id, const char *result, const char *json_extension, const void *user_data)
{
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isObject())
    {
        int count_ = values[kNIMMsglogQueryKeyCount].asUInt();
        int source_ = (NIMMsglogQuerySource)values[kNIMMsglogQueryKeySource].asUInt();
        Json::Value msgs = values[kNIMMsglogQueryKeyContent];
        int len = msgs.size();
        for (int i = 0; i < len; i++)
        {
            //解析为 IMMessage msg;
            //ParseMessage(msgs[i], msg);
            ...
        }
        return true;
    }
}
char* clientMsgId="msg_id";//以实际的消息id为准
nim_msglog_query_msg_by_id_async(clientMsgId, 0,my_nim_msglog_query_single_cb_func,0);

根据指定条件查询本地消息

根据指定条件查询本地消息,使用此接口可以完成全局搜索等功能,具体请参阅开发手册。暂时仅支持单个id的查询,即ids只能添加一个,不支持多个uid。search_content参数不能为空。

void nim_msglog_query_msg_by_options_async(enum NIMMsgLogQueryRange query_range,const char *ids,int limit_count,int64_t from_time,int64_t end_time,const char *end_client_msg_id,bool reverse,enum NIMMessageType msg_type,const char *search_content,const char *json_extension,nim_msglog_query_cb_func cb,const void *user_data);
参数 说明
query_range 消息历史的检索范围
ids 会话id,对方的account id的集合或者群组tid的集合,目前仅支持单个id的查询,json数组
limit_count 搜索结果的条数限制
from_time 起始时间戳,单位:毫秒
end_time 结束时间戳,单位:毫秒
end_client_msg_id 结束查询的最后一条消息的client_msg_id(不包含在查询结果中)(暂不启用)
reverse true:反向查询(按时间正序起查,正序排列),false:按时间逆序起查,逆序排列(建议默认为false)
msg_type 检索的消息类型(目前只支持kNIMMessageTypeTextkNIMMessageTypeImagekNIMMessageTypeFile这三种类型消息)
search_content 检索文本(目前只支持kNIMMessageTypeTextkNIMMessageTypeFile这两种类型消息的文本关键字检索,即支持文字消息和文件名的检索。如果合并检索,需使用未知类型消息kNIMMessageTypeUnknown
cb 查询结果回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理

NIMMsgLogQueryRange枚举类型

枚举 说明
kNIMMsgLogQueryRangeP2P 0 指定的个人(点对点会话)(注意:暂不支持指定多个人的检索!)
kNIMMsgLogQueryRangeTeam 1 指定的群组(注意:暂不支持指定多个群组的检索!)
kNIMMsgLogQueryRangeAll 100 全部
kNIMMsgLogQueryRangeAllP2P 101 所有个人会话
kNIMMsgLogQueryRangeAllTeam 102 所有群组
kNIMMsgLogQueryRangeUnknown 200 不支持查询
//查询结果,参考本地查询
void my_nim_msglog_query_cb_func(int res_code, const char *id, NIMSessionType to_type, const char* result, const char* json_extension, const void *user_data)
{
    ...
}
//以P2P消息为例
char* ids = "[\"testAccount\"]"; //json数组

int64_t sTimetag = 1519977874123;//13位时间戳毫秒
int64_t eTimetag = 1519978139567;13位时间戳毫秒,需要比sTimetag更晚,即eTimetag > sTimetag
char* endMsgId = "lastmsgid";//对应eTimetag时间点的消息id


nim_msglog_query_msg_by_options_async(kNIMMsgLogQueryRangeP2P, ids, 20,sTimetag, eTimetag, endMsgId, false, kNIMMessageTypeText, "111", 0,my_nim_msglog_query_cb_func,0)

插入本地消息

保存消息到本地数据库,如果已存在这条消息,则更新,但不发送到服务器端。需要保证整条消息内容是符合消息收发的规范。

void nim_msglog_insert_msglog_async(const char *talk_id, const char* json_msg, bool need_update_session, const char *json_extension, nim_msglog_res_cb_func cb, const void *user_data);
参数 说明
talk_id 会话id,对方的account id或者群组tid
need_update_session 是否更新会话列表(一般最新一条消息会有更新的需求)
json_msg 消息体,详见IMMessage
cb 操作结果的回调函数
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理

void my_nim_msglog_res_cb_func(int res_code, const char *msg_id, const char *json_extension, const void *user_data)
{
    ...
}
// 创建一条文本消息,以对方账号testAccount为例
Json::Value values;
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyToAccount] = "testAccount";对方账号
values[kNIMMsgKeyFromAccount] = sender_accid_;
values[kNIMMsgKeyTime] = 1519977874123;//13位时间戳毫秒
values[kNIMMsgKeyType] = kNIMMessageTypeText;
values[kNIMMsgKeyBody] = "111";
values[kNIMMsgKeyClientMsgid] = "uuid";//该条消息唯一id
values[kNIMMsgKeyLocalTalkId] = "testAccount";对方账号
values[kNIMMsgKeyLocalLogStatus] = kNIMMsgLogStatusDraft;//可设置其他消息状态
values[kNIMMsgKeyLocalLogSubStatus] = 0;

//其他消息设置
...

//序列化json
Json::FastWriter fw;
char* msg = fw.write(values);
...
// 保存消息到本地数据库,但不发送到服务器
nim_msglog_insert_msglog_async("testAccount", msg, true,0,my_nim_msglog_res_cb_func,0);

删除历史消息

可以删除指定msgid的消息,也可以批量删除消息。

1. 删除指定的一条消息

通过指定对方account或者群id,msgId来删除历史消息

void nim_msglog_delete_async(const char *account_id, enum NIMSessionType to_type, const char *msg_id, const char *json_extension, nim_msglog_res_cb_func cb, const void *user_data);
参数 说明
session_id 对方account或者群id
to_type 当前会话的类型,指定枚举类型NIMSessionType
msg_id 指定要删除的消息唯一id
cb 操作结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_res_cb_func(int res_code, const char *msg_id, const char *json_extension, const void *user_data)
{
    ...
}
//以p2p消息为例,测试账号testAccount
nim_msglog_delete_async("testAccout",kNIMSessionTypeP2P,"client_msgid",0,my_nim_msglog_res_cb_func,0);

2. 删除指定会话类型的所有消息

通知指定to_type批量删除数据库中的历史记录,只操作本地数据库,不同步服务器。

void nim_msglog_delete_by_session_type_async(bool delete_sessions, enum NIMSessionType to_type, const char *json_extension, nim_msglog_res_ex_cb_func cb, const void *user_data);
参数 说明
to_type 当前会话的类型,指定枚举类型NIMSessionType
delete_sessions 是否要同步删除会话列表项,true:删除,false:不删除,仅标记消息状态为已删除
cb 操作结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_res_ex_cb_func(int res_code, const char *uid, enum NIMSessionType type, const char *json_extension, const void *user_data)
{
    ...
}
// 批量删除点对点消息记录
nim_msglog_delete_by_session_type_async(true,kNIMSessionTypeP2P,0,my_nim_msglog_res_ex_cb_func,0);

3. 删除所有历史记录

删除全部本地的历史消息,并可以选择同步删除会话列表项。

void nim_msglog_delete_all_async(bool delete_sessions, const char *json_extension, nim_msglog_modify_res_cb_func cb, const void *user_data);
参数 说明
delete_sessions 是否要同步删除会话列表项,true:删除,false:不删除,仅标记消息状态为已删除
cb 操作结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_modify_res_cb_func(int res_code, const char *json_extension, const void *user_data)
{
    ...
}
// 批量删除点对点消息记录
nim_msglog_delete_all_async(kNIMSessionTypeP2P,0,my_nim_msglog_modify_res_cb_func,0);

修改消息状态

SDK 提供了修改消息为草稿等状态,也可以修改语音消息等的已播放和未播放的子状态

NIMMsgLogStatus消息状态

枚举 说明
kNIMMsgLogStatusNone 0 默认,不能当查询条件,意义太多
kNIMMsgLogStatusUnread 1 收到消息,未读
kNIMMsgLogStatusRead 2 收到消息,已读
kNIMMsgLogStatusDeleted 3 消息已删
kNIMMsgLogStatusSending 4 消息发送中
kNIMMsgLogStatusSendFailed 5 发送失败
kNIMMsgLogStatusSent 6 已发送
kNIMMsgLogStatusReceipt 7 对方已读发送的内容
kNIMMsgLogStatusDraft 8 草稿
kNIMMsgLogStatusSendCancel 9 发送取消
kNIMMsgLogStatusRefused 10 被对方拒绝,比如被对方加入黑名单等等

NIMMsgLogSubStatus消息子状态

枚举 说明
kNIMMsgLogSubStatusNone 0 默认
kNIMMsgLogSubStatusNotPlaying 1 未播放
kNIMMsgLogSubStatusPlayed 2 已播放

1. 设置消息状态

 void nim_msglog_set_status_async(const char *msg_id, enum NIMMsgLogStatus msglog_status, const char *json_extension, nim_msglog_res_cb_func cb, const void *user_data);
参数 说明
msg_id 指定的消息唯一id
msglog_status 指定需要修改的状态
cb 操作结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_res_cb_func(int res_code, const char *msg_id, const char *json_extension, const void *user_data)
{
    ...
}
// 设置client_msgid为kNIMMsgLogStatusSent状态;
nim::MsgLog::SetStatusAsync("client_msgid",kNIMMsgLogStatusSent,0,my_nim_msglog_res_cb_func,0);

2. 设置消息子状态

void nim_msglog_set_sub_status_async(const char *msg_id, enum NIMMsgLogSubStatus msglog_sub_status, const char *json_extension, nim_msglog_res_cb_func cb, const void *user_data);
参数 说明
msg_id 指定的消息唯一id
msglog_sub_status 指定需要修改的消息子状态,详见NIMMsgLogSubStatus
cb 操作结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_res_cb_func(int res_code, const char *msg_id, const char *json_extension, const void *user_data)
{
    ...
}

// 设置client_msgid为kNIMMsgLogStatusSent状态;
nim_msglog_set_sub_status_async("client_msgid",kNIMMsgLogSubStatusPlayed,0,my_nim_msglog_res_cb_func,0);

查询服务器消息历史

通过消息类型从服务器端获取消息历史,通过起止时间错和limit的显示来限制获取的范围。

void nim_msglog_query_msg_online_async(const char *id,enum NIMSessionType to_type,int limit_count,int64_t from_time,int64_t end_time,int64_t end_msg_id,bool reverse,bool need_save_to_local,const char *json_extension,nim_msglog_query_cb_func cb,const void *user_data);
参数 说明
id 会话id,对方的account id或者群组tid
to_type 会话类型
limit_count 搜索结果的条数限制,建议20
from_time 起始时间戳,单位:毫秒
end_time 结束时间戳,单位:毫秒
end_msg_id 结束查询的最后一条消息的服务器端消息id(server_msg_id)(不包含在查询结果中)
reverse true:反向查询(按时间正序起查,正序排列),false:按时间逆序起查,逆序排列(建议默认为false)
need_save_to_local true: 将在线查询结果保存到本地,false: 不保存
cb 查询结果回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
//查询结果,参考本地查询
void my_nim_msglog_query_cb_func(int res_code, const char *id, NIMSessionType to_type, const char* result, const char* json_extension, const void *user_data)
{
    ...
}
nim_msglog_query_msg_online_async(id, to_type, limit, from_time, end_time,end_msg_id, false, true, true,0, my_nim_msglog_query_cb_func,0)

导入导出消息历史

SDK为了方便用户,提供导入和导出消息历史文件的接口,必须提供导入或者导出文件的绝对路径。

导出消息历史

导出整个消息历史DB文件(不包括系统消息历史,android 和 ios 平台下不可用)

void nim_msglog_export_db_async(const char *dst_path, const char *json_extension, nim_msglog_modify_res_cb_func cb, const void *user_data);
参数 说明
dst_path 导出时保存的目标绝对路径,必须保证该路径下可写入文件
cb 操作结果回调通知
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_modify_res_cb_func(int res_code, const char* json_extension, const void* user_data)
{
    ...
}
//以windows平台路径为例
nim_msglog_export_db_async("D:\\msg.db",0,my_nim_msglog_modify_res_cb_func,0);

导入消息历史

导入消息历史记录(不包括系统通知),且不允许拿别人的消息历史记录文件来导入。调用此接口需要传入消息历史文件的绝对路径。

void nim_msglog_import_db_async(const char *src_path, const char *json_extension, nim_msglog_modify_res_cb_func res_cb, const void *res_user_data, nim_msglog_import_prg_cb_func prg_cb, const void *prg_user_data);
参数 说明
src_path 导出时保存的目标绝对路径,必须保证该路径下可写入文件
json_extension 扩展字段,预留
res_cb 操作结果回调通知
res_user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
prg_cb 操作进度回调通知
prg_user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
//导入结果回调
void my_nim_msglog_modify_res_cb_func(int res_code, const char* json_extension, const void* user_data)
{
    ...
}
//导入进度回调
void my_nim_msglog_import_prg_cb_func(int64_t imported_count, int64_t total_count, const char *json_extension, const void *user_data)
{
    //通知导入进度
    ...
}
//以windows平台路径为例
nim_msglog_import_db_async("D:\\msg.db",0,my_nim_msglog_modify_res_cb_func,0,my_nim_msglog_import_prg_cb_func,0);