聊天室消息管理
更新时间: 2024/03/14 16:36:34
聊天室消息收发
聊天室消息 ChatRoomMessage 继承自 IMMessage。新增了以下方法:
返回值 | ChatRoomMessage 接口 | 说明 |
---|---|---|
java.lang.String | getNotifyTargetTags | 获取消息目标的标签表达式 |
CustomChatRoomMessageConfig | getChatRoomConfig() | 获取聊天室消息配置 |
ChatRoomMessageExtension | getChatRoomMessageExtension() | 获取聊天室消息扩展属性 |
boolean | isHighPriorityMessage() | 是否是高优先级消息 |
void | setLocX(Double locX) | 设置坐标X,用于聊天室空间消息 |
void | setLocY(Double locY) | 设置坐标Y,用于聊天室空间消息 |
void | setLocZ(Double locZ) | 设置坐标Z,用于聊天室空间消息 |
void | setToAccounts(List |
设置消息接收者账户列表,用于聊天室定向消息,最多 100 个用户 |
- 为保证用户体验(如避免服务器过载),目前针对消息接收,有两套流控机制。第一套针对普通消息,聊天室用户每秒至多可接收20条,超过部分会因为流控随机丢弃。第二套针对高优先级消息,每秒至多接收10条,超过部分无法保证不丢失。
- 为避免丢失重要消息(通常为服务端消息),可将发送聊天室消息的 HighPriority 参数设置为 true 实现高优先级接收服务端消息,进而保证高优先级消息流控上限内(每秒10条)的重要消息不丢失。详情请参见发送聊天室消息中的 HighPriority 参数说明。
发送聊天室消息
先通过 ChatRoomMessageBuilder 提供的接口创建消息对象,然后调用 ChatRoomService 的 sendMessage 接口发送出去即可。
在聊天室发送自定义消息时,强烈建议将消息内容传入attach
字段
- ChatRoomMessageBuilder 接口说明
返回值 | ChatRoomMessageBuilder 接口 | 说明 |
---|---|---|
static ChatRoomMessage | createChatRoomAudioMessage(String roomId, File file, long duration) | 创建一条音频消息 |
static ChatRoomMessage | createChatRoomAudioMessage(String roomId, File file, long duration, String nosTokenSceneKey) | 创建一条音频消息并指定文件资源场景 |
static ChatRoomMessage | createChatRoomCustomMessage(String roomId, MsgAttachment attachment) | 创建自定义消息 |
static ChatRoomMessage | createChatRoomCustomMessage(String roomId, MsgAttachment attachment, String nosTokenSceneKey) | 创建自定义消息并指定文件资源场景 |
static ChatRoomMessage | createChatRoomFileMessage(String roomId, File file, String displayName) | 创建一条文件消息 |
static ChatRoomMessage | createChatRoomFileMessage(String roomId, File file, String displayName, String nosTokenSceneKey) | 创建一条文件消息并指定文件资源场景 |
static ChatRoomMessage | createChatRoomImageMessage(String roomId, File file, String displayName) | 创建一条图片消息 |
static ChatRoomMessage | createChatRoomImageMessage(String roomId, File file, String displayName, String nosTokenSceneKey) | 创建一条图片消息并指定文件资源场景 |
static ChatRoomMessage | createChatRoomLocationMessage(String roomId, double lat, double lng, String addr) | 创建一条地理位置信息 |
static ChatRoomMessage | createChatRoomTextMessage(String roomId, String text) | 创建普通文本消息 |
static ChatRoomMessage | createChatRoomVideoMessage(String roomId, File file, long duration, int width, int height, String displayName) | 创建一条视频消息 |
static ChatRoomMessage | createChatRoomVideoMessage(String roomId, File file, long duration, int width, int height, String displayName, String nosTokenSceneKey) | 创建一条视频消息并指定文件资源场景 |
static ChatRoomMessage | createEmptyChatRoomMessage(String roomId, long time) | 创建一条空消息,仅设置了房间ID以及时间点,用于记录查询 |
static ChatRoomMessage | createTipMessage(String roomId) | 创建一条提醒消息 |
static ChatRoomMessage | createChatRoomSpatialLocationTextMessage(String roomId, String text,Double x,Double y,Double z) | 创建带位置信息的消息 |
nosTokenSceneKey 详见 NOS 资源场景。
下面以文本消息发送为例,其它类型的消息发送方式与IM单聊群聊类似。
- API 原型
java/**
* 创建普通文本消息
*
* @param roomId 聊天室ID
* @param text 文本消息内容
* @return ChatRoomMessage 生成的聊天室消息对象
*/
public static ChatRoomMessage createChatRoomTextMessage(String roomId, String text);
/**
* 发送消息
*
* @param msg 带发送的消息体,由{@link ChatRoomMessageBuilder}构造。
* @param resend 如果是发送失败后重发,标记为true,否则填false。
* @return InvocationFuture 可以设置回调函数。消息发送完成后才会调用,如果出错,会有具体的错误代码。
*/
InvocationFuture<Void> sendMessage(ChatRoomMessage msg, boolean resend);
- 示例
java// 示例用roomId
String roomId = "50";
// 文本消息内容
String text = "这是聊天室文本消息";
// 创建聊天室文本消息
ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomTextMessage(roomId, text);
// 将文本消息发送出去
NIMClient.getService(ChatRoomService.class).sendMessage(message, false)
.setCallback(new RequestCallback<Void>() {
@Override
public void onSuccess(Void param) {
// 成功
}
@Override
public void onFailed(int code) {
// 失败
}
@Override
public void onException(Throwable exception) {
// 错误
}
});
- 特殊错误码
错误码 | 说明 |
---|---|
13004 | 在禁言列表中,不允许发言 |
13006 | 聊天室处于整体禁言状态,只有管理员能发言 |
发送消息配置选项
发送聊天室消息时,可以设置配置选项 CustomChatRoomMessageConfig
,主要用于设置是否存入云端历史记录。
CustomChatRoomMessageConfig 属性 | 说明 |
---|---|
skipHistory | 该消息是否要保存到服务器, 如果为true,通过ChatRoomService#pullMessageHistory 拉取的结果将不包含该条消息。 默认为false。 |
- 示例
java// 示例用roomId
String roomId = "50";
// 文本消息内容
String text = "这是聊天室文本消息";
// 创建聊天室文本消息
ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomTextMessage(roomId, text);
// 配置不存历史记录
CustomChatRoomMessageConfig config = new CustomChatRoomMessageConfig();
config.skipHistory = true;
message.setChatRoomConfig(config);
// 发送聊天室消息
NIMClient.getService(ChatRoomService.class).sendMessage(message, false);
发送带位置信息的消息
支持聊天室空间消息
SDK 在 8.11.0 中新增了空间消息能力,用于在部分基于空间坐标的场景下给指定范围内的用户发送消息,如某游戏地图内指定范围的区域。要使用空间消息能力,您首先需要开启空间消息开关SDKOptions#enableChatRoomLocation
,在加入聊天室时,可以预设一个坐标位置来加入房间,并且可以订阅接收多少距离内的消息。
- 示例
java// roomId 表示聊天室ID
EnterChatRoomData data = new EnterChatRoomData(roomId);
//确定用户地理位置并设置接收消息的有效距离
ChatRoomSpatialLocation location = new ChatRoomSpatialLocation(100.0, 100.0, 100.0,200.0);
data.setChatRoomSpatialLocation(location);
// 以登录一次不重试为例
NIMClient.getService(ChatRoomService.class).enterChatRoomEx(data, 1).setCallback(new RequestCallback<EnterChatRoomResultData>() {
@Override
public void onSuccess(EnterChatRoomResultData result) {
// 登录成功
}
@Override
public void onFailed(int code) {
// 登录失败
}
@Override
public void onException(Throwable exception) {
// 错误
}
});
更新位置信息
java/**
* 更新位置信息
* 注意:每300ms只能上报一次位置信息给服务器,300ms 内多次调用返回 416
* @param roomId 当前聊天室id
* @param location 当前地理位置和接收消息的有效距离
* @return
*/
InvocationFuture<Void> updateLocation(String roomId, ChatRoomSpatialLocation location);
ChatRoomSpatialLocation 参数说明:
参数 | 说明 |
---|---|
x | 坐标x |
y | 坐标y |
z | 坐标z |
distance | 订阅的消息的距离 |
空间坐标 X、Y、Z 主要用于确定当前用户的位置,距离(distance)是指在基于空间坐标(用户位置)给接收指定距离范围内的消息。
发送地理位置消息
发送聊天室消息时,给消息设置坐标位置:
- 示例
java// 示例用roomId
String roomId = "50";
// 文本消息内容
String text = "这是聊天室文本消息";
Double locationX = 100.0;
Double locationY = 100.0;
Double locationZ = 100.0;
ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomSpatialLocationTextMessage(roomId,text,locationX,locationY,locationZ);
// 发送聊天室消息
NIMClient.getService(ChatRoomService.class).sendMessage(message, false);
发送定向消息
传统聊天室场景一个人发送的消息将广播给所有人或设定的某个标签下所有人(聊天室 SDK 8.4.0 新增的聊天室标签功能)。但在某些场景下,我希望该消息仅发送给聊天室的指定人而不是所有,您可以使用聊天室定向消息能力。
定向消息不存离线,无法查询历史消息,即当发送定向消息时,接收者离线,后续重新连接后也获取不到该消息。
要发送一个定向消息,您可以在发送消息时指定接收消息的用户列表,最多指定 100 个用户:
- 示例
java// 示例用roomId
String roomId = "50";
// 文本消息内容
String text = "这是聊天室文本消息";
// 创建聊天室文本消息
ChatRoomMessage message = ChatRoomMessageBuilder.createChatRoomTextMessage(roomId, text);
//设置定向发送的账户列表
List<String> accountList = new ArrayList<>();
accountList.add("test1");
accountList.add("test2");
message.setToAccounts(accountList);
// 发送聊天室消息
NIMClient.getService(ChatRoomService.class).sendMessage(message, false);
接收聊天室消息
通过添加消息接收观察者,在有新消息到达时,就可以接收到通知。
- API 原型
java/**
* 注册/注销消息接收观察者。
*
* @param observer 观察者,参数为收到的消息集合
* @param register true为注册,false为注销
*/
public void observeReceiveMessage(Observer<List<ChatRoomMessage>> observer, boolean register);
- 示例
javaObserver<List<ChatRoomMessage>> incomingChatRoomMsg = new Observer<List<ChatRoomMessage>>() {
@Override
public void onEvent(List<ChatRoomMessage> messages) {
// 处理新收到的消息
}
};
NIMClient.getService(ChatRoomServiceObserver.class).observeReceiveMessage(incomingChatRoomMsg, register);
- 附件的下载,请使用
ChatRoomService
的downloadAttachment
方法进行下载。 - 注册/注销消息状态变化观察者,请使用
ChatRoomServiceObserver
的observeMsgStatus(Observer<ChatRoomMessage> observer, boolean register)
。 - 注册/注销消息附件上传/下载进度观察者,请使用
ChatRoomServiceObserver
的observeAttachmentProgress(Observer<AttachmentProgress> observer, boolean register)
。
聊天室通知消息
在聊天室中进行部分操作会产生聊天室通知消息。目前当出现以下事件,会产生通知消息:
NotificationType | 说明 |
---|---|
ChatRoomClose | 聊天室被关闭了 |
ChatRoomCommonAdd | 成员设定为固定成员 |
ChatRoomCommonRemove | 成员取消固定成员 |
ChatRoomInfoUpdated | 聊天室信息被更新了 |
ChatRoomManagerAdd | 设置为管理员 |
ChatRoomManagerRemove | 取消管理员 |
ChatRoomMemberBlackAdd | 成员被加黑 |
ChatRoomMemberBlackRemove | 成员被取消黑名单 |
ChatRoomMemberExit | 成员离开聊天室 |
ChatRoomMemberIn | 成员进入聊天室 |
ChatRoomMemberKicked | 成员被踢了 |
ChatRoomMemberMuteAdd | 成员被设置禁言 |
ChatRoomMemberTempMuteAdd | 新增临时禁言 |
ChatRoomMemberTempMuteRemove | 主动解除临时禁言 |
ChatRoomMyRoomRoleUpdated | 成员主动更新了聊天室内的角色信息(仅指nick/avator/ext) |
ChatRoomQueueBatchChange | 队列批量变更 |
ChatRoomQueueChange | 队列中有变更 |
ChatRoomRoomDeMuted | 聊天室解除全体禁言状态 |
ChatRoomRoomMuted | 聊天室被禁言了,只有管理员可以发言,其他人都处于禁言状态 |
ChatRoomRecall | 聊天室消息撤回 |
ChatRoomQueueBatchAdd | 批量添加聊天室队列元素 |
ChatRoomTagsUpdate | 更新标签 |
特别地,支持设置成员进出聊天室通知是否下发:
- 应用级别:网易云信控制台 > 选择应用 > 聊天室用户进出消息系统下发 > 开启/关闭。
- 单个聊天室:调用服务端API「关闭指定聊天室进出通知」。
- 如果希望查询聊天室消息历史时,也不要包含聊天室用户进出消息,请联系商务顾问申请关闭「聊天室用户进出消息历史存储」。
所有的聊天室通知都以消息 ChatRoomMessage 的形式封装。聊天室通知的解析如下:
聊天室通知解析步骤:
- 通过 ChatRoomMessage.getMsgType() 获取 消息类型,若为 MsgTypeEnum.notification ,则为聊天室通知消息。
- 将 ChatRoomMessage.getAttachment() 获取的附件对象强类型转换为 NotificationAttachment。
- 通过 NotificationAttachment.getType() 获取具体的 NotificationType 。
- 根据对应的 NotificationType 将 ChatRoomMessage.getAttachment() 得到的附件对象强转为对应的 附件类(ChatRoomNotificationAttachment或其子类)。
- 如果是NotificationType是ChatRoomRecall,可以将附件强转为ChatRoomRecallAttachment,通过其getMsgUuid()方法得到被撤回消息的id,从而找到对应消息并进行相应处理。
ChatRoomNotificationAttachment 参数说明:
方法 | 说明 |
---|---|
getExtension() | 获取聊天室通知扩展字段 |
getOperator() | 获取该操作的发起者的账号 |
getOperatorNick() | 获取该操作的发起者的昵称 |
getTargets() | 获取该操作的承受者的账号列表 |
getTargetNicks() | 获取该操作的承受者的昵称列表 |
ChatRoomRecallAttachment 参数说明:
方法 | 说明 |
---|---|
getMsgTime() | 获取被撤回消息的时间 |
getMsgUuid() | 获取被撤回消息的uuid,可根据此id找到需要撤回的消息 |
示例:
javapublic static String getNotificationText(ChatRoomNotificationAttachment attachment) {
if (attachment == null) {
return "";
}
String targets = getTargetNicks(attachment);
String text;
switch (attachment.getType()) {
case ChatRoomMemberIn:
text = buildText("欢迎", targets, "进入直播间");
break;
case ChatRoomMemberExit:
text = buildText(targets, "离开了直播间");
break;
case ChatRoomMemberBlackAdd:
text = buildText(targets, "被管理员拉入黑名单");
break;
case ChatRoomMemberBlackRemove:
text = buildText(targets, "被管理员解除拉黑");
break;
case ChatRoomMemberMuteAdd:
text = buildText(targets, "被管理员禁言");
break;
case ChatRoomMemberMuteRemove:
text = buildText(targets, "被管理员解除禁言");
break;
case ChatRoomManagerAdd:
text = buildText(targets, "被任命管理员身份");
break;
case ChatRoomManagerRemove:
text = buildText(targets, "被解除管理员身份");
break;
case ChatRoomCommonAdd:
text = buildText(targets, "被设为普通成员");
break;
case ChatRoomCommonRemove:
text = buildText(targets, "被取消普通成员");
break;
case ChatRoomClose:
text = buildText("直播间被关闭");
break;
case ChatRoomInfoUpdated:
text = buildText("直播间信息已更新");
break;
case ChatRoomMemberKicked:
text = buildText(targets, "被踢出直播间");
break;
case ChatRoomMemberTempMuteAdd:
text = buildText(targets, "被临时禁言");
break;
case ChatRoomMemberTempMuteRemove:
text = buildText(targets, "被解除临时禁言");
break;
case ChatRoomMyRoomRoleUpdated:
text = buildText(targets, "更新了自己的角色信息");
break;
case ChatRoomQueueChange:
text = buildText(targets, "麦序队列中有变更");
break;
case ChatRoomRoomMuted:
text = buildText("全体禁言,管理员可发言");
break;
case ChatRoomRoomDeMuted:
text = buildText("解除全体禁言");
break;
case ChatRoomQueueBatchChange:
text = buildText("批量变更");
break;
default:
text = attachment.toString();
break;
}
return text;
}
设置聊天室消息扩展字段
聊天室消息ChatRoomMessage
继承自IMMessage
,通过setRemoteExtension
方法设置聊天室消息的服务端扩展字段。服务端扩展字段只能在消息发送前设置,会同步到其他端。
- 聊天室消息没有客户端扩展字段。
- 扩展字段,请使用JSON格式封装,并传入非格式化的JSON字符串,最大长度1024字节。
查询云端历史消息
聊天室没有离线消息和漫游消息。可以通过下面的接口查询聊天室消息历史。服务器只保存最近10天的聊天室消息记录。但是10天之前发送的文件(例如:图片、音频、视频等),其url链接地址仍然是有效的(不过开发者需要自行保存这些url,因为无法通过已过期的消息来查询这些文件url)。如需延长「聊天室历史消息天数」,请联系商务顾问。
查询云端历史消息
以 startTime(单位毫秒)为查询起点,选择查询方向往前或者往后拉取 limit 条消息。拉取到的消息中也包含聊天室通知消息。
查询结果排序与查询方向有关,若方向往前,则结果排序按时间逆序,反之则结果排序按时间顺序。
java/**
* 获取历史消息,可选择给定时间往前或者往后查询,若方向往前,则结果排序按时间逆序,反之则结果排序按时间顺序。
*
* @return InvocationFuture 可以设置回调函数。回调中返回历史消息列表
*/
InvocationFuture<List<ChatRoomMessage>> pullMessageHistoryEx(String roomId, long startTime, int limit, QueryDirectionEnum direction);
- 参数说明
参数 | 说明 |
---|---|
roomId | 聊天室 id |
startTime | 时间戳,单位毫秒 |
limit | 可拉取的消息数量,最多100条 |
direction | 查询方向 |
QueryDirectionEnum 属性说明
QueryDirectionEnum 属性 | 说明 |
---|---|
QUERY_OLD | 查询比锚点时间更早的消息 |
QUERY_NEW | 查询比锚点时间更晚的消息 |
- 示例
javalong startTime = System.currentTimeMillis();
// 从现在开始,往 QueryDirectionEnum.QUERY_OLD 查询100条
NIMClient.getService(ChatRoomService.class).pullMessageHistoryEx(roomId, startTime, 100, QueryDirectionEnum.QUERY_OLD);
按消息类型查询
以 startTime(单位毫秒)为时间戳,选择查询方向,指定一种或多种类型的消息,往前或者往后拉取 limit 条消息。
- API 原型
java/**
* 获取历史消息,可选择给定时间往前或者往后查询,以及查询指定一种或多种类型的消息。
*
* 若方向往前,则结果排序按时间逆序,反之则结果排序按时间顺序
*
* 消息类型仅支持 0:文本,1:图片,2:语音,3:视频,4:地理位置,5:通知,6:文件,10:提示,11:Robot,100:自定义,其它为非法参数
*
* @param roomId 聊天室id
* @param startTime 时间戳,单位毫秒
* @param limit 可拉取的消息数量
* @param direction 查询方向
* @param typeEnums 消息类型,数组
* @return InvocationFuture 可以设置回调函数。回调中返回历史消息列表
*/
InvocationFuture<List<ChatRoomMessage>> pullMessageHistoryExType(String roomId, long startTime, int limit, QueryDirectionEnum direction, MsgTypeEnum[] typeEnums);
- 参数说明
参数 | 说明 |
---|---|
roomId | 聊天室 id |
startTime | 时间戳,单位毫秒 |
limit | 可拉取的消息数量 |
direction | 查询方向 |
typeEnums | 查询消息类型,数组 |
- 示例
javaMsgTypeEnum[] typeEnums = new MsgTypeEnum[]{MsgTypeEnum.text, MsgTypeEnum.image};
int[] types = new int[]{MsgTypeEnum.text.getValue(), MsgTypeEnum.image.getValue()};
long anchorTime = System.currentTimeMillis();
checkResponse(NIMClient.getService(ChatRoomService.class).pullMessageHistoryExType(Constants.CHATROOM_ID, anchorTime, 50, QueryDirectionEnum.QUERY_OLD, typeEnums), new TestRequestResult.Callback<List<ChatRoomMessage>>() {
@Override
public boolean onResponseData(int code, List<ChatRoomMessage> data) {
...
}
});
根据标签查询历史消息
根据标签(Tags)在云端查询聊天室的历史消息。
以 fromTime 和 toTime(单位毫秒)为时间戳,选择查询方向,指定一种或多种标签和消息类型,往前或者往后拉取 limit 条消息。
- API 原型
java/**
* 通过标签从云端拉取消息
* @param param 参数
* @return InvocationFuture 可以设置回调函数。回调中返回历史消息列表
*/
InvocationFuture<List<ChatRoomMessage>> getMessagesByTags(GetMessagesByTagsParam param);
- 参数说明
参数 | 类型 | 说明 |
---|---|---|
roomId | long | 聊天室 ID(必填) |
tags | List<String> | 标签列表,支持传入多个标签同时查询(必填) |
types | List<MsgTypeEnum > |
消息类型列表,查询指定消息类型的消息,默认查询全部消息类型 |
fromTime | Long | 起始时间,单位毫秒 |
toTime | Long | 结束时间,单位毫秒 |
limit | Integer | 可查询的最大消息数量 |
reverse | Boolean | 查询方向 |
- 示例代码
javaNIMClient.getService(ChatRoomService.class).getMessagesByTags(param).setCallback(new RequestCallback<List<ChatRoomMessage>>() {
@Override
public void onSuccess(List<ChatRoomMessage> result) {
// 获取消息成功
}
@Override
public void onFailed(int code) {
// 获取消息失败
}
@Override
public void onException(Throwable exception) {
// 获取消息出现异常
}
});