tencent cloud

文档反馈

Android&iOS&Windows&Mac

最后更新时间:2023-07-17 11:12:28

    功能描述

    拉取历史消息的 API 在类 V2TIMManagerV2TIMManager+Message(iOS & Mac) / V2TIMMessageManager(Android & Windows) 中。
    除了支持单聊、群聊历史消息的拉取外,还提供了高级接口以支持按指定方向拉取、按指定起点和指定时间范围拉取。
    除了支持单独拉取本地历史消息外,还支持拉取云端历史消息。
    说明
    在拉取云端历史消息时,如果检测到网络异常,SDK 会返回本地存储的历史消息。
    本地存储的历史消息无时间限制,但云端存储的历史消息有存储时长的限制:
    开发版:免费存储 7 天,不支持延长。
    标准版:免费存储 7 天,支持延长。
    进阶版:免费存储 30 天,支持延长。
    说明
    延长历史消息存储时长是增值服务,如需延长历史消息存储时长,请联系我们
    富媒体消息(图片、文件、语音等)对应的文件存储时长,与历史消息存储时长保持一致。

    拉取单聊历史消息

    您可以调用接口 getC2CHistoryMessageList (Android / 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);
    }];

    拉取群聊历史消息

    您可以调用接口 getGroupHistoryMessageList (Android / iOS & Mac) 获取群聊历史消息。 在网络正常的情况下会拉取最新的云端数据。如果网络出现异常,SDK 会返回本地存储的历史消息。
    如果您仅仅想拉取本地历史消息,可以参考 高级接口 。 本接口支持分页拉取,参考:分页拉取
    注意
    只有会议群(Meeting)才能拉取到进群前的历史消息,更多关于群消息的限制,详见 消息能力差异
    直播群(AVChatRoom)消息不存云端漫游和本地数据库,调用此接口无效。进阶版客户可以在 即时通信 IM 控制台 配置 “直播群新成员查看入群前消息量”,开启后会在加入直播群成功后,在 onRecvNewMessage 回调中获得入群前消息。最多支持新入群成员查看入群前 24h 产生的消息,最多可查看 20 条。控制台配置详见 直播群新成员查看入群前消息配置
    示例代码如下:
    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);
    }];

    高级功能

    高级接口

    如果以上的普通接口无法满足您对拉取历史消息的需求,我们还提供了高级接口 getHistoryMessageList (Android / 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. 只支持本地拉取,即当 getTypeV2TIM_GET_LOCAL_OLDER_MSGV2TIM_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. 如果同时指定了 lastMsglastMsgSeq,SDK 优先使用 lastMsg
    4. 如果均未指定 lastMsglastMsgSeq,拉取的起点取决于是否设置 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 定义一些常见的消息类型,例如文本、图片、视频等,参考 V2TIMElemType(Android / 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_CLOUD_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_CLOUD_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_CLOUD_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