# 历史消息 (Beta) (/zh-CN/realtime-media/rtm/build/message-design-and-history/history-message)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```java
PublishOptions options = new PublishOptions();
options.setCustomType("custom type");
options.setStoreInHistory(true);

String channelName = "chatRoom";
String message = "Hello world!";
rtmClient.publish(channelName, message, options, new ResultCallback<Void>() {
    @Override
    public void onSuccess(Void responseInfo) {
        log(CALLBACK, "send message success");
    }

    @Override
    public void onFailure(ErrorInfo errorInfo) {
        log(ERROR, errorInfo.toString());
    }
});
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```java
PublishOptions options = new PublishOptions();
options.setChannelType(RtmChannelType.USER);
options.setCustomType("custom type");
options.setStoreInHistory(true);

String userId = "Tony";
String message = "Hello world!";
rtmClient.publish(userId, message, options, new ResultCallback<Void>() {
    @Override
    public void onSuccess(Void responseInfo) {
        log(CALLBACK, "send message success");
    }

    @Override
    public void onFailure(ErrorInfo errorInfo) {
        log(ERROR, errorInfo.toString());
    }
});
```

## 获取历史消息 [#获取历史消息]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```java
GetHistoryMessagesOptions options = new GetHistoryMessagesOptions();
options.setMessageCount(50);
options.setEnd(1688978391800);

String channelName = "chatRoom";
rtmClient.getHistory().getMessages(channelName, RtmChannelType.MESSAGE, options, new ResultCallback<GetMessagesResult>() {
    @Override
    public void onSuccess(GetMessagesResult result) {
        log(CALLBACK, "get history messages! new start: " + result.getNewStart());
        for (HistoryMessage message : result.getMessageList()) {
            log(INFO, message.toString());
        }
    }

    @Override
    public void onFailure(ErrorInfo errorInfo) {
        log(ERROR, errorInfo.toString());
    }
});
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-1]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-1]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```objc
NSString* message = @"Hello Agora!";
NSString* channel = @"your_channel";

AgoraRtmPublishOptions* publish_option = [[AgoraRtmPublishOptions alloc] init];
publish_option.storeInHistory = true;

[rtm publish:channel message:message option:publish_option completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
    if (errorInfo == nil) {
        NSLog(@"publish success!!");
    } else {
        NSLog(@"publish failed, errorCode %d, reason %@", errorInfo.errorCode, errorInfo.reason);
    }
}];
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```objc
NSString* message = @"Hello Agora!";
NSString* user = @"Tony";

AgoraRtmPublishOptions* publish_option = [[AgoraRtmPublishOptions alloc] init];
publish_option.channelType = AgoraRtmChannelTypeUser;
publish_option.storeInHistory = true;

[rtm publish:user message:message option:publish_option completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
    if (errorInfo == nil) {
        NSLog(@"publish success!!");
    } else {
        NSLog(@"publish failed, errorCode %d, reason %@", errorInfo.errorCode, errorInfo.reason);
    }
}];
```

## 获取历史消息 [#获取历史消息-1]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```objc
AgoraRtmGetHistoryMessagesOptions *option = [[AgoraRtmGetHistoryMessagesOptions alloc] init];
option.messageCount = 50;
option.end = 1688978391800;

[rtmClient getMessages:@"channel_name"
            channelType:AgoraRtmChannelTypeMessage
                options:option
             completion:^(AgoraRtmGetHistoryMessagesResponse *response, NSError *error) {
    if (response != nil) {
        NSLog(@"total message count is: %lu\n\n", (unsigned long)response.messageList.count);

        for (AgoraRtmMessage *msg in response.messageList) {
            NSLog(@"publisher: %@\nmessage content: %@\ntime stamp: %lld\n", msg.publisher, msg.message.stringData, msg.timestamp);
        }

        NSLog(@"new start: %@", response.newStart);
    } else {
        NSLog(@"get history message failed: %@", error.localizedDescription);
    }
}];
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-1]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-1]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-1]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-2]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-2]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```javascript
try {
    const result = await rtm.publish(
        "chatroom",
        "Hello world!",
        {
            channelType:"MESSAGE",
            customType: "STRING",
            storeInHistory:true,            //override default storage options
        }
    );
} catch (status) {
    console.log(status);
}
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```javascript
try {
    const result = await rtm.publish(
        "Tony",                             // User ID
        "Hello world!",
        {
            channelType:"USER",
            customType: "STRING",
            storeInHistory:true,            //override default storage options
        }
    );
} catch (status) {
    console.log(status);
}
```

## 获取历史消息 [#获取历史消息-2]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```javascript
try {
    const result = await rtmClient.history.getMessages(
        "chat_room",
        "MESSAGE",{
        messageCount: 50,
        end: 1688978391800
        });
} catch (status) {
    const { operation, reason, errorCode } = status;
    console.log(`${operation} failed, the error code is ${errorCode}, due to: ${reason}.`);
}
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-2]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-2]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-2]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-3]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-3]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```typescript
import { PublishOptions, RtmChannelType } from '@shengwang/rtm-full';
import { RtmError } from '@shengwang/rtm-full';

const channelName = "chatRoom";
const message = "Hello world!";
const options: PublishOptions = {
  channelType: RtmChannelType.MESSAGE,
  customType: "custom type",
  storeInHistory: true
};

try {
  const response = await rtmClient.publish(channelName, message, options);
  console.log("Publish message success:", response);
} catch (error) {
  console.error("Publish message failed:", error);
  if (error instanceof RtmError) {
    console.error(`Publish failed: ${error.reason} (code: ${error.errorCode})`);
  }
}
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```typescript
import { PublishOptions, RtmChannelType } from '@shengwang/rtm-full';
import { RtmError } from '@shengwang/rtm-full';

const userId = "Tony";
const message = "Hello world!";
const options: PublishOptions = {
  channelType: RtmChannelType.USER,
  customType: "custom type",
  storeInHistory: true
};

try {
  const response = await rtmClient.publish(userId, message, options);
  console.log("Send message to user success:", response);
} catch (error) {
  console.error("Send message to user failed:", error);
  if (error instanceof RtmError) {
    console.error(`Publish failed: ${error.reason} (code: ${error.errorCode})`);
  }
}
```

## 获取历史消息 [#获取历史消息-3]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```typescript
import { RtmChannelType, GetHistoryMessagesOptions } from '@shengwang/rtm-full';
import { RtmError } from '@shengwang/rtm-full';

const channelName = "chatRoom";
const options: GetHistoryMessagesOptions = {
  messageCount: 50,
  end: 1688978391800
};

try {
  const result = await rtmClient.history.getMessages(channelName, RtmChannelType.MESSAGE, options);
  console.log("Get history messages success! new start:", result.newStart);
  console.log("Total messages:", result.messageList.length);

  result.messageList.forEach((message) => {
    console.log(`Publisher: ${message.publisher}, Message: ${message.message}, Timestamp: ${message.timestamp}`);
  });
} catch (error) {
  console.error("Get history messages failed:", error);
  if (error instanceof RtmError) {
    console.error(`Get messages failed: ${error.reason} (code: ${error.errorCode})`);
  }
}
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-3]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-3]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-3]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-4]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-4]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```dart
final (status, _) = await _rtmClient.publish(
  'chatroom',
  'Hello world!',
  channelType: 'MESSAGE',
  customType: 'STRING',
  storeInHistory: true,
);
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```dart
final (status, _) = await _rtmClient.publish(
  'Tony',
  'Hello world!',
  channelType: 'USER',
  customType: 'STRING',
  storeInHistory: true,
);
```

## 获取历史消息 [#获取历史消息-4]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```dart
final history = rtmClient.getHistory();
final (_, result) = await history.getMessages(
  'chat_room',
  'MESSAGE',
  messageCount: 100,
  start: 0,
  end: 0,
);
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-4]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-4]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-4]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-5]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-5]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```cpp
uint64_t requestId = 0;
std::string channelName = "chatRoom"
std::string message = "Hello world!";

PublishOptions options;
options.storeInHistory = true;
options.channelType = RTM_CHANNEL_TYPE_MESSAGE;
options.messageType = RTM_MESSAGE_TYPE_STRING;

rtmClient->publish(channelName.c_str(), message.c_str(), message.size(), options,
                   requestId);
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```cpp
uint64_t requestId = 0;
std::string userId = "Tony"
std::string message = "Hello world!";

PublishOptions options;
options.storeInHistory = true;
options.channelType = RTM_CHANNEL_TYPE_USER;
options.messageType = RTM_MESSAGE_TYPE_STRING;

rtmClient->(userId.c_str(), message.c_str(), message.size(), options,
            requestId);
```

## 获取历史消息 [#获取历史消息-5]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```cpp
uint64_t requestId = 0;
std::string channelName = "chatRoom";

GetHistoryMessagesOptions options;
options.messageCount = 50;
options.end = 1688978391800;

rtmClient->getHistory()->getMessages(channelName.c_str(), RTM_CHANNEL_TYPE_MESSAGE,
                                     options, requestId);

```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-5]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-5]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-5]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-6]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-6]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```swift
let message = "Hello Agora!"
let channel = "your_channel"

let publishOption = AgoraRtmPublishOptions()
publishOption.storeInHistory = true;

rtm.publish(channelName: channel, message: message, option: publishOption, completion: { res, error in
    if error != nil {
        print("\(error?.operation) failed! error reason is \(error?.reason)")
    } else {
        print("success")
    }
})
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```swift
let message = "Hello Agora!"
let user = "Tony"

let publishOption = AgoraRtmPublishOptions()
publishOption.channelType = .user
publishOption.storeInHistory = true;

rtm.publish(channelName: user, message: message, option: publishOption, completion: { res, error in
    if error != nil {
        print("\(error?.operation) failed! error reason is \(error?.reason)")
    } else {
        print("success")
    }
})
```

## 获取历史消息 [#获取历史消息-6]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```swift
 var option = AgoraRtmGetHistoryMessagesOptions()
 option.messageCount = 50
 option.end = 1688978391800

rtmClient.getHistory()?.getMessages(channelName: "channel_name", channelType: .message, options: option, completion: { response, error in
    if response != nil {
        print("total message count is: \(response!.messageList.count)\n\n")
            for msg in response!.messageList {
                print("publisher: \(msg.publisher)\nmessage content: \(msg.message.stringData!)\ntime stamp: \(msg.timestamp)\n")
            }
            print("new start: \(response!.newStart)")
    } else {
        print("get history message failed")
    }
})
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-6]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-6]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-6]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="mini-program" />
历史消息功能允许你在向频道发布消息的时候存储所有消息。例如，当你中途加入聊天频道时，你可以利用此特性检索加入之前频道中发布的消息。你可以为项目配置消息存储时间，从 1 天到永久存储。

当消息发布时，历史消息会使用频道名和消息的发布时间戳进行存储，你可以利用这些信息来检索历史消息。

:::warning[注意]
历史消息特性仅支持 User Channel 和 Message Channel，暂时不支持 Stream Channel。
:::

## 开通历史消息 [#开通历史消息-7]

在使用历史消息功能之前，你需要确保你已经在控制台中针对此项目开通了历史消息功能开关，步骤如下：

1. 在[控制台](https://console.shengwang.cn/)左导航的**全部产品**下，点击**实时消息 RTM**，进入产品配置页。
2. 切换到**功能配置**页签，点击**历史消息（History）配置**区域的启用按钮：

   ![控制台开通历史消息](https://web-cdn.agora.io/docs-portal/img/rtm2/history-message.png)

3. 根据你的业务场景需要，设置历史消息的存储时间，例如：1 天、7 天、30 天、90 天、365 天或永久存储。

:::info[信息]
消息一旦被存储，你将不能再改变其存储时间。如果你在控制台更改了历史消息存储时间，这些设置只对之后存储的消息有效。
:::

## 存储历史消息 [#存储历史消息-7]

在确保控制台中为此项目开通历史消息存储功能的情况下，你只需要在调用 `publish()` 接口时，将 `storeInHistory`  参数设置成 `true` 即可将此消息存储到历史消息服务器。

以下向你演示如何在向 Message Channel 发送消息的同时将消息存储到历史消息服务器：

```javascript
try {
  const result = await rtm.publish(
    "chatroom",
    "Hello world!",
    {
      channelType: "MESSAGE",
      customType: "STRING",
      storeInHistory: true,
    },
  );
  console.log("Publish message success:", result);
} catch (error) {
  console.error("Publish message failed:", error);
}
```

​
你也可以向 User Channel 发送消息的同时将消息存储到历史消息服务器，从而实现收件箱的功能：

```javascript
try {
  const result = await rtm.publish(
    "Tony",
    "Hello world!",
    {
      channelType: "USER",
      customType: "STRING",
      storeInHistory: true,
    },
  );
  console.log("Send message to user success:", result);
} catch (error) {
  console.error("Send message to user failed:", error);
}
```

## 获取历史消息 [#获取历史消息-7]

SDK 为你提供了获取历史消息的 API，你可以使用 `getMessages()` 接口一次性查询至多 100 条消息。

你可以通过设置 `start` 和 `end` 参数来获取指定时间段内的历史消息。当然，大部分情况下你可能只想获取上次掉线时刻到当前时间之间最新的消息，这种情况下，你只需要设置 `end` 参数即可。以下代码演示如何获取到上次掉线时刻为止的最新 50 条消息：

```javascript
try {
  const result = await rtm.history.getMessages(
    "chat_room",
    "MESSAGE",
    {
      messageCount: 50,
      end: 1688978391800,
    },
  );
  console.log("Get history messages success! new start:", result.newStart);
  console.log("Total messages:", result.messageList.length);
} catch (error) {
  const { operation, reason, errorCode } = error;
  console.error(`${operation} failed, the error code is ${errorCode}, due to: ${reason}.`);
}
```

​
你可以通过返回值 `result` 中的 `newStart` 字段来判断是否还存在没有被读取的历史消息：如果此字段值为 0，表示所有历史消息都已被读取；如果不为 0，你可以将此值作为新的起点配置 `getMessages()` 接口的 `start` 参数，继续查询直到读取所有历史消息。

获取历史消息的时候，你可以通过配置以下参数组合来灵活控制获取消息的范围，让你读取信息更有效率：

#### 场景一：获取从 start 时间戳开始的 n 条消息 [#场景一获取从-start-时间戳开始的-n-条消息-7]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取此时间戳开始更早的消息，不包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- start timeStamp ----------------------- 最新的频道消息
[                 n 条消息  <----------]
```

#### 场景二：获取从当前时刻开始到 end 时间戳为止的消息 [#场景二获取从当前时刻开始到-end-时间戳为止的消息-7]

| 配置参数 | 行为 |
| --- | --- |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息----------------------- end timeStamp ------------------------- 最新的频道消息
                                                   [    n 条消息   <----------]
```

#### 场景三：获取从 start 时间戳开始到 end 时间戳为止中间的消息 [#场景三获取从-start-时间戳开始到-end-时间戳为止中间的消息-7]

| 配置参数 | 行为 |
| --- | --- |
| `start` | 获取从 start 时间戳开始更早的消息，不包含此时间戳。 |
| `end` | 获取从当前时刻开始到此时间戳为止最近的消息，包含此时间戳。 |

```
时间线
更早之前的频道消息---- end timeStamp --------------------- start timeStamp ------ 最新的频道消息
                                [ n 条消息 <------------]
```
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
