消息收发

消息功能概述

SDK 提供一套完善的消息传输管理服务,包括收发消息,存储消息,上传下载附件,管理最近联系人等。原生支持发送文本,语音,图片,视频,文件,地理位置,提醒等多种类型消息,同时支持用户发送自定义的消息类型。消息功能具体介绍可参考产品介绍的 基础消息功能

NIMMessageType消息类型

枚举 说明
kNIMMessageTypeText 0 文本类型消息
kNIMMessageTypekNIMMessageTypeImageText 1 图片类型消息
kNIMMessageTypeAudio 2 声音类型消息
kNIMMessageTypeVideo 3 视频类型消息
kNIMMessageTypeLocation 4 位置类型消息
kNIMMessageTypeNotification 5 系统类型通知(包括入群出群通知等
kNIMMessageTypeFile 6 文件类型消息
kNIMMessageTypeTips 10 提醒类型消息,Tip内容根据格式要求填入消息结构中的kNIMMsgKeyServerExt字段
kNIMMessageTypeRobot 11 智能机器人消(暂不支持)
kNIMMessageTypeCustom 100 自定义消息
kNIMMessageTypeUnknown 1000 未知类型消息,作为默认值

NIMMessageFeature消息类型

枚举 说明
kNIMMessageFeatureDefault 0 默认
kNIMMessageFeatureLeaveMsg 1 离线消息
kNIMMessageFeatureRoamMsg 2 漫游消息
kNIMMessageFeatureSyncMsg 3 默认消息,多端同时登录时,同步到各端的消息
kNIMMessageFeatureCustomizedMsg 4 透传消息

IMMessage消息基础内容

类型 参数 说明
NIMSessionType kNIMMsgKeyToType 会话类型,详见NIMSessionType
string kNIMMsgKeyFromAccount 消息发送方id,服务器填写,发送方不需要填写
string kNIMMsgKeyToAccount 消息接收方id,必填,如给自己发送消息时填写自己id
NIMClientType kNIMMsgKeyFromClientType 消息发送方客户端类型,服务器填写,发送方不需要填写
string kNIMMsgKeyFromDeviceId 消息发送方设备id,服务器填写,发送方不需要填写
string kNIMMsgKeyFromNick 消息发送方昵称,服务器填写,发送方不需要填写
int64_t kNIMMsgKeyTime 消息时间戳,(毫秒13位UNIX时间戳)
NIMMessageType kNIMMsgKeyType 消息类型,详见NIMMessageType
string kNIMMsgKeyClientMsgid 消息uuid,唯一标识,发送方填写
int64_t kNIMMsgKeyServerMsgid 服务器端消息id,服务器填写
string kNIMMsgKeyLocalFilePath 多媒体消息资源本地绝对路径,SDK本地维护,发送多媒体消息时必填,如果是图片消息,当设置下载缩略图时,此路径为缩略图的本地绝对路径
string kNIMMsgKeyLocalTalkId 会话id,发送方选填,接收方收到的是消息发送方id
string kNIMMsgKeyLocalResId 多媒体资源id,发送方选填,接收方收到的是客户端消息id
NIMMsgLogStatus kNIMMsgKeyLocalLogStatus 本地消息状态,详见消息状态类型)
NIMMsgLogSubStatus kNIMMsgKeyLocalLogSubStatus 本地消息子状态,详见消息子状态类型)
-- 消息设置 以下是消息设置字段定义说明
int kNIMMsgKeyResendFlag 是否是重发消息,第一次发送0,再次重发该消息填 1,一般用于失败重发
int kNIMMsgKeyPushEnable 是否需要推送,1:需要,0:不需要
int kNIMMsgKeyPushNeedBadge (可选)推送是否要做消息计数(角标) 1:需要,0:不需要
int kNIMMsgKeyPushNeedPrefix (可选)推送是否需要前缀 默认 True
string kNIMMsgKeyPushContent 自定义推送文案,长度限制200字节
string kNIMMsgKeyPushPayload 自定义的推送属性,限制非格式化的json字符串,长度限制2048
int kNIMMsgKeyHistorySave (可选)该消息是否存储云端历史,可选,默认填 1,1:需要,0:不需要,如果支持漫游和离线,则必须填1
int kNIMMsgKeyMsgRoaming (可选)该消息是否支持漫游,可选, 默认1,1:需要,0:不需要
int kNIMMsgKeyMsgSync (可选)该消息是否支持发送者多端同步,默认填1, 1:需要,0:不需要
int kNIMMsgKeyMsgRoutable (可选)该消息是否抄送,0:不支持,1:支持,默认按照app的路由开关
int kNIMMsgKeySetMsgOffline (可选)消息是否要存离线,默认填1, 1:需要,0:不需要,如果需要支持漫游,必须填1
int kNIMMsgKeyAntiSpamEnable 是否需要过易盾反垃圾,1:需要,0:不需要
string kNIMMsgKeyAntiSpamContent (可选)开发者自定义的反垃圾字段,长度限制:5000字符, 格式为json string,{"type" : 1:文本,2:图片,3视频, "data" : "文本内容or图片地址or视频地址"}
string kNIMMsgKeyServerExt 第三方扩展字段, 长度限制1024
string kNIMMsgKeyLocalExt 本地扩展内容,只保存在本地,预留字段
int kNIMMsgKeyIsForcePush 群组消息强推开关,强推全员设置true并强推列表为空
string kNIMMsgKeyForcePushList_ 群组消息强推列表,json array
string kNIMMsgKeyForcePushContent 群组消息强推文本

注意: 漫游消息是指在一端已经收过的消息,在未登录的一端也会下发(服务端最近100个会话)的消息,多端同步是指多个设备平台是同时登录时,一端发送消息,其他端同步收到发出的的消息,离线消息是指 发送给对方消息,如果对方不在线,对方在下次登录时会收到的消息。

消息相关设置说明

kNIMMsgKeySetMsgOffline kNIMMsgKeyHistorySave kNIMMsgKeyMsgRoaming kNIMMsgKeyMsgSync
离线消息 1 1 optional optional
漫游消息 1 1 1 optional
多端同步消息 optional optional optional 1

发送消息

SDK提供对普通文本消息,图片消息,语音消息,视频消息,文件消息,地理位置消息,提醒消息等等内置消息类型(NIMMessageType)的支持,也可以发送自定义的消息。同时我们也提供了停止发送消息接口,该接口目前主要用于在文件消息上传过程中终止消息发送。

void nim_talk_send_msg(const char *json_msg, const char *json_extension, nim_nos_upload_prg_cb_func prg_cb, const void *prg_user_data);
参数 说明
json_msg 消息内容,json字符串,字段定义详见IMMessage
json_extension 扩展字段,预留
nim_nos_upload_prg_cb_func 上传进度回调通知,如果存在图片、音视频文件 等自定上传的附件内容时,会通知上传进度
prg_user_data APP的自定义用户数据,SDK只负责传回给回调函数prg_cb,不做任何处理

消息设置

发送消息还提供了以下消息属性设置(对应MessageSetting中的字段):

针对群组消息,提供强推属性设置(可以用于实现@功能等):

反垃圾字段:

聊天室相同类型的消息,其内容同IM同类型消息的附件,附件内容组装格式是一致的。

文本消息

首先创建文本消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。

//创建文本消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
char* content = "这是一条文本消息。";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyBody] = content;
values[kNIMMsgKeyType] = kNIMMessageTypeText;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0,SDK自动获取本地时间戳

//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;
...

//如果需要反垃圾
values[kNIMMsgKeyAntiSpamEnable] = 1;
//组装反垃圾内容
Json::Value jx;
jx["type"] = 1;
jx["data"] = content;//如果是图片视频类型,填附件的url
values[kNIMMsgKeyAntiSpamContent] = fw.write(jx);//序列化得到json字符串

//其他设置
...

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

图片消息

首先创建图片消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。发送本地图片文件会自动上传。

图片消息的附件内容IMImage除拥有IMFile所有字段外,其自有字段说明

类型 参数 字段
int kNIMImgMsgKeyWidth 图片宽度
int kNIMImgMsgKeyHeight 图片高度
//以点对消息为例,测试账号test1
//创建图片消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
//本地文件路径
char* local_file_path = "c:\\img.png";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeImage;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0SDK自动获取本地时间戳
values[kNIMMsgKeyLocalFilePath] = local_file_path;

//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//组装附件内容
Json::Value attachment;
attachment[kNIMFileMsgKeyMd5] = "0ca175b9c0f726a831d895e269332461";
attachment[kNIMFileMsgKeySize] = 409600;
attachment[kNIMMsgAttachKeyUrl]_="http://xxxxxx/img.png";//如果发送本地文件,此处填空
attachment[kNIMFileMsgKeyDisplayName] = "img";
attachment[kNIMFileMsgKeyExt] = "png";

//设置图片高度和宽度
attachment[kNIMImgMsgKeyWidth] = 800;
attachment[kNIMImgMsgKeyHeight] = 600;

values[kNIMMsgKeyAttach] = fw.write(attachment);//得到附件内容

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

语音消息

首先创建语音消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。发送本地语音文件会自动上传。

语音消息的附件内容IMAudio除拥有IMFile所有字段外,其自有字段说明

类型 参数 字段
int kNIMAudioMsgKeyDuration 语音消息时长
//以点对消息为例,测试账号test1
//创建语音消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
//本地文件路径
char* local_file_path = "c:\\audio.aac";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeAudio;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0,SDK自动获取本地时间戳
values[kNIMMsgKeyLocalFilePath] = local_file_path;


//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//组装附件内容
Json::Value attachment;
attachment[kNIMFileMsgKeyMd5] = "0ca175b9c0f726a831d895e269332461";
attachment[kNIMFileMsgKeySize] = 409600;
attachment[kNIMMsgAttachKeyUrl]_="http://xxxxxx/audio.aac";//如果发送本地文件,此处填空
attachment[kNIMFileMsgKeyDisplayName] = "audio";
attachment[kNIMFileMsgKeyExt] = "aac";

//设置时长
attachment[kNIMAudioMsgKeyDuration] = 8000;//毫秒

values[kNIMMsgKeyAttach] = fw.write(attachment);//得到附件内容

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

视频消息

首先创建视频消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。发送本地视频文件会自动上传。

视频消息的附件内容IMVideo除拥有IMFile所有字段外,其自有字段说明

类型 参数 字段
int kNIMVideoMsgKeyDuration 语音消息时长
int kNIMVideoMsgKeyWidth 图片宽度
int kNIMVideoMsgKeyHeight 图片高度
//以点对消息为例,测试账号test1
//创建视频消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
//本地文件路径
char* local_file_path = "c:\\video.mp4";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeVideo;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳
values[kNIMMsgKeyLocalFilePath] = local_file_path;


//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//组装附件内容
Json::Value attachment;
attachment[kNIMFileMsgKeyMd5] = "0ca175b9c0f726a831d895e269332461";
attachment[kNIMFileMsgKeySize] = 409600;
attachment[kNIMMsgAttachKeyUrl]_="http://xxxxxx/video.mp4";//如果发送本地文件,此处填空
attachment[kNIMFileMsgKeyDisplayName] = "video";
attachment[kNIMFileMsgKeyExt] = "mp4";

//设置时长,图像长宽
attachment[kNIMVideoMsgKeyDuration] = 8000;//毫秒
attachment[kNIMVideoMsgKeyWidth] = 800;
attachment[kNIMVideoMsgKeyHeight] = 600;

values[kNIMMsgKeyAttach] = fw.write(attachment);//得到附件内容

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

地理位置

首先创建地理位置息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。

地理位置消息的附件内容NIMLocationMsgInfo字段说明

类型 参数 字段
string kNIMLocationMsgKeyTitle 地理位置描述
int kNIMLocationMsgKeyLatitude 纬度
int kNIMLocationMsgKeyLongitude 经度
//以点对消息为例,测试账号test1
//创建地理位置消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1


Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeLocation;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0,SDK自动获取本地时间戳


//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//组装附件内容
Json::Value attachment;
//设置地理名称和经纬度
attachment[kNIMLocationMsgKeyTitle] = "杭州";
attachment[kNIMLocationMsgKeyLatitude] = 30.3;
attachment[kNIMLocationMsgKeyLongitude] = 120.2;

values[kNIMMsgKeyAttach] = fw.write(attachment);//得到附件内容

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

文件消息

首先创建文件消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。

IMFile文件类型附件

类型 参数 字段
string kNIMFileMsgKeyMd5 文件内容的md5
int64_t kNIMFileMsgKeySize 文件大小,64位整型
string kNIMMsgAttachKeyUrl 文件的http url
string kNIMFileMsgKeyDisplayName文件名
string kNIMFileMsgKeyExt 文件扩展名
//以点对消息为例,测试账号test1
//创建文件消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
//本地文件路径
char* local_file_path = "c:\\文档.doc";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeFile;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳
values[kNIMMsgKeyLocalFilePath] = local_file_path;


//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//组装附件内容
Json::Value attachment;
attachment[kNIMFileMsgKeyMd5] = "0ca175b9c0f726a831d895e269332461";
attachment[kNIMFileMsgKeySize] = 409600;
attachment[kNIMMsgAttachKeyUrl]_="http://xxxxxx/文档.doc";//如果发送本地文件,此处填空
attachment[kNIMFileMsgKeyDisplayName] = "文档";
attachment[kNIMFileMsgKeyExt] = "doc";

values[kNIMMsgKeyAttach] = fw.write(attachment);//得到附件内容

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

提示消息

首先创建提示消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。如果开发者不需要发送到服务器,则可以使用插入本地消息接口,将消息存入数据库,并更新会话类表。


//以点对消息为例,测试账号test1
//创建提示消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
char* tip_content = "这是提示信息";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeTips;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0,SDK自动获取本地时间戳
values[kNIMMsgKeyBody] = tip_content;

//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

自定义消息

首先创建自定义消息消息的内容,按需填写必要的消息设置,然后通过nim_talk_send_msg接口发送。除SDK 不负责定义和解析自定义消息的具体内容,解释工作由开发者完成。SDK 会将自定义消息存入消息数据库,会和内建消息一并展现在消息记录中。在全局设置中,可以设置是否本地存储自定义消息,默认是存储。


//以点对消息为例,测试账号test1
//创建提示消息示例
Json::FastWriter fw;
//以点对消息kNIMSessionTypeP2P为例,测试账号test1
char* content = "这是普通文本内容";

Json::Value values;
values[kNIMMsgKeyToAccount] = "test1";
values[kNIMMsgKeyToType] = kNIMSessionTypeP2P;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyType] = kNIMMessageTypeCustom;
values[kNIMMsgKeyLocalTalkId] = "test1";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0,SDK自动获取本地时间戳
values[kNIMMsgKeyBody] = content;

//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;

//其他设置
...

//组装附件内容
Json::Value attachment;
attachment["customFiled1"] = "自定义内容1";
attachment["customFiled2"] = 10; //自定义值

values[kNIMMsgKeyAttach] = fw.write(attachment);//得到附件内容

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

群组强推消息

向群组发送强推消息,以@提醒指定的人或者所有人,详见MessageSetting


//以群为例,测试群账号1222222
Json::FastWriter fw;
char* content = "这是一条文本消息。";

Json::Value values;
values[kNIMMsgKeyToAccount] = "1222222";
values[kNIMMsgKeyToType] = kNIMSessionTypeTeam;
values[kNIMMsgKeyClientMsgid] = "生成自己的唯一uuid";
values[kNIMMsgKeyBody] = content;
values[kNIMMsgKeyType] = kNIMMessageTypeText;
values[kNIMMsgKeyLocalTalkId] = "1222222";
values[kNIMMsgKeyTime] = 1520500638234;//当前时间戳,若为0,SDK自动获取本地时间戳

//消息设置,按需设置
values[kNIMMsgKeyMsgRoaming] = 1;
values[kNIMMsgKeySetMsgOffline] = 1;
values[kNIMMsgKeyHistorySave] = 1;
...


//其他设置
...

//强推消息设置,强推test1,test2,且为群成员
values[kNIMMsgKeyIsForcePush] = 1;
values[kNIMMsgKeyForcePushContent] = "这是一条强推消息";

Json::Value pushlist;
pushlist.append("test1");
pushlist.append("test2");
values[kNIMMsgKeyForcePushList] = fw.write(pushlist);

//得到消息内容的json,用于nim_talk_send_msg发送
char* msg = fw.write(values);
//发送消息
nim_talk_send_msg(msg,0,0,0);

发送结果通知

通知发送成功、失败,也可以从结果获的是否命中客户端发垃圾标识。

SendMessageArc参数说明

类型 参数 说明
string kNIMSendAckKeyTalkId 会话id
string kNIMSendAckKeyMsgId 消息id
NIMResCode kNIMSendAckKeyRescode 错误码
int64_t kNIMSendAckKeyTimetag 消息时间戳
bool kNIMSendAckKeyClientAntiSpam 是否命中客户端反垃圾,1:是, 0:否
void nim_talk_reg_ack_cb(const char *json_extension, nim_talk_ack_cb_func cb, const void *user_data);
void my_nim_talk_ack_cb_func(const char *result, const void *user_data)
{
    //result 解析 为 SendMessageArc
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isObject())
    {
        NIMResCode rescode = (NIMResCode)values[kNIMSendAckKeyRescode].asUInt();
        char* msg_id = values[kNIMSendAckKeyMsgId].asString();
        char* talk_id = values[kNIMSendAckKeyTalkId].asString();
        int64_t msg_timetag = values[kNIMSendAckKeyTimetag].asInt64();
        bool client_anti_spam_hit = values[kNIMSendAckKeyClientAntiSpam].asUInt();
        ...
    }
}
//监听事件
nim_talk_reg_ack_cb(0,my_nim_talk_ack_cb_func,0);

//取消监听
nim_talk_reg_ack_cb(0,0,0);

停止发送消息

取消发送消息,目前支持文件类型消息,在文件上传过程中可以终止发送。如果文件已经上传完成,则无法中断。

 void nim_talk_stop_send_msg(const char *json_msg, const char *json_extension);
参数 说明
json_msg 所要终止发送的消息结构
json_extension 扩展字段,预留
//需要中断的消息唯一uuid,必填
char* clientMsgId = "uuid";

Json::FastWriter fw;
Json::Value values;
values[kNIMMsgKeyClientMsgid] = client_msg_id;
values[kNIMMsgKeyType] = kNIMMessageTypeFile;
//中断发送
nim_talk_stop_send_msg(fw.write(values), 0);

消息接收

开发者在登陆SDK之前需要提前注册消息接收的事件监听。消息接收包括在线消息的接收,也包括离线、同步、漫游消息等的接收。如果接收到多媒体消息,SDK 默认会在后台自动下载附件。如果是语音消息,直接下载文件,如果是图片消息,下载缩略图文件,可以通过下载接口去获取原图。

消息解析

图片、文件、语音、视频、地理位置等等内置的消息提供了解析的支持,其他自定义的消息及附件内容需要开发者自行解析使用。

1. 解析消息内容 IMMessage所指定字段的内容。

//解析消息内容示例
void ParseIMMessage(Json::Value message)
{
    //消息内容
    int session_type = (NIMSessionType)message[kNIMMsgKeyToType].asUInt();
    char* receiver_accid = message[kNIMMsgKeyToAccount].asString();
    char* sender_accid = message[kNIMMsgKeyFromAccount].asString();
    int readonly_sender_client_type = (NIMClientType)message[kNIMMsgKeyFromClientType].asUInt();
    char* readonly_sender_device_id = message[kNIMMsgKeyFromDeviceId].asString();
    char* readonly_sender_nickname = message[kNIMMsgKeyFromNick].asString();
    int64_t timetag = message[kNIMMsgKeyTime].asUInt64();

    int type = (NIMMessageType)message[kNIMMsgKeyType].asUInt();
    char* content = message[kNIMMsgKeyBody].asString();
    char* attach = message[kNIMMsgKeyAttach].asString();
    char* client_msg_id = message[kNIMMsgKeyClientMsgid].asString();
    int64_t readonly_server_id = message[kNIMMsgKeyServerMsgid].asUInt64();

    char* local_res_path = message[kNIMMsgKeyLocalFilePath].asString();
    char* local_talk_id = message[kNIMMsgKeyLocalTalkId].asString();
    char* local_res_id = message[kNIMMsgKeyLocalResId].asString();
    int status = (NIMMsgLogStatus)message[kNIMMsgKeyLocalLogStatus].asUInt();
    int sub_status = (NIMMsgLogSubStatus)message[kNIMMsgKeyLocalLogSubStatus].asUInt();

    //消息设置
    int server_history_saved = message[kNIMMsgKeyHistorySave].asInt();
    int roaming = message[kNIMMsgKeyMsgRoaming].asInt()
    int multi_sync = message[kNIMMsgKeyMsgSync].asInt();
    int push_need_badge = message[kNIMMsgKeyPushNeedBadge].asInt();
    int need_push = message[kNIMMsgKeyPushEnable].asInt();
    int push_need_prefix = message[kNIMMsgKeyPushNeedPrefix].asInt();
    int resend_flag = message[kNIMMsgKeyResendFlag].asInt();
    int routable = message[kNIMMsgKeyMsgRoutable].asInt();
    int need_offline = message[kNIMMsgKeySetMsgOffline].asInt();
    char* push_payload = message[kNIMMsgKeyPushPayload].asString();
    char* server_ext = message[kNIMMsgKeyServerExt].asString();
    char* local_ext = message[kNIMMsgKeyLocalExt].asString();
    char* push_content = message[kNIMMsgKeyPushContent].asString();
    int is_force_push = message[kNIMMsgKeyIsForcePush].asInt();
    char* force_push_content = message[kNIMMsgKeyForcePushContent].asString();
    char* force_push_list = message[kNIMMsgKeyForcePushList].asString();
    int anti_spam_enable = message[kNIMMsgKeyAntiSpamEnable].asInt();
    char* anti_spam_content = message[kNIMMsgKeyAntiSpamContent].asString();
    ...
}

2. 解析接收消息

解析消息内容区别在于,此函数解析kNIMMsgKeyLocalRescode字段,kNIMMsgKeyLocalMsgFeature字段,kNIMMsgKeyLocalReceiveMsgContent,而ParseIMMessage解析的是kNIMMsgKeyLocalReceiveMsgContent所承载的实际消息内容。

//解析收到的消息示例
void ParseReceiveMessage(Json::Value received_message)
{

    NIMResCode rescode = (NIMResCode)received_message[kNIMMsgKeyLocalRescode].asUInt();
    NIMMessageFeature feature = (NIMMessageFeature)received_message[kNIMMsgKeyLocalMsgFeature].asUInt();

    Json::Value message = received_message[kNIMMsgKeyLocalReceiveMsgContent];
    //message 解析参考 ParseIMMessage
    ParseIMMessage(message);
    ...
}

在线消息接收

建议注册全局回调,SDK只存储一个cb,注册多次回调会导致覆盖,以最后一次注册的回调为准。不同类型的消息,比如文件、图片、语音等等消息的解析参考发送消息的附件,两者保持一致。

void nim_talk_reg_receive_cb(const char *json_extension, nim_talk_receive_cb_func cb, const void *user_data);
参数 说明
cb 异步通知回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理

void my_nim_talk_receive_cb_func(const char *result, const char *json_extension, const void *user_data)
{
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isObject())
    {
        //参考ParseReceiveMessage
        ParseReceiveMessage(values);
        ...
    }
}

//监听事件
nim_talk_reg_receive_cb(0,my_nim_talk_receive_cb_func,0);
//取消监听
nim_talk_reg_receive_cb(0,0,0);

离线同步漫游消息接收

接收批量消息,如离线,漫游,同步的批量消息。如果在注册了接收消息回调的同时也注册了该批量接口,当有批量消息时,会改走这个接口通知应用层,例如登录后接收到的离线消息等,必须在登录之前注册事件监听。区别于在线接收消息回调,此接口通知的是消息的集合。

void nim_talk_reg_receive_msgs_cb(const char *json_extension, nim_talk_receive_cb_func cb, const void *user_data);
参数 说明
cb 异步通知回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_talk_receive_cb_func(const char *result, const char *json_extension, const void *user_data)
{
    //区别于在线接收消息回调,这里返回的是消息的集合
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isArray())
    {
        int size = value.size();
        for (int i = 0; i < size; i++)
        {
            //参考ParseReceiveMessage
            ParseReceiveMessage(values);
            ...
        }
        ...
    }
}

//监听事件
nim_talk_reg_receive_msgs_cb(0,my_nim_talk_receive_cb_func,0);

//取消监听
nim_talk_reg_receive_msgs_cb(0,0,0);

过滤群通知消息

注册接收群通知是否需要过滤的回调。若果在此回调中返回true,则SDK认为此通知已被处理,SDK将不再通过接收消息通道下发,也不会保存本地数据库。

void nim_talk_reg_notification_filter_cb(const char *json_extension, nim_talk_team_notification_filter_func cb, const void *user_data);
参数 说明
cb 异步通知回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
//假设 bool filterTeamNotify = true;
bool my_nim_talk_team_notification_filter_func(const char *result, const char *json_extension, const void *user_data)
{
    //result是消息内容,参考ParseIMMessage
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isObject())
    {
        ParseIMMessage(values);
        ...
    }
    //如果设置处理过滤了通知消息,返回true,否则返回false;
    if (filterTeamNotify)
    {
        ...
        return true;
    }
    return false;
}
//监听事件
nim_talk_reg_notification_filter_cb(0,my_nim_talk_team_notification_filter_func,0);

//取消监听
nim_talk_reg_notification_filter_cb(0,0,0);

转发消息

用户通过构造API获取新的消息对象,然后调用发送消息接口。返回新的消息内容字符串,需要开发者主动释放内存。

char *nim_talk_create_retweet_msg(const char* src_msg_json, const char* client_msg_id, enum NIMSessionType retweet_to_session_type, const char* retweet_to_session_id, const char* msg_setting, int64_t timetag);
参数 说明
src_msg_json 接收到的消息内容,内容同IMMessage
client_msg_id 生成的新的消息uuid
retweet_to_session_id 转发的对方id,个人账号或者群id
retweet_to_session_type 会话类型,0:点对点消息 1: 群消息
msg_setting 消息设置,详见消息设置说明
timetag 当前的时间戳(毫秒)
//假设srcMsg已经发送或者收到的消息内容。
char* srcMsg;

//消息设置,按需设置,参考消息发送
Json::FastWriter fw;
Json::Value setting;
setting[kNIMMsgKeyMsgRoaming] = 1;
setting[kNIMMsgKeySetMsgOffline] = 1;
setting[kNIMMsgKeyHistorySave] = 1;
...

//通过srcMsg生成一个新的消息。
int64_t timeNow = 1520500638234;//当前UNIX时间戳 毫秒
char* sessionid = "1222222";
char* clientMsgID = "uuid2";//生成新的唯一uuid;
NIMSessionType sessionType = kNIMSessionTypeTeam;
char* newMsg = nim_talk_create_retweet_msg(srcMsg,clientMsgID,sessionType,sessionid,fw.write(setting),timeNow);

//发送消息
nim_talk_send_msg(newMsg,0,0,0);

free(newMsg);//需要释放内存;

消息撤回

用户通过发送消息发的消息或者群主、管理员可以通过该接口执行撤回操作(不支持聊天室消息),撤回操作一般有时限限制(该限制为全局的APP设置),超过限制返回508。 开发者通过注册撤回消息通知回调,接收其他端的撤回消息的通知,收到通知后SDK会标记主动在消息历史中标记该条消息为删除状态,同时开发者根据自身需求,删除界面上显示的消息,甚至插入一条提示,IM Demo有开发示例。

RecallNotification参数说明

类型 参数 说明
NIMSessionType kNIMRecallMsgKeyToType 会话类型 0:点对点消息 1 :群消息
string kNIMRecallMsgKeyFromAccID 消息发送方ID
string kNIMRecallMsgKeyToAccID 消息接收方ID
string kNIMRecallMsgKeyMsgId 消息唯一id
string kNIMRecallMsgKeyNotify 自定义通知文案
int64_t kNIMRecallMsgKeyTime 撤回操作的时间戳(毫秒)
NIMMessageFeature kNIMRecallMsgKeyNotifyFeature 撤回消息的类型,详见NIMMessageFeature
bool kNIMRecallMsgKeyMsgExist 撤回的消息本地是否存在,比如对方离线时发一条消息又撤回,对方上线收到离线撤回通知该tag为false
int64_t kNIMRecallMsgKeyMsgTime 要撤回的消息的时间戳(毫秒)(毫秒)
string kNIMRecallMsgKeyMsgFromNick 要撤回消息的发送者昵称

RecallNotification解析示例

void ParseRecallNotification(Json::Value value)
{
    if (value.isObject())
    {
        //解析为RecallMsgNotify
        char* from_id = value[kNIMRecallMsgKeyFromAccID].asString();
        char* to_id = value[kNIMRecallMsgKeyToAccID].asString();
        char* msg_id = value[kNIMRecallMsgKeyMsgId].asString();
        char* operator_id = value[kNIMRecallMsgKeyOpeAccID].asString();
        char* notify = value[kNIMRecallMsgKeyNotify].asString();
        NIMSessionType session_type = (NIMSessionType)value[kNIMRecallMsgKeyToType].asInt();
        int64_t notify_timetag = value[kNIMRecallMsgKeyTime].asUInt64();
        NIMMessageFeature notify_feature = (NIMMessageFeature)value[kNIMRecallMsgKeyNotifyFeature].asInt();
        bool msglog_exist = value[kNIMRecallMsgKeyMsgExist].asBool();
        int64_t msglog_timetag = value[kNIMRecallMsgKeyMsgTime].asUInt64();
        char* from_nick = value[kNIMRecallMsgKeyMsgFromNick].asString();
            ...
        ...
    }
    ...
}

主动撤回消息

撤回已发送成功的消息,此功能依赖本地历史记录,需要通过消息id查询本地消息记录,如果无法从本地找到消息记录,将无法撤回。

void nim_talk_recall_msg(const char *json_msg, const char *notify, const char *json_extension, nim_talk_recall_msg_func cb, const void *user_data);
参数 说明
json_msg 需要撤回的消息,详见IMMessage,只用到了kNIMMsgKeyClientMsgid
notify 自定义通知
cb 撤回消息的回调通知
json_extension 通知扩展,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_talk_recall_msg_func(int rescode, 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 count = values.size();
        for (int i = 0; i < count; i++)
        {
            //解析为RecallNotification,参考ParseRecallNotification
            ParseRecallNotification(values[i]);
        }
        ...
    }
}
//自己组装,目前是通过msgId撤回,
Json::FastWriter fw;
Json::Value assembleMsg;
assembleMsg[kNIMMsgKeyClientMsgid]  = "撤回消息的uuid"; //目前只用到了消息id;
nim_talk_recall_msg(fw.write(assembleMsg),"这是一条撤回通知" , 0,my_nim_talk_recall_msg_func,0);

消息撤回的通知

通知用户消息已被撤回,该通知支持离线。

void nim_talk_reg_recall_msg_cb(const char *json_extension, nim_talk_recall_msg_func cb, const void *user_data);
参数 说明
cb 消息撤回的通知的回调
json_extension 通知扩展,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
//监听事件
nim_talk_reg_recall_msg_cb(0,my_nim_talk_recall_msg_func,0);

//取消监听
nim_talk_reg_recall_msg_cb(0,0,0);

已读回执

网易云通信提供点对点消息的已读回执。注意:此功能仅对 P2P 消息中有效。

在会话界面中调用发送已读回执的接口并传入最后一条消息,即表示这之前的消息都已读,对端将收到此回执。

发送消息已读回执的一般场景:

1. 进入 P2P 聊天界面(如果没有收到新的消息,反复进入调用发送已读回执接口, SDK 会自动过滤,只会发送一次给网易云通信服务器)。

2. 处于聊天界面中,收到当前会话新消息时。

发送已读回执

void nim_msglog_send_receipt_async(const char *json_msg, const char *json_extension, nim_msglog_status_changed_cb_func cb, const void *user_data);
参数 说明
json_msg 收到的消息内容,json字符串,字段定义详见IMMessage
cb 发送消息已读会之后,消息状态变化的回调通知,结果解析查看全局消息状态变更通知
json_extension 通知扩展,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_msglog_status_changed_cb_func(int res_code, const char *result, const char *json_extension, const void *user_data)
{
    //result:参考全局消息状态变更通知
    ...
}
//假设 msg为需要发送已读回执的消息。
nim_msglog_send_receipt_async(msg,0,my_nim_msglog_status_changed_cb_func,0);

监听已读回执通知

已读回执也是消息状态的变化,可查阅全局消息状态变更通知

监听全员广播通知

接收全员广播通知。分单个通知和批量全员广播通知,一般而言,批量通知是登陆时下发的离线广播、同步广播、漫游广播通知等。

BroadcastMessage广播通知字段说明

类型 参数 说明
int64_t kNIMBroadcastMsgKeyID 通知消息id
string kNIMBroadcastMsgKeyFromAccid 发送者账号,可能为空
int64_t kNIMBroadcastMsgKeyTime 通知消息UNIX时间戳,毫秒
string kNIMBroadcastMsgKeyBody 通知内容

1. 单条全员广播通知 接收广播消息回调 , 建议全局注册,统一接受回调后分发消息到具体的会话。

 void nim_talk_reg_receive_broadcast_cb(const char *json_extension, nim_talk_receive_broadcast_cb_func cb, const void *user_data);
参数 说明
cb 通知的回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_talk_receive_broadcast_cb_func(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.size();
        for (int i = 0; i < count; i++)
        {
            //解析为BroadcastMessage定义内容
            char* body = values[kNIMBroadcastMsgKeyBody].asString();
            char* from_id = values[kNIMBroadcastMsgKeyFromAccid].asString();
            int64_t id = values[kNIMBroadcastMsgKeyID].asUInt64();
            int64_t time = values[kNIMBroadcastMsgKeyTime].asUInt64();
            ...
        }
        ...
    }
...
}
//监听事件
nim_talk_reg_receive_broadcast_cb(0,nim_talk_reg_receive_broadcast_cb,0);
//取消监听
nim_talk_reg_receive_broadcast_cb(0,0,0);

2. 批量全员广播通知

接收批量广播消息回调。如果在注册了接收消息回调的同时也注册了该批量接口,当有批量消息时,会改走这个接口通知应用层,例如登录后接收到的离线消息等。

nim_talk_reg_receive_broadcast_msgs_cb(const char *json_extension, nim_talk_receive_broadcast_cb_func cb, const void *user_data);
参数 说明
cb 批量消息的回调
json_extension 扩展字段,预留
user_data APP的自定义用户数据,SDK只负责传回给回调函数,不做任何处理
void my_nim_talk_receive_broadcasts_cb_func(const char *result, const char *json_extension, const void *user_data)
{
    //处理广播通知,此为多条广播集合
    Json::Value values;
    Json::Reader reader;
    if (reader.parse(result, values) && values.isArray())
    {
        int count = values.size();
        for (int i = 0; i < count; i++)
        {
            Json::Value value = values[i];
            //解析为BroadcastMessage定义内容
            char* body = value[kNIMBroadcastMsgKeyBody].asString();
            char* from_id = value[kNIMBroadcastMsgKeyFromAccid].asString();
            int64_t id = value[kNIMBroadcastMsgKeyID].asUInt64();
            int64_t time = value[kNIMBroadcastMsgKeyTime].asUInt64();
            ...
        }
        ...
    }
}
//监听事件
nim_talk_reg_receive_broadcast_msgs_cb(0,my_nim_talk_receive_broadcasts_cb_func,0)
//取消监听
nim_talk_reg_receive_broadcast_msgs_cb(0,0,0)

从消息附件中获取本地路径

从消息的中获取附件(图片、语音、视频等)的本地路径。如果预下载的是缩略图,且没下载过原图,此获得的路径文件可能不存在,需要开发者调用nim_nos_download_media去下载。如果全局设置预加载的是缩略图,则开发者若想下载原图,在传入消息内容前,先将kNIMMsgKeyLocalFilePath字段设为空或者自定义的保存路径。

char *nim_talk_get_attachment_path_from_msg(const char *json_msg);
参数 说明
msg 所要获取的消息内容,详见IMMessage
//假设msg为需要获取的消息
char* filePath = nim_talk_get_attachment_path_from_msg(msg);

//下载原图
Json::FastWriter fw;
Json::Reader reader;
Json::Value message;
if (reader.parse(msg, message))
{
    message[kNIMMsgKeyLocalFilePath] = "";//此处置空 或者设置为自定义的保存路径;
}
nim_nos_download_media(fw.write(message),0,0,0,0);

free(filePath);//需要开发者释放内存

获取图片缩略图

网易云通信SDK目前默认收到图片消息后会提前下载原图缓存到本地,如果开发者想控制下载图片的质量,可以通过初始化SDK时设置kNIMPreloadImageQuality来控制图片质量,设置kNIMPreloadImageResize来控制图片长宽, IM Demo开发范例中默认下载原图,所以开发者如果想基于IM Demo工程源码开发,需要在图片预览环节或者其他需要显示原图的地方自行下载原图。

以下但不限于以下场景下开发者可以自行下载缩略图:

目前SDK提供两种获取缩略图方案:

目前IM Demo工程在消息显示图片的时候对图片进行了压缩处理,开发者可以参考bubble_image.cpp