Android&iOS&Windows&Mac

最近更新时间:2024-10-10 10:07:42

我的收藏

功能描述

拉取历史消息的 API 在类 V2TIMManagerV2TIMManager+Message(iOS & Mac) / V2TIMMessageManager(Android & Windows) 中。
除了支持单聊、群聊历史消息的拉取外,还提供了高级接口以支持按指定方向拉取、按指定起点和指定时间范围拉取。
除了支持单独拉取本地历史消息外,还支持拉取云端历史消息。
拉取历史消息接口说明:
如果没有触发登录,调用接口不会返回历史消息。
如果登录失败,调用接口会返回本地历史消息。
如果 SDK 检测到没有网络,调用接口会返回本地历史消息。
如果登录成功且网络正常,调用接口会先请求云端历史消息,然后再和本地历史消息合并后返回。
只有会议群(Meeting)才能拉取到进群前的历史消息,直播群(AVChatRoom)消息不存漫游和本地数据库,调用接口无效。
本地存储的历史消息无时间限制,但云端存储的历史消息有存储时长的限制:
体验版:免费存储 7 天,不支持延长。
专业版:免费存储 7 天,支持延长。
旗舰版:免费存储 30 天,支持延长。
说明:
延长历史消息存储时长是增值服务,您可以登录 即时通信 IM 控制台 修改相关配置,具体计费说明请参加 增值服务详情
富媒体消息(图片、文件、语音等)对应的文件存储时长,与历史消息存储时长保持一致。

拉取单聊历史消息

您可以调用接口 getC2CHistoryMessageListAndroid / iOS & Mac)获取单聊历史消息。 在网络正常的情况下会拉取最新的云端数据。如果网络出现异常,SDK 会返回本地存储的历史消息。
如果您仅仅想拉取本地历史消息,请参见 高级接口 。 本接口支持分页拉取,请参见 分页拉取
示例代码如下:
Android
iOS & Mac
// 拉取单聊历史消息
// 首次拉取,lastMsg 设置为 null
// 再次拉取时,lastMsg 可以使用返回的消息列表中的最后一条消息
V2TIMManager.getMessageManager().getC2CHistoryMessageList(#your user id#, 20, null, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onError(int code, String desc) {
Log.i("imsdk", "fail, " + code + ", " + desc);
}

@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
// 记录下次拉取的 lastMsg, 用于下次拉取
V2TIMMessage lastMsg = v2TIMMessages.get(v2TIMMessages.size() - 1);
Log.i("imsdk", "success");
}
});
// 拉取单聊历史消息
// 首次拉取,lastMsg 设置为 nil
// 再次拉取时,lastMsg 可以使用返回的消息列表中的最后一条消息
[V2TIMManager.sharedInstance getC2CHistoryMessageList:#your user id# count:20 lastMsg:nil succ:^(NSArray<V2TIMMessage *> *msgs) {
// 记录下次拉取的 lastMsg,用于下次拉取
V2TIMMessage *lastMsg = msgs.lastObject;
NSLog(@"success, %@", msgs);
} fail:^(int code, NSString *desc) {
NSLog(@"fail, %d, %@", code, desc);
}];

拉取群聊历史消息

您可以调用接口 getGroupHistoryMessageListAndroid / iOS & Mac)获取群聊历史消息。 在网络正常的情况下会拉取最新的云端数据。如果网络出现异常,SDK 会返回本地存储的历史消息。
如果您仅仅想拉取本地历史消息,请参见 高级接口 。 本接口支持分页拉取,请参见 分页拉取
注意
只有会议群(Meeting)才能拉取到进群前的历史消息,更多关于群消息的限制,详情请参见 消息能力差异
直播群(AVChatRoom)消息不存云端漫游和本地数据库,调用此接口无效。旗舰版客户可以在 即时通信 IM 控制台 配置 “直播群新成员查看入群前消息量”,开启后会在加入直播群成功后,在 onRecvNewMessage 回调中获得入群前消息。最多支持新入群成员查看入群前 24h 产生的消息,最多可查看 50 条。控制台配置请参见 直播群新成员查看入群前消息配置
示例代码如下:
Android
iOS & Mac
// 拉取群聊历史消息
// 首次拉取,lastMsg 设置为 null
// 再次拉取时,lastMsg 可以使用返回的消息列表中的最后一条消息
V2TIMManager.getMessageManager().getGroupHistoryMessageList(#your group id#, 20, null, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onError(int code, String desc) {
Log.i("imsdk", "fail, " + code + ", " + desc);
}

@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
// 记录下次拉取的 lastMsg,用于下次拉取
V2TIMMessage lastMsg = v2TIMMessages.get(v2TIMMessages.size() - 1);
Log.i("imsdk", "success");
}
});
// 拉取群聊历史消息
// 首次拉取,lastMsg 设置为 null
// 再次拉取时,lastMsg 可以使用返回的消息列表中的最后一条消息
[V2TIMManager.sharedInstance getGroupHistoryMessageList:#your group id# count:20 lastMsg:nil succ:^(NSArray<V2TIMMessage *> *msgs) {
// 记录下次拉取的 lastMsg,用于下次拉取
V2TIMMessage *lastMsg = msgs.lastObject;
NSLog(@"success, %@", msgs);
} fail:^(int code, NSString *desc) {
NSLog(@"fail, %d, %@", code, desc);
}];

高级功能

高级接口

如果以上的普通接口无法满足您对拉取历史消息的需求,我们还提供了高级接口 getHistoryMessageListAndroid / iOS & Mac / Windows)。
该接口除了支持普通拉取单聊、群聊历史消息外,还支持以下高级特性:
支持设置消息拉取时的起点。
支持设置拉取消息的时间范围。
支持设置拉取消息的位置:从本地拉取、从云端拉取。
支持按照指定的方向拉取:往消息时间更老的方向拉取、往消息时间更新的方向拉取。
支持拉取本地指定的消息类型:文本、图片、语音、视频、文件、表情、群 tips 消息、合并消息、自定义消息等。
接口原型:
Android
iOS & Mac
Windows
public abstract void getHistoryMessageList(V2TIMMessageListGetOption option, V2TIMValueCallback<List<V2TIMMessage>> callback);
- (void)getHistoryMessageList:(V2TIMMessageListGetOption *)option
succ:(V2TIMMessageListSucc)succ
fail:(V2TIMFail)fail;
virtual void GetHistoryMessageList(const V2TIMMessageListGetOption& option,
V2TIMValueCallback<V2TIMMessageVector>* callback) = 0;
V2TIMMessageListGetOption 类参数说明:
参数
含义
单聊有效
群聊有效
是否必填
说明
getType
拉取消息的位置及方向,可以设置拉取 本地/云端更老/更新 的消息
YES
YES
YES
当设置从云端拉取时,会将本地存储消息列表与云端存储消息列表合并后返回。如果无网络,则直接返回本地消息列表。
userID
拉取指定用户的单聊历史消息
YES
NO
NO
拉取单聊消息,需要指定对方的 userID,此时 groupID 传空即可。
groupID
拉取指定群组的群聊历史消息
NO
YES
NO
拉取群聊消息,需要指定群聊的 groupID,此时 userID 传空即可。
count
单次拉取的消息数量
YES
YES
YES
建议设置为 20,否则可能影响拉取速度
messageTypeList
拉取的消息类型集合
YES
YES
NO
1. 只支持本地拉取,即当 getType 为 V2TIM_GET_LOCAL_OLDER_MSG 或 V2TIM_GET_LOCAL_NEWER_MSG 时有效。
2. 如果该字段为空,表示拉取所有的消息类型。
3. 支持的消息类型详见 V2TIMElemType (Android / iOS & Mac / Windows)。
lastMsg
最后一条消息
YES
YES
NO
可用于拉取历史消息的场景。
1. 单聊和群聊中均能使用。
2. 设置 lastMsg 作为拉取的起点,返回的消息列表中不包含这条消息。
3. 如果设置为空,则使用会话的最新一条消息作为拉取起点。
lastMsgSeq
最后一条消息的 seq
NO
YES
NO
可用于拉取历史消息或消息定位等场景。
1. 仅能在群聊中使用该字段。
2. 设置 lastMsgSeq 作为拉取的起点,返回的消息列表中包含这条消息。
3. 如果同时指定了 lastMsg 和 lastMsgSeq,SDK 优先使用 lastMsg。
4. 如果均未指定 lastMsg 和 lastMsgSeq,拉取的起点取决于是否设置 getTimeBegin。设置了,则使用设置的范围作为起点;未设置,则使用最新消息作为起点。
getTimeBegin
拉取消息的时间起点。UTC 时间戳,单位:秒
YES
YES
NO
默认为 0,表示从当前时间开始拉取。
getTimePeriod
拉取消息的时间范围。单位:秒
YES
YES
NO
1. 默认为 0,表示不限制时间范围。
2. 取值的范围区间为闭区间,包含起止时间,二者关系如下:
如果 getType 指定了朝消息时间更老的方向拉取,则时间范围表示为 [getTimeBegin - getTimePeriod, getTimeBegin]。
如果 getType 指定了朝消息时间更新的方向拉取,则时间范围表示为 [getTimeBegin, getTimeBegin + getTimePeriod]。

分页拉取

上述拉取单聊历史消息、群聊历史消息,及高级接口均可按照相同的方式实现分页,即使用 lastMsgcount 来实现:
1. 首次拉取,设置 lastMsg 为空,此时 SDK 会拉取到最新的消息。
2. 非首次拉取,使用上一次拉取到的消息列表中最后一条消息作为本次拉取的 lastMsg,拉取下一页数据。此时消息列表返回的消息不包含设置的 lastMsg。
3. 如果成功回调中返回的消息列表为空,表示拉取完毕,没有更多数据了。
说明:
1. 拉取到的消息列表中,越新的消息越靠前。
2. 考虑到加载效率、网络省流,建议分页时 count 设置为 20。
如果您使用 lastMsgSeq 拉取历史消息,返回的消息列表会包含lastMsgSeq 所对应的消息。因此,非首次拉取群聊历史消息(也就是续拉)时,建议不要使用 lastMsgSeq,否则可能出现同一条消息被重复拉到的情况。
例如,现在的历史消息有 8 条,分别是:msg1、msg2、msg3、msg4、msg5、msg6、msg7、msg8。每次拉取 4 条,首次拉取得到了 msg1、msg2、msg3、msg4,此时再用 msg4 的 lastMsgSeq 续拉,会拉到消息 msg4、msg5、msg6、msg7。两次拉取中,msg4 被重复拉取了。 如果您一定要使用 lastMsgSeq 续拉,建议处理好消息去重的逻辑。

按照时间范围拉取

您可以通过设置 getTimeBegingetTimePeriod 来拉取指定的时间范围内的消息。 如下图所示,时间范围的起止时间戳与 getType 有关。



示例代码将演示:从 2022-01-01 00:00:00 开始(时间戳是 1640966400),往过去的方向,从云端拉取一整天的群聊消息。
Android
iOS & Mac
Windows
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // 拉取云端的更老的消息
option.setGetTimeBegin(1640966400); // 从 2022-01-01 00:00:00 开始
option.setGetTimePeriod(1 * 24 * 60 * 60); // 拉取一整天的消息
option.setCount(Integer.MAX_VALUE); // 返回时间范围内所有的消息
option.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
option.getType = V2TIM_GET_CLOUD_OLDER_MSG; // 拉取云端的更老的消息
option.getTimeBegin = 1640966400; // 从 2022-01-01 00:00:00 开始
option.getTimePeriod = 1 * 24 * 60 * 60; // 拉取一整天的消息
option.count = INT_MAX; // 返回时间范围内所有的消息
option.groupID = #your group id#; // 拉取群聊消息
[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMMessageListGetOption option;
option.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_OLDER_MSG; // 拉取云端的更老的消息
option.getTimeBegin = 1640966400; // 从 2022-01-01 00:00:00 开始
option.getTimePeriod = 1 * 24 * 60 * 60; // 拉取一整天的消息
option.count = std::numeric_limits<uint64_t>::max(); // 返回时间范围内所有的消息
option.groupID = "your group id"; // 拉取群聊消息

auto callback = new ValueCallback<V2TIMMessageVector>{};
callback->SetCallback(
[=](const V2TIMMessageVector& messageList) {
std::cout << "success" << std::endl;
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(option, callback);

在时间范围内分页拉取

您可以同时指定拉取的时间范围和 lastMsg/lastMsgSeq。此时 SDK 的表现是:
1. 如果用户同时设置了 getTimeBegin/getTimePeriodlastMsg/lastMsgSeq,结果集可理解成:「单独按起始消息拉取的结果」与「单独按时间范围拉取的结果」 取交集。
2. 如果用户都没设置 getTimeBegin/getTimePeriodlastMsg/lastMsgSeq,结果集可理解成:从当前会话最新的一条消息开始,按照 getType 所指定的方向和拉取方式拉取。
示例代码将演示:从 2022-01-01 00:00:00 开始(时间戳是 1640966400),往过去的方向,每页 20 条,分页地从云端拉取一整天的群聊消息。
Android
iOS & Mac
Windows
// 定义变量,记录每次拉取的游标
private V2TIMMessage m_lastMsg = null; // 首次拉取时为 null

// 分页拉取逻辑
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // 拉取云端的更老的消息
option.setGetTimeBegin(1640966400); // 从 2022-01-01 00:00:00 开始
option.setGetTimePeriod(1 * 24 * 60 * 60); // 拉取一整天的消息
option.setCount(20); // 每页 20 条
option.setLastMsg(m_lastMsg); // 上次拉取的位置 (每次返回的消息列表的最后一条消息)
option.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
Log.i("imsdk", "success");
// 记录下一次拉取的 lastMsg
m_lastMsg = v2TIMMessages.get(v2TIMMessages.size() - 1);
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
// 定义变量,记录每次拉取的游标
@property (nonatomic, copy) V2TIMMessage *lastMsg;

// 分页拉取逻辑
V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
option.getType = V2TIM_GET_CLOUD_OLDER_MSG; // 拉取云端的更老的消息
option.getTimeBegin = 1640966400; // 从 2022-01-01 00:00:00 开始
option.getTimePeriod = 1 * 24 * 60 * 60; // 拉取一整天的消息
option.count = 20; // 每页 20 条
option.lastMsg = self.lastMsg; // 上次拉取的位置 (每次返回的消息列表的最后一条消息)
option.groupID = #your group id#; // 拉取群聊消息
__weak typeof(self) weakSelf = self;
[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {
NSLog(@"success");
// 记录下一次拉取的 lastMsg
weakSelf.lastMsg = msgs.lastObject;
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// 定义变量,记录每次拉取的游标
V2TIMMessage lastMsg;

// 分页拉取逻辑
V2TIMMessageListGetOption option;
option.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_OLDER_MSG; // 拉取云端的更老的消息
option.getTimeBegin = 1640966400; // 从 2022-01-01 00:00:00 开始
option.getTimePeriod = 1 * 24 * 60 * 60; // 拉取一整天的消息
option.count = 20; // 每页 20 条
option.lastMsg = 首次拉取 ? nullptr : &lastMsg; // 上次拉取的位置(每次返回的消息列表的最后一条消息)
option.groupID = "your group id"; // 拉取群聊消息

auto callback = new ValueCallback<V2TIMMessageVector>{};
callback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
std::cout << "success" << std::endl;
// 记录下一次拉取的 lastMsg
lastMsg = messageList[messageList.Size() - 1];
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(option, callback);

仅拉取本地消息

通过设置 getType 来实现仅拉取本地消息:
getType 取值为 V2TIM_GET_LOCAL_OLDER_MSG 时,表示往时间更旧的方向,拉取本地存储的消息。
getType 取值为 V2TIM_GET_LOCAL_NEWER_MSG 时,表示往时间更新的方向,拉取本地存储的消息。
示例代码将演示:从最新的消息开始,往更老的方向,从本地数据库中拉取 20 条单聊消息。
Android
iOS & Mac
Windows
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_LOCAL_OLDER_MSG); // 拉取本地的更老的消息
option.setLastMsg(null); // 设置从最新的消息开始拉取
option.setCount(20); // 拉取 20 条消息
option.setUserID(#you user id#); // 拉取单聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
option.getType = V2TIM_GET_LOCAL_OLDER_MSG; // 拉取本地的更老的消息
option.lastMsg = nil; // 设置从最新的消息开始拉取
option.count = 20; // 拉取 20 条消息
option.userID = #your user id#; // 拉取单聊消息
[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMMessageListGetOption option;
option.getType = V2TIMMessageGetType::V2TIM_GET_LOCAL_OLDER_MSG; // 拉取本地的更老的消息
option.count = 20; // 拉取 20 条消息
option.userID = "you user id"; // 拉取单聊消息

auto callback = new ValueCallback<V2TIMMessageVector>{};
callback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
std::cout << "success" << std::endl;
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(option, callback);

拉取指定类型的消息

SDK 定义一些常见的消息类型,例如文本、图片、视频等,参考 V2TIMElemTypeAndroid / iOS & Mac / Windows)。高级接口 getHistoryMessageList 支持通过设置 messageTypeList,拉取指定类型的消息。
注意:
1. messageTypeList 为空时,表示拉取所有类型的消息。
2. 拉取指定的消息类型,只支持从本地拉取。从云端拉取消息不支持指定消息类型。
示例代码将演示:从当前开始,往过去的方向,拉取 20 条文本和图片消息。
Android
iOS & Mac
Windows
// 拉取图片消息、文本消息
ArrayList<Integer> messageTypeList = new ArrayList<Integer>();
messageTypeList.add(V2TIM_ELEM_TYPE_IMAGE);
messageTypeList.add(V2TIM_ELEM_TYPE_TEXT);

V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_LOCAL_OLDER_MSG); // 拉取本地的更老的消息
option.setCount(20);
option.setMessageTypeList(messageTypeList);
option.setGroupID("you group id");
V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
option.getType = V2TIM_GET_LOCAL_OLDER_MSG;
// 拉取图片消息、文本消息
option.messageTypeList = @[@(V2TIM_ELEM_TYPE_IMAGE), @(V2TIM_ELEM_TYPE_TEXT)];
option.count = 20;
option.groupID = @"your group id";
[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMMessageListGetOption option;
option.getType = V2TIMMessageGetType::V2TIM_GET_LOCAL_OLDER_MSG; // 拉取本地的更老的消息
option.count = 20; // 拉取 20 条消息
option.messageTypeList.PushBack(V2TIMElemType::V2TIM_ELEM_TYPE_IMAGE); // 拉取图片消息
option.messageTypeList.PushBack(V2TIMElemType::V2TIM_ELEM_TYPE_TEXT); // 拉取文本消息
option.userID = "you group id"; // 拉取群聊消息

auto callback = new ValueCallback<V2TIMMessageVector>{};
callback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
std::cout << "success" << std::endl;
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(option, callback);

拉取指定 sequence 的消息

在拉取群聊历史消息时,您可以按照指定的消息序列号 sequence 拉取。
说明
仅拉取群组历史消息时有效。
消息序列号 seq 可以通过 V2TIMMessage 对象的 seq 字段获取。
当 getType 设置为从云端拉取时,会将本地存储消息列表与云端存储消息列表合并后返回;如果无网络,则直接返回本地消息列表。
当 getType 设置为从本地拉取时,直接返回本地的消息列表。
当 getType 设置为拉取更旧的消息时,消息列表按照时间逆序,也即消息按照时间戳从大往小的顺序排序。
当 getType 设置为拉取更新的消息时,消息列表按照时间顺序,也即消息按照时间戳从小往大的顺序排序。
示例代码将演示:在群组中,从云端拉取消息 sequence 为 1,3,5,9 的消息,并将消息按照时间逆序返回。
Android
iOS & Mac
Windows
ArrayList<Long> sequenceList = new ArrayList<>();
sequenceList.add(1L);
sequenceList.add(3L);
sequenceList.add(5L);
sequenceList.add(9L);
V2TIMMessageListGetOption option = new V2TIMMessageListGetOption();
option.setGroupID("your groupID");
option.setMessageSeqList(sequenceList);
option.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG);
V2TIMManager.getMessageManager().getHistoryMessageList(option, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {

}

@Override
public void onError(int code, String desc) {

}
});
V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];
option.getType = V2TIM_GET_CLOUD_OLDER_MSG;
option.groupID = @"your groupID";
option.messageSeqList = @[@(1), @(3), @(5), @(9)];
[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {

} fail:^(int code, NSString *desc) {

}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMUInt64Vector sequence_list;
sequence_list.PushBack(1);
sequence_list.PushBack(3);
sequence_list.PushBack(5);
sequence_list.PushBack(9);
V2TIMMessageListGetOption option;
option.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_OLDER_MSG;
option.messageSeqList = sequence_list;
option.groupID = "your group id";

auto callback = new ValueCallback<V2TIMMessageVector>{};
callback->SetCallback(
[=](const V2TIMMessageVector& messageList) {
std::cout << "success" << std::endl;
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(option, callback);

一键跳转到群 @ 消息

在群聊会话中,收到群 @ 消息后,一般需要通过点击群 @ 提示条,跳转到群 @ 消息的位置,并拉取附近的消息列表用于显示。 由于群 @ 消息本身也需要显示,可以将 lastMsgSeq 设置成群 @ 消息的 sequence ,并使用高级接口 getHistoryMessageList 来拉取。
示例代码将演示:单击群 @ 提示后,跳转到群 @ 消息,并拉取前后各 20 条消息用于展示。
Android
iOS & Mac
Windows
// 获取群 @ 消息对应的的 sequence
long atSequence = 1081;

// 拉取群 @ 消息及之前的消息
V2TIMMessageListGetOption beforeOption = new V2TIMMessageListGetOption();
beforeOption.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // 拉取比群 @ 消息更早的消息
beforeOption.setCount(20); // 拉取 20 条
beforeOption.setLastMsgSeq(atSequence); // 从群 @ 消息开始拉取,包括群 @ 消息
beforeOption.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(beforeOption, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
// 返回的消息列表中包括群 @ 消息
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});

// 拉取群 @ 消息之后的消息
V2TIMMessageListGetOption afterOption = new V2TIMMessageListGetOption();
afterOption.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_NEWER_MSG); // 拉取比群 @ 消息更晚的消息
afterOption.setCount(20); // 拉取 20 条
afterOption.setLastMsgSeq(atSequence + 1); // 从群 @ 消息的后一条消息开始拉取,不包括群 @ 消息
afterOption.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(afterOption, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
// 返回的消息列表中不包括群 @ 消息
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
// 获取群 @ 消息对应的的 sequence
NSInteger atSequence = 1081;

// 拉取群 @ 消息及之前的消息
V2TIMMessageListGetOption *beforeOption = [[V2TIMMessageListGetOption alloc] init];
beforeOption.getType = V2TIM_GET_CLOUD_OLDER_MSG; // 拉取比群 @ 消息更早的消息
beforeOption.count = 20; // 拉取 20 条
beforeOption.lastMsgSeq = atSequence; // 从群 @ 消息开始拉取, 包括群 @ 消息
beforeOption.groupID = #your group id#; // 拉取群聊消息
[V2TIMManager.sharedInstance getHistoryMessageList:beforeOption succ:^(NSArray<V2TIMMessage *> *msgs) {
// 返回的消息列表中包括群 @ 消息
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];

// 拉取群 @ 消息之后的消息
V2TIMMessageListGetOption *afterOption = [[V2TIMMessageListGetOption alloc] init];
afterOption.getType = V2TIM_GET_CLOUD_NEWER_MSG; // 拉取比群 @ 消息更晚的消息
afterOption.count = 20; // 拉取 20 条
afterOption.lastMsgSeq = atSequence + 1; // 从群 @ 消息的后一条消息开始拉取,不包括群 @ 消息
afterOption.groupID = #your group id#; // 拉取群聊消息
[V2TIMManager.sharedInstance getHistoryMessageList:afterOption succ:^(NSArray<V2TIMMessage *> *msgs) {
// 返回的消息列表中不包括群 @ 消息
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// 获取群 @ 消息对应的的 sequence
uint64_t atSequence = 1081;

// 拉取群 @ 消息及之前的消息
V2TIMMessageListGetOption beforeOption;
beforeOption.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_OLDER_MSG; // 拉取比群 @ 消息更早的消息
beforeOption.count = 20; // 拉取 20 条消息
beforeOption.lastMsgSeq = atSequence; // 从群 @ 消息开始拉取,包括群 @ 消息
beforeOption.userID = "you group id"; // 拉取群聊消息

auto beforeCallback = new ValueCallback<V2TIMMessageVector>{};
beforeCallback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
// 返回的消息列表中包括群 @ 消息
std::cout << "success" << std::endl;
delete beforeCallback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete beforeCallback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(beforeOption, beforeCallback);

// 拉取群 @ 消息及之前的消息
V2TIMMessageListGetOption afterOption;
afterOption.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_NEWER_MSG; // 拉取比群 @ 消息更晚的消息
afterOption.count = 20; // 拉取 20 条消息
afterOption.lastMsgSeq = atSequence + 1; // 从群 @ 消息的后一条消息开始拉取,不包括群 @ 消息
afterOption.userID = "you group id"; // 拉取群聊消息

auto afterCallback = new ValueCallback<V2TIMMessageVector>{};
afterCallback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
// 返回的消息列表中不包括群 @ 消息
std::cout << "success" << std::endl;
delete afterCallback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete afterCallback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(afterOption, afterCallback);

搜索场景下的消息定位

当用户通过本地搜索获取到 V2TIMMessage 对象。点击该消息后,一般需要跳转到该消息对应的位置并展示附近的消息。 此时可以将 lastMsg 设置成该消息对象,并使用高级接口 getHistoryMessageList 拉取前后的消息。
示例代码将演示:拉取搜索到的消息前后各 20 条消息,用于展示。
Android
iOS & Mac
Windows
// 获取当前的 message 对象
V2TIMMessage lastMsg = #搜索到的消息#;

// 拉取指定消息之前的消息
V2TIMMessageListGetOption beforeOption = new V2TIMMessageListGetOption();
beforeOption.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_OLDER_MSG); // 拉取比指定消息更早的消息
beforeOption.setCount(20); // 拉取 20 条
beforeOption.setLastMsg(lastMsg); // 从指定消息开始拉取,不包括该消息
beforeOption.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(beforeOption, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
// 返回的消息列表中不包括 lastMsg
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});

// 拉取指定消息之后的消息
V2TIMMessageListGetOption afterOption = new V2TIMMessageListGetOption();
afterOption.setGetType(V2TIMMessageListGetOption.V2TIM_GET_CLOUD_NEWER_MSG); // 拉取比指定消息更晚的消息
afterOption.setCount(20); // 拉取 20 条
afterOption.setLastMsg(lastMsg); // 从指定消息开始拉取,不包括该消息
afterOption.setGroupID(#you group id#); // 拉取群聊消息
V2TIMManager.getMessageManager().getHistoryMessageList(afterOption, new V2TIMValueCallback<List<V2TIMMessage>>() {
@Override
public void onSuccess(List<V2TIMMessage> v2TIMMessages) {
// 返回的消息列表中不包括 lastMsg
Log.i("imsdk", "success");
}

@Override
public void onError(int code, String desc) {
Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
}
});
// 获取当前的 message 对象
V2TIMMessage *lastMsg = #搜索后的消息#;

// 拉取指定消息之前的消息
V2TIMMessageListGetOption *beforeOption = [[V2TIMMessageListGetOption alloc] init];
beforeOption.getType = V2TIM_GET_CLOUD_OLDER_MSG; // 拉取比指定消息更早的消息
beforeOption.count = 20; // 拉取 20 条
beforeOption.lastMsg = lastMsg; // 从指定消息开始拉取, 不包括该消息
beforeOption.groupID = #your group id#; // 拉取群聊消息
[V2TIMManager.sharedInstance getHistoryMessageList:beforeOption succ:^(NSArray<V2TIMMessage *> *msgs) {
// 返回的消息列表中不包括指定消息
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];

// 拉取指定消息之后的消息
V2TIMMessageListGetOption *afterOption = [[V2TIMMessageListGetOption alloc] init];
afterOption.getType = V2TIM_GET_CLOUD_NEWER_MSG; // 拉取比指定消息更晚的消息
afterOption.count = 20; // 拉取 20 条
afterOption.lastMsg = lastMsg; // 从指定消息开始拉取,不包括该消息
afterOption.groupID = #your group id#; // 拉取群聊消息
[V2TIMManager.sharedInstance getHistoryMessageList:afterOption succ:^(NSArray<V2TIMMessage *> *msgs) {
// 返回的消息列表中不包括指定消息
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// 获取当前的 message 对象
V2TIMMessage lastMsg = 搜索到的消息;

// 拉取指定消息之前的消息
V2TIMMessageListGetOption beforeOption;
beforeOption.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_OLDER_MSG; // 拉取比指定消息更早的消息
beforeOption.count = 20; // 拉取 20 条消息
beforeOption.lastMsg = lastMsg; // 从指定消息开始拉取,不包括该消息
beforeOption.userID = "you group id"; // 拉取群聊消息

auto beforeCallback = new ValueCallback<V2TIMMessageVector>{};
beforeCallback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
// 返回的消息列表中不包括 lastMsg
std::cout << "success" << std::endl;
delete beforeCallback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete beforeCallback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(beforeOption, beforeCallback);

// 拉取指定消息之后的消息
V2TIMMessageListGetOption afterOption;
afterOption.getType = V2TIMMessageGetType::V2TIM_GET_CLOUD_NEWER_MSG; // 拉取比指定消息更晚的消息
afterOption.count = 20; // 拉取 20 条消息
afterOption.lastMsg = lastMsg; // 从指定消息开始拉取,不包括该消息
afterOption.userID = "you group id"; // 拉取群聊消息

auto afterCallback = new ValueCallback<V2TIMMessageVector>{};
afterCallback->SetCallback(
[=](const V2TIMMessageVector& messageList) mutable {
// 返回的消息列表中不包括 lastMsg
std::cout << "success" << std::endl;
delete afterCallback;
},
[=](int error_code, const V2TIMString& error_message) {
std::cout << "error" << std::endl;
delete afterCallback;
});

V2TIMManager::GetInstance()->GetMessageManager()->GetHistoryMessageList(afterOption, afterCallback);

解析信令消息

如果您使用了 IM SDK 的信令相关接口(Android / iOS & Mac),调用 invite/inviteInGroup 时,设置了 onlineUserOnly false(Android) / NO(iOS),那么每次信令操作(包括 invitecancelacceptrejecttimeout)都会产生一条自定义消息,该消息会通过 V2TIMAdvancedMsgListeneronRecvNewMessage 回调抛给用户,也可以通过历史消息拉取。
如果您需要根据信令信息做自定义化文本展示,可以使用信令解析接口 getSignalingInfoAndroid / iOS & Mac / Windows)获取信令信息。
接口原型
Android
iOS & Mac
Windows
/**
* 获取信令信息
*
* 如果 invite 设置 onlineUserOnly 为 false,每次信令操作(包括 invite、cancel、accept、reject、timeout)都会产生一条自定义消息,
* 该消息会通过 V2TIMAdvancedMsgListener -> onRecvNewMessage 抛给用户,用户也可以通过历史消息拉取,如果需要根据信令信息做自定义化文本展示,可以调用下面接口获取信令信息。
*
* @param msg 消息对象
* @return V2TIMSignalingInfo 信令信息,如果为 null,则 msg 不是一条信令消息。
*/
public abstract V2TIMSignalingInfo getSignalingInfo(V2TIMMessage msg);
/**
* 获取信令信息
*
* 如果 invite 设置 onlineUserOnly 为 NO,每次信令操作(包括 invite、cancel、accept、reject、timeout)都会产生一条自定义消息,该消息会通过 V2TIMAdvancedMsgListener -> onRecvNewMessage 抛给用户,用户也可以通过历史消息拉取,如果需要根据信令信息做自定义化文本展示,可以调用下面接口获取信令信息。
*
* @param msg 消息对象
* @return V2TIMSignalingInfo 信令信息,如果为 nil,则 msg 不是一条信令消息。
*/
- (V2TIMSignalingInfo *)getSignallingInfo:(V2TIMMessage *)msg;
/**
* 获取信令信息
*
* 如果 Invite 设置 onlineUserOnly 为 false,每次信令操作(包括
* Invite、Cancel、Accept、Reject、Timeout)都会产生一条自定义消息, 该消息会通过
* V2TIMAdvancedMsgListener -> onRecvNewMessage
* 抛给用户,用户也可以通过历史消息拉取,如果需要根据信令信息做自定义化文本展示,可以调用下面接口获取信令信息。
*
* @param msg 消息对象
* @return V2TIMSignalingInfo 信令信息,如果 V2TIMSignalingInfo::inviteID 为空字符串,则 msg 不是一条信令消息。
*/
virtual V2TIMSignalingInfo GetSignalingInfo(const V2TIMMessage& msg) = 0;
示例代码将演示:拉取到历史消息之后,解析信令消息的显示文本。
Android
iOS & Mac
Windows
/// 信令消息对应的自定义文本
public String getCallSignalingContentWithMessage(V2TIMMessage message) {
if (message == null) {
Log.e(TAG, " invalid param ");
return "";
}

V2TIMSignalingInfo signalingInfo = V2TIMManager.getSignalingManager().getSignalingInfo(message);
if (signalingInfo == null) {
Log.e(TAG, " signalingInfo is null ");
return "";
}

String content = "";
Gson gson = new Gson();
Object businessIdObj = null;
String businessId = null;
try {
HashMap signalDataMap = gson.fromJson(signalingInfo.getData(), HashMap.class);
if (signalDataMap != null) {
businessIdObj = signalDataMap.get(TUIConstants.Message.CUSTOM_BUSINESS_ID_KEY);
} else {
Log.e(TAG, " signalDataMap is null ");
return "";
}
} catch (JsonSyntaxException e) {
Log.e(TAG, " get signalingInfoCustomJsonMap error ");
}

if (businessIdObj instanceof String) {
businessId = (String) businessIdObj;
}

if (TextUtils.equals(businessId, "av_call")) {
if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE) {
// 邀请通话
content = "@邀请通话";
} else if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_ACCEPT_INVITE) {
// 同意邀请
content = "@同意通话";
} else {
// 其他
// ...
}
}

return content;
}
/// 信令消息对应的自定义文本
+ (NSString *)getCallSignalingContentWithMessage:(V2TIMMessage *)message
{
V2TIMSignalingInfo *info = [[V2TIMManager sharedInstance] getSignallingInfo:message];
if (!info) {
return nil;
}
// 解析透传的data字段
NSError *err = nil;
NSDictionary *param = nil;
if (info.data != nil) {
param = [NSJSONSerialization JSONObjectWithData:[info.data dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&err];
}
if (!param || ![param isKindOfClass:[NSDictionary class]]) {
return nil;
}

// 判断业务类型
NSArray *allKeys = param.allKeys;
if (![allKeys containsObject:@"businessID"]) {
return nil;
}
NSString *businessId = [param objectForKey:@"businessID"];

// 判断是否为音视频通话信令
NSString *content = nil;
if ([businessId isEqualToString:@"av_call"]) {
if (info.actionType == SignalingActionType_Invite) {
// 邀请通话
content = @"邀请通话";
} else if (info.actionType == SignalingActionType_Accept_Invite) {
// 同意邀请
content = @"同意通话";
} else {
// 其他
// ...
}
}
return content;
}
信令消息对应的自定义文本
std::string GetCallSignalingContentWithMessage(const V2TIMMessage& message) {
V2TIMSignalingInfo signalingInfo =
V2TIMManager::GetInstance()->GetSignalingManager()->GetSignalingInfo(message);
if (signalingInfo.inviteID.Empty()) {
// 如果 V2TIMSignalingInfo::inviteID 为空,则 message 不是一条信令消息
return {};
}

// 解析透传的 data 字段,使用开源库 RapidJSON :https://github.com/Tencent/rapidjson/
rapidjson::Document document;
document.Parse(signalingInfo.data.CString(), signalingInfo.data.Size());
if (!document.HasMember("businessId") || !document["businessId"].IsString()) {
return {};
}
const char* businessId = document["businessId"].GetString();

// 判断是否为音视频通话信令
std::string content;
if (businessId == "av_call") {
if (signalingInfo.actionType == V2TIMSignalingActionType::SignalingActionType_Invite) {
// 邀请通话
content = u8"邀请通话";
} else if (signalingInfo.actionType == 2TIMSignalingActionType::SignalingActionType_Accept_Invite) {
// 同意邀请
content = u8"同意通话";
} else {
// 其他 ...
}
}

return content;
}

常见问题

1. 拉历史消息时,日志中出现 "total count of request cloud message exceed max limit" 信息

SDK 目前的策略是:
1. getType 设置成拉云端历史消息,且拉取 count 条消息时,SDK 会从云端拉取 count 条消息。
2. SDK 过滤无效的消息,例如消息被删除、非当前用户关心的消息等。
3. 当云端历史消息中无效的消息过多,会触发 SDK 多次分页拉取。
为了提供系统的稳定性和健壮性,SDK 最多触发 3 次自动分页。当超过限制后,会出现 “total count of request cloud message exceed max limit” 的日志信息。
为了尽可能的减少此类限频机制对业务层的影响,您可以使用如下措施来减少无效消息的产生:
您可以使用在线消息,即发送消息时设置 onlineUserOnlyYES/true
如果是群聊消息,可以使用群定向消息指定消息的接收者,避免产生无效消息。

2. 拉云端历史消息时,消息 “丢失” ?

getType 设置成拉云端历史消息,且拉取 count 条消息时,SDK 会做如下操作:
1. SDK 先从本地拉取 count 条消息。
2. SDK 再次云端拉取 count 条消息,过滤掉被删除等无效的消息,如果不够 count 条,SDK 内部触发分页拉取。
3. 将本地和云端消息进行合并,更新消息状态等信息。
4. 从合并的消息列表中,返回 count 条消息。
一般出现消息 “丢失” 时,指的是在第 2 步中拉取的无效消息过多,导致触发了问题 1 中的限频机制,从而导致实际拉取的云端消息不够。 建议按照问题 1 中的解决方法来处理,如果仍然无法解决,欢迎加入文末的 QQ 群反馈。

3. 拉取的历史消息,群名片等群成员信息没有实时更新?

SDK 会在消息产生时,更新当前的群名片、role 等群成员信息并存储在本地数据库中。
当拉取群历史消息时,会直接查询消息产生时的群成员信息,不会实时向后台请求更新。
如果您需要获取最新的群成员信息,您可以使用 getGroupMembersInfoAndroid / iOS & Mac / Windows)。

4. 拉取历史消息时卡顿

SDK 内部已对消息拉取做了性能优化,您如果碰到消息卡顿的情况,可以先尝试减少拉取的消息数 count,如果还是不能解决问题,欢迎加入文末的 QQ 群反馈。