本文档提供消息相关的类型和接口使用说明。

客户端

API 接口详细文档参看 Android API 参考、iOS API 参考、Web API 参考、微信小程序 API 参考。

消息类型

BIMMessage 为 IMSDK 的消息内容承载类,在使用 IMSDK 的过程中会频繁的使用该类。
IMSDK 支持如下消息:

消息分类消息类型说明
文本消息BIM_MESSAGE_TYPE_TEXT普通文本消息
图片消息BIM_MESSAGE_TYPE_IMAGE图片消息,含原始图,缩略图
视频消息BIM_MESSAGE_TYPE_VIDEO视频文件以及视频封面图,最大不超过 50M
语音消息BIM_MESSAGE_TYPE_AUDIO语音文件,最大不超过 50M
文件消息BIM_MESSAGE_TYPE_FILE文件消息,最大不超过 50M
自定义消息BIM_MESSAGE_TYPE_CUSTOM开发者自定义字符串发送,IMSDK 透传
创建消息
创建文本消息

使用 BIMClient 中的 createTextMessage 方法创建文本消息。


BIMMessage textMessage = BIMClient.getInstance().createTextMessage("消息内容");
java

BIMMessage *textMessage = [[BIMClient sharedInstance] createTextMessage:@"消息内容"];
objectivec
创建图片消息

使用 BIMClient 中的 createImageMessage 方法创建图片消息,其中 path 为当前发送图片文件的本地路径。


BIMMessage imageMessage = BIMClient.getInstance().createImageMessage(path);
java

BIMMessage *imageMessage = [[BIMClient sharedInstance] createImageMessage:path];
objectivec
创建语音消息

使用 BIMClient 中的 createAudioMessage 方法创建语音消息,其中 path 为当前语音文件的本地路径。


BIMMessage audioMessage = BIMClient.getInstance().createAudioMessage(path);
java

BIMMessage *audioMessage = [[BIMClient sharedInstance] createAudioMessage:path duration:duration];
objectivec
创建视频消息

使用 BIMClient 中的 createVideoMessage 方法创建视频消息,其中 path 为当前视频文件的本地路径。


BIMMessage videoMessage = BIMClient.getInstance().createVideoMessage(path);
java

BIMMessage *videoMessage = [[BIMClient sharedInstance] createVideoMessage:path];
objectivec
创建文件消息

使用 BIMClient 中的 createFileMessage 方法创建文件消息,其中 path 为当前文件的本地路径,uri 为当前文件本地 uri,path 和 uri 可以二选一使用(iOS 只有 path),推荐优先使用 path。


/**
 * 创建文件消息
 * @param uri      文件uri
 * @param path     文件路径
 * @param fileName 文件名称
 * @param length   文件大小
 * @return
 */
 BIMMessage fileMessage = BIMClient.getInstance().createFileMessage(uri, path, fileName, length);
java

BIMMessage *fileMessage = [[BIMClient sharedInstance] createFileMessage:path fileName:fileName];
objectivec
创建自定义消息

使用 BIMClient 中的 createCustomMessage 方法创建文件消息,其中 data 参数为自定义消息内容,通常为 json 格式数据。


/**
 * 创建自定义消息
 * @param data 自定义消息内容
 * @return
 */
BIMMessage customMessage = BIMClient.getInstance().createCustomMessage(data);
java

BIMMessage *customMessage = [[BIMClient sharedInstance] createCustomMessage:data];
objectivec
发送消息

发送消息的方法在 BIMClient 中,使用 sendMessage 接口可实现,示例代码如下。


/**
 * @param message
 * @param conversationId 会话id
 * @param callback       回调
 */
BIMClient.getInstance().sendMessage(msg, conversationId, new BIMSendCallback() {

    @Override
    public void onAdd(BIMMessage message) {
        //媒体消息回调,方便媒体消息上屏
    }

    @Override
    public void onProgress(BIMMessage message, int progress) {
        //媒体消息回调,上传进度
    }

    @Override
    public void onSaved(BIMMessage bimMessage) {
       //媒体消息回调,消息已经入库
    }

    @Override
    public void onSuccess(BIMMessage bimMessage) {
       //发送成功
    }

    @Override
    public void onAsync(BIMMessage bimMessage, boolean isUpdate) {
        //发送风控回调
    }

    @Override
    public void onError(BIMMessage bimMessage, int code, String desc) {
        //发送失败
    }
})
java

//发送消息
[[BIMClient sharedInstance] sendMessage:sendMessage conversationId:self.conversation.conversationID saved:nil completion:^(BIMMessage * _Nonnull message, BIMError * _Nullable error) {
        
}];
objectivec
接收消息

使用 BIMClient 中的 addMessageListener 设置消息监听,可通过 bimMessage.getMsgType() 获取消息类型属性。


BIMClient.getInstance().addMessageListener(new BIMMessageListener() {
    @Override
    public void onReceiveMessage(BIMMessage bimMessage) {
        //收到消息回调
    }

    @Override
    public void onSendMessage(BIMMessage bimMessage) {
        //本地发出消息回调
    }

    @Override
    public void onDeleteMessage(BIMMessage bimMessage) {
        //删除消息回调
    }

    @Override
    public void onRecallMessage(BIMMessage bimMessage) {
        //撤回消息回调
    }

    @Override
    public void onUpdateMessage(BIMMessage bimMessage) {
        //消息更新回调
    }

    @Override
    public void onReceiveMessagesReadReceipt(List<BIMMessageReadReceipt> receiptList) {
        //收到消息已读回执回调
    }
});
java

[[BIMClient sharedInstance] addMessageListener:<#(nonnull id<BIMMessageListener>)#>];

/// 收到新消息
- (void)onReceiveMessage:(BIMMessage *)message {
    
}

/// 收到消息被删除
- (void)onDeleteMessage:(NSString *)msgID {

}

/// 收到消息撤回
- (void)onRecallMessage:(BIMMessage *)message {
    
}

/// 消息被修改(内容+扩展)
- (void)onUpdateMessage:(BIMMessage *)message {
    
}

/// 发送消息入库完成
- (void)onSendMessage:(BIMMessage *)message {
    
}

/// 收到消息已读回执
- (void)onReceiveMessagesReadReceipt:(NSArray<BIMMessageReadReceipt *> *)receiptList;
{

}
objectivec
已读回执

版本 v1.11.0 以上单聊支持消息和会话已读回执。消息已读回执是指消息发送后,接收方查看消息后可以发送自己已读给发送端。会话已读回执是指接收方可以标记整个会话消息已读。

消息是否已读

是否(消息接收方)已发送或(消息发送方)已收到消息已读回执,可通过 BIMMessage 的 isReadAck 方法获取。


public boolean isReadAck();
java

@property (nonatomic, assign, readonly) BOOL isReadAck;
objectivec
主动拉取消息已读回执信息

从其他界面进入会话页面时,完成消息拉取后可主动拉取消息已读回执信息。


// 进入会话拉取消息
BIMClient.getInstance().getNewerMessageList(conversationId, option, new BIMResultCallback<BIMMessageListResult>() {
    @Override
    public void onSuccess(BIMMessageListResult bimMessageListResult) {
        // ...
        // 历史消息
        List<BIMMessage> messageList = bimMessageListResult.getMessageList();
        
        // 过滤已读消息
        List<BIMMessage> needQueryMsgList = new ArrayList<>();
        for (BIMMessage bimMessage: messageList) {
            // 已读消息不再查询
            if (!bimMessage.isReadAck()) {
                needQueryMsgList.add(bimMessage);
            }
        }
        // 获取消息已读回执
        BIMClient.getInstance().getMessagesReadReceipt(needQueryMsgList, new BIMResultCallback<List<BIMMessageReadReceipt>>() {
            @Override
            public void onSuccess(List<BIMMessageReadReceipt> messageReadReceipts) {
                // 请求成功,刷新UI
            }
        
            @Override
            public void onFailed(BIMErrorCode code) {
                // 请求失败
            }
        });
    }

    @Override
    public void onFailed(BIMErrorCode code) {
        // 获取历史消息失败
    }
});
java

@weakify(self);
[[BIMClient sharedInstance] getHistoryMessageList:self.conversation.conversationID option:option completion:^(NSArray<BIMMessage *> * _Nullable messages, BOOL hasMore, BIMMessage * _Nullable earliestMessage, BIMError * _Nullable error) {
    @strongify(self);
    // 不是单聊会话不用拉已读回执
    if (self.conversation.conversationType != BIM_CONVERSATION_TYPE_ONE_CHAT) {
        return;
    }
    NSMutableArray<BIMMessage *> *needGetReceiptMessages = [NSMutableArray array];
    [messages enumerateObjectsUsingBlock:^(BIMMessage * _Nonnull message, NSUInteger idx, BOOL * _Nonnull stop) {
        // 已读的或者不是自己发的消息,也不用拉已读回执
        if (message.isReadAck || message.senderUID != [[BIMClient sharedInstance] getCurrentUserID].longLongValue) {
            return;
        }
        [needGetReceiptMessages addObject:message];
    }];
    if (BTD_isEmptyArray(needGetReceiptMessages)) {
        return;
    }
    [[BIMClient sharedInstance] getMessagesReadReceipt:[needGetReceiptMessages copy] completion:^(NSArray<BIMMessageReadReceipt *> * _Nullable receiptList, BIMError * _Nullable error) {}];
}];
objectivec
发送消息已读回执

在会话页面,接收到消息时,根据消息类型发送消息已读回执。


// 假设bimMessage已被用户查看
public void sendMessageAck(BIMMessage bimMessage) {
    if (!bimMessage.isSelf() && !bimMessage.isReadAck()) {
        // 语音和视频消息需要点开才发送已读回执,可以根据需求调整。
        if (bimMessage.getMsgType() == BIMMessageType.BIM_MESSAGE_TYPE_AUDIO
            || bimMessage.getMsgType() == BIMMessageType.BIM_MESSAGE_TYPE_VIDEO) {
            return;    
        }
    
        List<BIMMessage> messageList = new ArrayList<>();
        messageList.add(bimMessage);
        BIMClient.getInstance().sendMessageReadReceipts(bimMessage, new BIMSimpleCallback() {
            @Override
            public void onSuccess() {
                // 发送成功
            }

            @Override
            public void onFailed(BIMErrorCode code) {
                // 发送失败
            }
        });
    }
}
java

if (message.senderUID == [BIMClient sharedInstance].getCurrentUserID.longLongValue) {
    return;
}
if (!message.serverMessageID || message.isReadAck || self.conversation.conversationType != BIM_CONVERSATION_TYPE_ONE_CHAT) {
    return;
}
// 语音和视频消息需要点开才发送已读回执,可以根据需求调整。
if (message.msgType == BIM_MESSAGE_TYPE_VIDEO || message.msgType == BIM_MESSAGE_TYPE_AUDIO) {
    return;
}
[[BIMClient sharedInstance] sendMessageReadReceipts:@[message] completion:^(BIMError * _Nullable error) {}];
objectivec
收到消息已读回执通知

使用 BIMClient 中的 addMessageListener 设置消息已读回执监听。


BIMClient.getInstance().addMessageListener(new BIMMessageListener() {
    // ... 其他回调
    
    @Override
    public void onReceiveMessagesReadReceipt(List<BIMMessageReadReceipt> receiptList) {
        // 收到消息已读回执回调
    }
});
java

[[BIMClient sharedInstance] addMessageListener:listener];

/// 收到消息已读回执
- (void)onReceiveMessagesReadReceipt:(NSArray<BIMMessageReadReceipt *> *)receiptList;
{
    [receiptList enumerateObjectsUsingBlock:^(BIMMessageReadReceipt * _Nonnull receipt, NSUInteger idx, BOOL * _Nonnull stop) {
        // 收到消息已读回执回调
    }];
}
objectivec
发送会话已读回执

进入会话页面,可通过发送会话已读回执标记会话所有消息已读。


// 会话已读回执仅支持单聊
if (bimConversation.getConversationType() == BIMConversationType.BIM_CONVERSATION_TYPE_ONE_CHAT) {
    BIMClient.getInstance().markConversationMessagesRead(bimConversation.getConversationID(), new BIMSimpleCallback() {
        @Override
        public void onSuccess() {
            // 发送成功
        }
    
        @Override
        public void onFailed(BIMErrorCode code) {
            // 发送失败
        }
    });
}
java

// 会话已读回执仅支持单聊
if (self.conversation.conversationType == BIM_CONVERSATION_TYPE_ONE_CHAT) {
    [[BIMClient sharedInstance] markConversationMessagesRead:self.conversation.conversationID completion:^(BIMError * _Nullable error) {}];
}
objectivec
收到会话已读回执通知

使用 BIMClient 中的 addConversationListener 设置消息已读回执监听。


BIMClient.getInstance().addConversationListener(new BIMConversationListListener() {
    // ... 其他回调
    
    @Override
    public void onConversationRead(String conversationId, long fromUid) {
        //收到会话已读回执回调,刷新UI
    }
});
java

[[BIMClient sharedInstance] addConversationListener:listener];

//收到会话已读回执
- (void)onConversationRead:(NSString *)conversationId fromUid:(long long)uid
{
    dispatch_async(dispatch_get_main_queue(), ^{
        //收到会话已读回执回调,刷新UI
    });
}
objectivec
服务端

当你需要通过调用服务端接口 SendMessage 或 UserBroadcast 接口向客户端发送消息时,你需要传入 MsgType 和 Content 来构建一条信息。
你需要将消息内容按照以下 Json 格式进行构建,并将 Json 内容转换成 String 格式后传入 SendMessage.Content 中。

文字消息
MsgType

MsgType = 10001

Content
{
    "text":"文字消息" // 文本
}
Json
图片消息
MsgType

MsgType = 10003

Content
{
    "__files":{//媒体列表
        "media":{//媒体信息
            "displayType":"media",//固定值为 media
            "mime":"image/jpeg",//mimetype 格式
            "length":5313,//文件大小,单位为 b
            "fileName":"Your_file.jpeg",//文件名称
            "type":"jpeg",//文件类型
            "ext":{
                "s:file_ext_key_source_app_id":"000000",    //AppId
                "s:file_ext_key_file_name":"Your_file.jpeg",//文件名称
                "s:file_ext_key_original_height":"200",    //原图高
                "s:file_ext_key_original_width":"100",    //原图宽
                "s:file_ext_key_thumb_height":"100",      //缩略图高
                "s:file_ext_key_thumb_width":"50", //缩略图宽
                "s:file_ext_key_preview_width":"100",//中图宽
                "s:file_ext_key_preview_height":"200",//中图宽
                "s:file_ext_key_preview_url":"https://xxx.xxx",//中图url
                "s:file_ext_key_thumb_url":"https://xxx.xxx.xxx"//缩略图url
            },
            "remoteURL":"https://xxx.xxx.xxxxx"//原图url
        }
    }
}
Json
视频消息
MsgType

MsgType = 10004

Content
{
    "__files":{//媒体列表
        "media":{//媒体信息
            "displayType":"media",//固定值为 media
            "mime":"video/mp4",//mimetype 格式
            "length":13494185,//文件大小,单位为 b
            "fileName":"Your_file.mp4",//文件名称
            "type":"mp4",//文件类型
            "ext":{
                "s:file_ext_key_source_app_id":"000000",//AppId
                "s:file_ext_key_file_name":"Your_file.mp4",//文件名称
                "s:file_ext_key_video_duration":"10",//视频时长,单位为 s。
                "s:file_ext_key_video_height":"200",//视频高,单位为 px。
                "s:file_ext_key_video_width":"100",//视频宽,单位为 px。
                "s:file_ext_key_video_cover_url":"https://xxx.xxx"//封面url
            },
            //视频url
            "remoteURL":"https://xxx.xxx"
        }
    }
}
Json
文件消息
MsgType

MsgType = 10005

Content
{
    "__files":{//媒体列表
        "media":{//媒体信息
            "displayType":"media",//固定值为 media
            "mime":"string",//mimetype 格式
            "length":9410,//文件大小,单位为 b
            "fileName":"Your_file.v",//文件名称
            "type":"v",//文件类型
            "ext":{
                "s:file_ext_key_source_app_id":"000000",//AppId
                "s:file_ext_key_file_name":"Your_file.v"//文件名称
            },
            //文件 url
            "remoteURL":"https://xxx.xxx"
        }
    }
}
Json
语音消息
MsgType

MsgType = 10006

Content
{
    "__files":{//媒体列表
        "media":{//媒体信息
            "displayType":"media",//固定值为 media
            "mime":"audio/*",//mimetype 格式
            "length":328364,//文件大小,单位为 b
            "fileName":"Your_file.wav",//文件名称
            "type":"wav",//文件类型
            "ext":{
                "s:file_ext_key_source_app_id":"000000",//AppId
                "s:file_ext_key_file_name":"Your_file.wav",//文件名称
                "s:file_ext_key_audio_duration":"3.608"//语音时长,单位为 s
            },
            //语音url
            "remoteURL":"xxx.xxx"
        }
    }
}
Json
自定义消息
MsgType

MsgType = 10012

Content

IM 未对自定义消息 Content 字段进行约定,你可以自行构建渲染。