# 应用配置 (/zh-CN/realtime-media/rtm/build/rtm-initialization/application-setup)

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

在开始配置你的应用之前，你需要先了解用户 ID、服务类型等概念，然后下载并安装 SDK，再初始化一个 RTM 对象实例，最后实现事件监听函数以捕获 RTM 实时网络中的所有事件通知。

## 用户 ID（`userId`） [#用户-iduserid]

用户 ID 是一个用于标识用户和设备的 ASCII 码字符串，长度最多为 64 个字符。在初始化 RTM 客户端实例时，你需要自行定义用户 ID 并将其传递给 `userId` 参数。RTM 规定在同一个 App ID（`appId`）下，每个用户或设备都必须具有唯一的全局用户 ID。

为了正确使用 RTM，你需要了解用户、设备和客户端的概念：

- **用户**: 是指应用的实际使用者。
- **设备**: 是指实际接入 RTM 网络的终端，包括但不限于手机、电脑、智能手表等 IoT 设备。
- **客户端**: 是指运行在设备上的 RTM 对象实例。

一个用户可能拥有多台设备，而一台设备也有可能被多人拥有。为更好地区分不同的设备和用户，RTM 规定同一个用户 ID 不能在多台设备上同时登录 RTM 服务、一台设备上不能同时存在多个 RTM 客户端。如果一个用户拥有多台设备，则需要为每台设备都分配唯一的用户 ID。如果两台拥有相同用户 ID 的设备同时登录 RTM 服务，那么先登录上的设备会被后登录的设备挤下线，而被强制下线的设备会收到相应的事件通知。

在实际场景中，业务层的用户名和 RTM 的用户 ID 可能不同，你需要自行实现二者的映射与绑定逻辑。例如，用户先通过用户名登录你的业务服务器，服务器再生成对应的用户 ID，然后使用该用户 ID 初始化并登录 RTM 服务。

此外，用户 ID 也会影响计费和在线状态通知等功能的使用，所以声网建议你为用户和设备分配全局唯一的用户 ID 并在整个生命周期内保持不变。

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
<a id="servicetype"></a>

## 服务类型 [#服务类型]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `RtmClient` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `StreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `login` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `join` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `onLinkStateEvent` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。

<a id="protocol"></a>

## 连接协议配置 [#连接协议配置]

为保证连接的稳定性和服务的持续可用性，RTM 客户端与边缘服务器建立连接时会为每种服务（`MESSAGE` 服务和 `STREAM` 服务）分别建立两条传输链路。默认情况下，这两条链路分别基于 TCP 协议和 UDP 协议，这种设计使得任何一条链路出现网络问题都不会影响传输效果。相较于其他基于 WebSocket 的消息传输方案，RTM 的冗余链路设计能够最大程度地提升传输稳定性和消息到达率。

在某些情况下，用户可能会发现他们的网络不支持 UDP 端口的传输，这可能是暂时的，也可能是永久性的。在这种情况下，为了确保双链路设计能够最大程度地发挥作用，SDK 允许用户将两条链路都配置成 TCP 协议，只需在 `RtmConfig` 中设置 `protocolType` 字段即可。以下是一个将双链路都配置为 TCP 协议的代码示例：

```java
RtmConfig rtmConfig = new RtmConfig.Builder("appid", "userId")
    .protocolType(RtmProtocolType.TCP_ONLY)
    .build();
```

:::info[信息]
SDK 不支持将两条链路同时配置为 UDP 协议。
:::
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
<a id="servicetype"></a>

## 服务类型 [#服务类型-1]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `AgoraRtmClientKit` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `AgoraRtmStreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `loginByToken` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `joinWithOption` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `didReceiveLinkStateEvent` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。

<a id="protocol"></a>

## 连接协议配置 [#连接协议配置-1]

为保证连接的稳定性和服务的持续可用性，RTM 客户端与边缘服务器建立连接时会为每种服务（`MESSAGE` 服务和 `STREAM` 服务）分别建立两条传输链路。默认情况下，这两条链路分别基于 TCP 协议和 UDP 协议，这种设计使得任何一条链路出现网络问题都不会影响传输效果。相较于其他基于 WebSocket 的消息传输方案，RTM 的冗余链路设计能够最大程度地提升传输稳定性和消息到达率。

在某些情况下，用户可能会发现他们的网络不支持 UDP 端口的传输，这可能是暂时的，也可能是永久性的。在这种情况下，为了确保双链路设计能够最大程度地发挥作用，SDK 允许用户将两条链路都配置成 TCP 协议，只需在 `AgoraRtmClientConfig` 中设置 `protocolType` 字段即可。以下是一个将双链路都配置为 TCP 协议的代码示例：

```objc
AgoraRtmClientConfig* rtm_config = [[AgoraRtmClientConfig alloc] initWithAppId:@"your_appid" userId:@"your_userid"];
rtm_config.protocolType = AgoraRtmProtocolTypeTcpOnly;
```

:::info[信息]
SDK 不支持将两条链路同时配置为 UDP 协议。
:::
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
<a id="servicetype"></a>

## 服务类型 [#服务类型-2]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `rtm` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `RTMStreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `login` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `join` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `linkState` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
<a id="servicetype"></a>

## 服务类型 [#服务类型-3]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `RtmClient` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `StreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `login` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `join` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `linkState` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。

<a id="protocol"></a>

## 连接协议配置 [#连接协议配置-2]

为保证连接的稳定性和服务的持续可用性，RTM 客户端与边缘服务器建立连接时会为每种服务（`MESSAGE` 服务和 `STREAM` 服务）分别建立两条传输链路。默认情况下，这两条链路分别基于 TCP 协议和 UDP 协议，这种设计使得任何一条链路出现网络问题都不会影响传输效果。相较于其他基于 WebSocket 的消息传输方案，RTM 的冗余链路设计能够最大程度地提升传输稳定性和消息到达率。

在某些情况下，用户可能会发现他们的网络不支持 UDP 端口的传输，这可能是暂时的，也可能是永久性的。在这种情况下，为了确保双链路设计能够最大程度地发挥作用，SDK 允许用户将两条链路都配置成 TCP 协议，只需在 `RtmConfig` 中设置 `protocolType` 字段即可。以下是一个将双链路都配置为 TCP 协议的代码示例：

```typescript
const rtmConfig: RtmConfig = {
  appId: "your_appId",
  userId: "your_userId",
  protocolType: RtmProtocolType.TCP_ONLY
};
```

:::info[信息]
SDK 不支持将两条链路同时配置为 UDP 协议。
:::
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
<a id="servicetype"></a>

## 服务类型 [#服务类型-4]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `RtmClient` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `StreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `login` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `join` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `linkState` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。

<a id="protocol"></a>

## 连接协议配置 [#连接协议配置-3]

为保证连接的稳定性和服务的持续可用性，RTM 客户端与边缘服务器建立连接时会为每种服务（`MESSAGE` 服务和 `STREAM` 服务）分别建立两条传输链路。默认情况下，这两条链路分别基于 TCP 协议和 UDP 协议，这种设计使得任何一条链路出现网络问题都不会影响传输效果。相较于其他基于 WebSocket 的消息传输方案，RTM 的冗余链路设计能够最大程度地提升传输稳定性和消息到达率。

在某些情况下，用户可能会发现他们的网络不支持 UDP 端口的传输，这可能是暂时的，也可能是永久性的。在这种情况下，为了确保双链路设计能够最大程度地发挥作用，SDK 允许用户将两条链路都配置成 TCP 协议，只需在 `RtmConfig` 中设置 `protocolType` 字段即可。以下是一个将双链路都配置为 TCP 协议的代码示例：

```dart
late RtmClient rtmClient;
const protocolType = RtmProtocolType.tcpOnly;
const rtmConfig = RtmConfig( protocolType:protocolType );
try {
    final (status,client) = await RTM("myAppId", "Tony", rtmConfig:rtmConfig);
    if (status.error == true) {
        print(status);
    } else {
        rtmClient = client;
        print('Initialize success!');
    }
} catch (e) {
    print('Failed to create RTM client: $e');
}
```

:::info[信息]
SDK 不支持将两条链路同时配置为 UDP 协议。
:::
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
<a id="servicetype"></a>

## 服务类型 [#服务类型-5]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `IRtmClient` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `IStreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `login` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `join` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `onLinkStateEvent` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。

<a id="protocol"></a>

## 连接协议配置 [#连接协议配置-4]

为保证连接的稳定性和服务的持续可用性，RTM 客户端与边缘服务器建立连接时会为每种服务（`MESSAGE` 服务和 `STREAM` 服务）分别建立两条传输链路。默认情况下，这两条链路分别基于 TCP 协议和 UDP 协议，这种设计使得任何一条链路出现网络问题都不会影响传输效果。相较于其他基于 WebSocket 的消息传输方案，RTM 的冗余链路设计能够最大程度地提升传输稳定性和消息到达率。

在某些情况下，用户可能会发现他们的网络不支持 UDP 端口的传输，这可能是暂时的，也可能是永久性的。在这种情况下，为了确保双链路设计能够最大程度地发挥作用，SDK 允许用户将两条链路都配置成 TCP 协议，只需在 `RtmConfig` 中设置 `protocolType` 字段即可。以下是一个将双链路都配置为 TCP 协议的代码示例：

```cpp
RtmConfig config;
config.appId = "appid";
config.userId = "userId";
config.protocolType = RTM_PROTOCOL_TYPE_TCP_ONLY;
```

:::info[信息]
SDK 不支持将两条链路同时配置为 UDP 协议。
:::
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
<a id="servicetype"></a>

## 服务类型 [#服务类型-6]

基于不同的传输连接，RTM SDK 提供的功能可以被划分为两种服务类型： `MESSAGE` 服务和 `STREAM` 服务。

- `MESSAGE` 服务涵盖了 `Message Channel`、`User Channel`、`Presence`、`Storage`、`Lock`、`Token` 鉴权等功能特性，通过 `AgoraRtmClientKit` 实例调用 API。
- `STREAM` 服务则提供了 `Stream Channel`、`Topic` 等功能，通过 `AgoraRtmStreamChannel` 实例调用 API。

在 `MESSAGE` 服务中，所有功能特性将共享一条传输连接，该连接在 `login` 时建立，在 `logout` 时关闭。而在 `STREAM` 服务中，传输连接的数量取决于加入的 `STREAM CHANNEL` 数量，即每个加入的 `STREAM CHANNEL` 实例都拥有独立的连接，连接在 `join` 时建立，在 `leave` 时关闭。

所有传输连接都由 SDK 统一管理，并通过 `didReceiveLinkStateEvent` 事件通知给用户，详见[连接管理](/zh-CN/realtime-media/rtm/build/authentication-and-connection/link-basic)。深入理解 RTM 服务类型的区别，有助于你更准确地选择和使用相关能力。

此外，服务类型还涉及私有化配置的选择。用户可以选择私有化一个服务，或者同时私有化两种服务，具体取决于应用场景和预算。详见[私有化配置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/private-setup)。

<a id="protocol"></a>

## 连接协议配置 [#连接协议配置-5]

为保证连接的稳定性和服务的持续可用性，RTM 客户端与边缘服务器建立连接时会为每种服务（`MESSAGE` 服务和 `STREAM` 服务）分别建立两条传输链路。默认情况下，这两条链路分别基于 TCP 协议和 UDP 协议，这种设计使得任何一条链路出现网络问题都不会影响传输效果。相较于其他基于 WebSocket 的消息传输方案，RTM 的冗余链路设计能够最大程度地提升传输稳定性和消息到达率。

在某些情况下，用户可能会发现他们的网络不支持 UDP 端口的传输，这可能是暂时的，也可能是永久性的。在这种情况下，为了确保双链路设计能够最大程度地发挥作用，SDK 允许用户将两条链路都配置成 TCP 协议，只需在 `AgoraRtmClientConfig` 中设置 `protocolType` 字段即可。以下是一个将双链路都配置为 TCP 协议的代码示例：

```swift
let rtmConfig = AgoraRtmClientConfig(appId: "your_appid", userId: "your_userid")
rtmConfig.protocolType = .tcpOnly
```

:::info[信息]
SDK 不支持将两条链路同时配置为 UDP 协议。
:::
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

<a id="install"></a>

## 安装 SDK [#安装-sdk]

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
你可以通过以下方式获取最新的 RTM Android SDK。

<Tabs defaultValue="cdn">
<TabsList>
  <TabsTrigger value="cdn">使用 CDN</TabsTrigger>
  <TabsTrigger value="maven">使用 Maven</TabsTrigger>
</TabsList>

<TabsContent value="cdn">

1. [点击此处](https://download.shengwang.cn/rtm2/release/RTM_JAVA_SDK_for_Android_v2.3.0.zip)下载最新版本的 Java SDK。
2. 将 SDK 包内 `sdk` 文件夹中的所有文件拷贝到项目的 `/app/libs` 路径下。
3. 添加 SDK 引用。在 **Project** 窗口找到 `/Gradle Scripts/build.gradle(Module: <projectname>.app)` 文件并添加如下代码：

   1. 在 `defaultConfig` 节点添加 `ndk` 节点，指定支持的架构。

      ```groovy
      Config {
          // ...

          ndk{
              abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
          }
      }
      ```

      :::info[信息]
      支持的架构越多，App 的体积会越大，声网建议你根据实际情况添加需要支持的架构。一般在发布 Android App 时只需保留 armeabi-v7a 和 arm64-v8a 架构。
      :::

   2. 在 `android` 节点添加 `sourceSets` 节点，指定 `libs` 所在目录。

      ```groovy
      android {
          // ...
          sourceSets {
              main {
                  jniLibs.srcDirs = ['libs']
              }
          }
      }
      ```

   3. 在 `dependencies` 节点引入 `libs` 路径下所有的 jar 库。

      ```groovy
      dependencies {
          implementation fileTree(dir: 'libs', include: ['*.jar'])
          // ...
      }
      ```

</TabsContent>

<TabsContent value="maven">

1. 在 `/Gradle Scripts/build.gradle(Project: <projectname>)` 文件中添加如下代码，添加 Maven Central 依赖：

   ```java
   buildscript {
       repositories {
           // ...
           mavenCentral()
       }
       ...
   }
   allprojects {
       repositories {
           // ...
           mavenCentral()
       }
   }
   ```

   :::info[信息]
   如果你的 Android 项目设置了 [dependencyResolutionManagement](https://docs.gradle.org/current/userguide/centralizing_repositories.html)，添加 Maven Central 依赖的方式可能存在差异。
   :::

2. 在 `/Gradle Scripts/build.gradle(Module: <projectname>.app)` 文件中添加如下代码，将 SDK 集成到你的 Android 项目中：

   ```groovy
   ...
   dependencies {
       // 将 x.y.z 替换为具体的 SDK 版本号，如 2.3.0
       // 对于 2.2.7 及之后版本:
       implementation 'cn.shengwang.rtm:android-java:x.y.z'
       // 对于 2.2.6 及之前版本:
       // implementation 'io.agora:agora-rtm:x.y.z'

   }
   ```

</TabsContent>
</Tabs>
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
你可以通过以下方式获取最新的 RTM iOS SDK。

<Tabs defaultValue="cdn">
<TabsList>
  <TabsTrigger value="cdn">使用 CDN</TabsTrigger>
  <TabsTrigger value="cocoapods">使用 Cocoapods</TabsTrigger>
  <TabsTrigger value="spm">通过 SPM 集成 SDK</TabsTrigger>
</TabsList>

<TabsContent value="cdn">

1. [点击此处](https://download.shengwang.cn/rtm2/release/RTM_OC_SDK_v2.3.0.zip)下载最新版本的 Objective-C SDK。
2. 复制 SDK 包中 `/libs` 路径下所有的 `xcframework` 文件至项目路径下。
3. 打开 Xcode，进入 **TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content** 菜单。
4. 点击 **+ > Add Other… > Add Files** 添加所有的 `xcframework` 文件，并确保添加的动态库 **Embed** 属性设置为 **Embed & Sign**。

添加完成后，项目会自动链接所需系统库。

</TabsContent>

<TabsContent value="cocoapods">

1. 开始前请确保你已安装 Cocoapods，如尚未安装 Cocoapods，参考 [Getting Started with CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started) 安装说明。
2. 在终端里进入项目根目录，并运行 `pod init` 命令。项目文件夹下会生成一个 `Podfile` 文本文件。
3. 打开 `Podfile` 文件，修改文件为如下内容。注意将 `Your App` 替换为你的 Target 名称。

   ```ruby
   platform :ios, '11.0'
   target 'Your App' do
      # 对于 2.2.8 及之后版本:
      pod 'ShengWang-Rtm', '2.3.0', :subspecs => ['RtmKit']
      # 对于 2.2.7 版本:
      # pod 'ShengwangRtm', 'x.y.z'
      # 对于 2.2.6 及之前版本:
      # pod 'AgoraRtm', 'x.y.z'
      # 如需获取 2.2.0 之前的版本，请将包名修改为 AgoraRtm_iOS
   end
   ```

4. 在终端内运行 `pod install` 命令安装声网 SDK。成功安装后，Terminal 中会显示 `Pod installation complete!`。
5. 成功安装后，项目文件夹下会生成一个后缀为 `.xcworkspace` 的文件，通过 Xcode 打开该文件进行后续操作。

</TabsContent>

<TabsContent value="spm">

使用如下链接，通过 SPM (Swift Package Manager) 集成 SDK：

```text
https://github.com/AgoraIO/AgoraRtm_Apple.git
```

</TabsContent>
</Tabs>
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
你可以通过以下方式获取最新的 RTM Web SDK。

#### 方式一：使用 CDN 添加 SDK [#方式一使用-cdn-添加-sdk]

[点击此处](https://download.agora.io/rtm2/release/Agora_RTM_JavaScript_SDK_for_Web_v2.3.0.zip)下载最新版本的 JavaScript SDK，并在你的项目中添加以下代码引用它：

```javascript
// 使用 CDN 直接将以下代码添加到你的 Web 应用中，或下载 SDK 文件后在本地引用
// 将 x.y.z 替换为具体的 SDK 版本号，如 2.3.0
// 可通过发版说明获取最新版本号
<script src="your_path_to_sdk/agora-rtm.x.y.z.min.js"></script>
```

#### 方式二：使用包管理器引入 SDK [#方式二使用包管理器引入-sdk]

1. 根据你的应用场景和开发需要，选择一种方式和工具安装 SDK。

   **场景一**：项目仅使用 RTM 产品，且没有集成声网任何版本的 RTC 产品。

   <Tabs defaultValue="npm" groupId="package" persist>
   <TabsList>
     <TabsTrigger value="npm">使用 npm</TabsTrigger>
     <TabsTrigger value="pnpm">使用 pnpm</TabsTrigger>
     <TabsTrigger value="yarn">使用 Yarn</TabsTrigger>
   </TabsList>

   <TabsContent value="npm">

   ```shell
   npm install agora-rtm
   ```

   </TabsContent>

   <TabsContent value="pnpm">

   ```shell
   pnpm add agora-rtm
   ```

   </TabsContent>

   <TabsContent value="yarn">

   ```shell
   yarn add agora-rtm
   yarn add agora-rtc-sdk-ng@4.22.0 --save-exact
   ```

   </TabsContent>
   </Tabs>

   **场景二**：项目中已经集成了 RTC 产品，需要新接入 RTM 产品。

   <Tabs defaultValue="npm" groupId="package" persist>
   <TabsList>
     <TabsTrigger value="npm">使用 npm</TabsTrigger>
     <TabsTrigger value="pnpm">使用 pnpm</TabsTrigger>
     <TabsTrigger value="yarn">使用 Yarn</TabsTrigger>
   </TabsList>

   <TabsContent value="npm">

   ```shell
   npm install agora-rtm
   ```

   </TabsContent>

   <TabsContent value="pnpm">

   ```shell
   pnpm add agora-rtm
   ```

   如果项目使用的 RTC 版本与 RTM 中依赖的 RTC 版本不一致，会收到提示：`unmet peer agora-rtc-sdk-ng@4.22.0: found 4.16.0`。此时你需要升级 RTC 的版本：

   ```shell
   pnpm update agora-rtc-sdk-ng@4.22.0
   ```

   或者通过以下命令同时保留两个版本的 RTC 库：

   ```shell
   pnpm add agora-rtc-sdk-ng-4.16@npm:agora-rtc-sdk-ng@4.16.0 --save-exact
   pnpm add agora-rtc-sdk-ng@4.22.0 --save-exact
   ```

   然后将代码中原来的 `import AgoraRTC from "agora-rtc-sdk-ng"` 替换为如下行：

   ```javascript
   import AgoraRTC from "agora-rtc-sdk-ng-4.16"
   ```

   :::warning[注意]
   保留两个版本的 RTC 库会增加项目的包体积。
   :::

   </TabsContent>

   <TabsContent value="yarn">

   ```shell
   yarn add agora-rtm
   ```

   如果项目使用的 RTC 版本与 RTM 中依赖的 RTC 版本不一致，会收到提示：`unmet peer agora-rtc-sdk-ng@4.22.0: found 4.16.0`。此时你需要升级 RTC 的版本：

   ```shell
   yarn upgrade agora-rtc-sdk-ng@4.22.0
   ```

   或者通过以下命令同时保留两个版本的 RTC 库：

   ```shell
   yarn add agora-rtc-sdk-ng-4.16@npm:agora-rtc-sdk-ng@4.16.0 --save-exact
   yarn add agora-rtc-sdk-ng@4.22.0 --save-exact
   ```

   然后将代码中原来的 `import AgoraRTC from "agora-rtc-sdk-ng"` 替换为如下行：

   ```javascript
   import AgoraRTC from "agora-rtc-sdk-ng-4.16"
   ```

   :::warning[注意]
   保留两个版本的 RTC 库会增加项目的包体积。
   :::

   </TabsContent>
   </Tabs>

   **场景三**：你的项目是全新的，且需要同时集成 RTM 和 RTC，以利用其共频道、数据优先级控制等能力。这种场景下建议你集成融合版本的 SDK。

   <Tabs defaultValue="npm" groupId="package" persist>
   <TabsList>
     <TabsTrigger value="npm">使用 npm</TabsTrigger>
     <TabsTrigger value="pnpm">使用 pnpm</TabsTrigger>
     <TabsTrigger value="yarn">使用 Yarn</TabsTrigger>
   </TabsList>

   <TabsContent value="npm">

   ```shell
   npm install agora-rtx
   ```

   </TabsContent>

   <TabsContent value="pnpm">

   ```shell
   pnpm add agora-rtx --shamefully-hoist
   ```

   </TabsContent>

   <TabsContent value="yarn">

   ```shell
   # 若版本为 2.2.0
   # yarn add agora-rtx
   # yarn add agora-rtc-sdk-ng@4.22.0 --save-exact

   # 2.2.0 及之后版本
   yarn add agora-rtx
   ```

   </TabsContent>
   </Tabs>

2. 完成安装后，在你的 `app.js` 中引入 RTM：

    ```javascript
    // 如果安装的是 agora-rtm
    import AgoraRTM from 'agora-rtm';

    // 如果安装的是融合版 agora-rtx
    // import AgoraRTM from 'agora-rtx';
    // import AgoraRTC from 'agora-rtc-sdk-ng';
    ```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
你可以通过以下方式获取最新的 RTM HarmonyOS SDK。

[点击此处](https://download.shengwang.cn/rtm2/release/RTM_ArkTS_SDK_for_HarmonyOS_v2.3.0.zip)下载最新版本的 HarmonyOS SDK。

下载完成后，解压 SDK 包，你将获得一个 `.har` 文件，这是 HarmonyOS 的静态共享包格式。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
[点击此处](https://download.agora.io/sdk/release/Agora_Unity_RTM_SDK_v2.1.9.zip)下载最新版本的 Unity SDK，并在你的项目中导入它。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
你可以通过以下方式获取最新的 RTM Flutter SDK。

1. 打开终端或命令行，执行以下命令来创建一个新的 Flutter 项目：

    ```shell
    # 创建 Flutter 项目
    flutter create getting_started
    ```

2. 使用的你的 IDE 工具打开项目，编辑 `pubspec.yaml` 文件，添加以下依赖：

    ```yaml
    dependencies:
      # 添加 RTM Flutter SDK 依赖项，请使用最新版本的 agora_rtm
      agora_rtm: ^2.2.6
    ```

   :::info[信息]
   如果你同时集成了 2.2.1 及以上版本的 RTM SDK 和 4.3.0 及以上版本的 RTC SDK，请参考 [FAQ](/zh-CN/reference/faq/integration/rtm2_rtc_integration_issue) 处理集成问题。
   :::

3. 添加依赖并保存文件后，打开终端，在项目路径下执行以下命令获取并安装依赖：

    ```shell
    flutter pub get
    ```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
[点击此处](https://download.shengwang.cn/rtm2/release/RTM_C%2B%2B_SDK_for_Windows_v2.3.0.zip)下载最新版本的 C++ SDK 并解压。将 SDK 包中的如下文件复制到项目的对应目录下：

- 将 `/rtm/sdk/libagora_rtm_sdk.so` 文件复制到项目的 `lib` 目录下。
- 将 `/rtm/sdk/high_level_api/include` 路径下的所有 `*.h` 文件复制到项目的 `include` 目录下。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
你可以通过以下方式获取最新的 RTM Swift SDK。

<Tabs defaultValue="cdn">
<TabsList>
  <TabsTrigger value="cdn">使用 CDN</TabsTrigger>
  <TabsTrigger value="cocoapods">使用 Cocoapods</TabsTrigger>
  <TabsTrigger value="spm">通过 SPM 集成 SDK</TabsTrigger>
</TabsList>

<TabsContent value="cdn">

1. [点击此处](https://download.shengwang.cn/rtm2/release/RTM_OC_SDK_v2.3.0.zip)下载最新版本的 Objective-C SDK。
2. 复制 SDK 包中 `/libs` 路径下所有的 `xcframework` 文件至项目路径下。
3. 打开 Xcode，进入 **TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content** 菜单。
4. 点击 **+ > Add Other… > Add Files** 添加所有的 `xcframework` 文件，并确保添加的动态库 **Embed** 属性设置为 **Embed & Sign**。

添加完成后，项目会自动链接所需系统库。

</TabsContent>

<TabsContent value="cocoapods">

1. 开始前请确保你已安装 Cocoapods，如尚未安装 Cocoapods，参考 [Getting Started with CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started) 安装说明。
2. 在终端里进入项目根目录，并运行 `pod init` 命令。项目文件夹下会生成一个 `Podfile` 文本文件。
3. 打开 `Podfile` 文件，修改文件为如下内容。注意将 `Your App` 替换为你的 Target 名称。

   ```ruby
   platform :ios, '11.0'
   target 'Your App' do
      # 对于 2.2.8 及之后版本:
      pod 'ShengWang-Rtm', '2.3.0', :subspecs => ['RtmKit']
      # 对于 2.2.7 版本:
      # pod 'ShengwangRtm', 'x.y.z'
      # 对于 2.2.6 及之前版本:
      # pod 'AgoraRtm', 'x.y.z'
      # 如需获取 2.2.0 之前的版本，请将包名修改为 AgoraRtm_iOS
   end
   ```

4. 在终端内运行 `pod install` 命令安装声网 SDK。成功安装后，Terminal 中会显示 `Pod installation complete!`。
5. 成功安装后，项目文件夹下会生成一个后缀为 `.xcworkspace` 的文件，通过 Xcode 打开该文件进行后续操作。

</TabsContent>

<TabsContent value="spm">

使用如下链接，通过 SPM (Swift Package Manager) 集成 SDK：

```text
https://github.com/AgoraIO/AgoraRtm_Apple.git
```

</TabsContent>
</Tabs>
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

详细流程参考[快速开始](/zh-CN/realtime-media/rtm/get-started/quick-start)。

## 初始化 RTM 实例 [#初始化-rtm-实例]

在使用 RTM 功能前，你需要使用 `appId` 和 `userId` 来初始化一个 RTM 实例。在后续的示例代码中，你需要将 `your_appId` 和 `your_userId` 字段都替换为你自己的 `appId` 和 `userId`。

:::info[信息]
初始化 RTM 对象时的 `appId` 和 `userId` 为必填参数，如果缺失，则初始化会失败。
:::

在一个客户端中，你只需要初始化一次 RTM 对象实例，即可在后续实现中通过该对象实例调用 RTM 的其他 API。

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
```java
RtmConfig rtmConfig = new RtmConfig();
rtmConfig.userId = "your_userId";
rtmConfig.appId = "your_appId";
try {
    mRtmClient = RtmClient.create(rtmConfig);
} catch(Exception e) {
    log(INFO, "create rtm client failed with exception: " e.toString());
}
```

现在，你就可以使用 `RtmClient` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
```objc
AgoraRtmClientConfig* rtm_cfg = [[AgoraRtmClientConfig alloc] initWithAppId:@"your_appid" userId:@"your_userid"];
NSError* initError = nil;
AgoraRtmClientKit* rtm = [[AgoraRtmClientKit alloc] initWithConfig:rtm_cfg delegate:handler error:&initError];
```

现在，你就可以使用 `AgoraRtmClientKit` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
```javascript
const { RTM } = AgoraRTM;
// Fill in the App ID of your project.
const appId = "your_appId";
// Fill in your user ID.
const userId = "your_userId";
try {
    const rtm = new RTM(appId, userId);
    console.log("Create new RTM client Success!");
} catch (status) {
    console.log("Error with status: ${status}");
}
```

我们推荐你使用 `try{...}/catch{...}` 范式捕获初始化过程中可能出现的异常。现在，你就可以使用 `rtm` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
```typescript
import { RtmClient, RtmConfig } from '@shengwang/rtm-full';
import { RtmError } from '@shengwang/rtm-full';

const rtmConfig: RtmConfig = {
  appId: "your_appId",
  userId: "your_userId"
};

try {
  const rtmClient = new RtmClient(rtmConfig);
  console.log("RTM Client Initialize Successful");
} catch (error) {
  if (error instanceof RtmError) {
    console.error(`Initialize failed: ${error.reason} (code: ${error.errorCode})`);
  } else {
    console.error("Failed to initialize RTM client:", error);
  }
}
```

现在，你就可以使用 `RtmClient` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
```csharp showLineNumbers
using Agora.Rtm;

private IRtmClient rtmClient;

var config = new RtmConfig();
config.appId = "your_appId";
config.userId = "your_userId";
try
{
    rtmClient = RtmClient.CreateAgoraRtmClient(config);
    Debug.Log("RTM Client Initialize Successful");
}
catch (RTMException e)
{
    Debug.Log(string.Format("{0} is failed.", e.Status.Operation ));
    Debug.Log(string.Format("ErrorCode: {0}, due to: {1}", e.Status.ErrorCode, e.Status.Reason));
}
```

现在，你就可以使用 `IRtmClient` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
```dart
late RtmClient rtmClient;

const rtmConfig = RtmConfig(
    heartbeatInterval : 30,              // Set heartbeat interval to 30 seconds
    presenceTimeout : 30);               // Set presence timeout to 30 seconds

try {
    var (status,client) = await RTM("your_appId", "you_userId", rtmConfig:rtmConfig);
    if (status.error == true) {
        print(status);
    } else {
        rtmClient = client;
        print('Initialize success!');
    }
} catch (e) {
    print('Failed to create RTM client: $e');
}
```

现在，你就可以使用 `RtmClient` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
```cpp
RtmConfig config;
config.appId = "your_appid";
config.userId = "your_userId";
config.eventHandler = new RtmEventHandler();

int errorCode = 0;
IRtmClient* rtmClient = createAgoraRtmClient(config, errorCode);
if (!rtmClient || errorCode != 0) {
  // create rtm client failed
}
```

现在，你就可以使用 `IRtmClient` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
```swift
do {
    let config = AgoraRtmClientConfig(appId: "yourAppId", userId: "uniqueUserId")
    // Initializing the RTM client
    let rtmClient = try AgoraRtmClientKit(config, delegate: nil)
    if rtmClient != nil {
        print("RTM Client initialized successfully!")
    }
} catch let error {
    print("Failed to initialize RTM client. Error: \(error)")
}
```

现在，你就可以使用 `AgoraRtmClientKit` 对象调用 RTM 的其他 API 接口了。
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

## 日志设置 [#日志设置]

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `RtmConfig` 中的 `RtmLogLevel` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```java
RtmLogConfig logConfig = new RtmLogConfig()
// set log file path.
logConfig.filePath = "./logfile/";
// set log file size.
logConfig.fileSizeInKB = 512;
// set log report level.
logConfig.level = RtmLogLevel.INFO;

RtmConfig rtmConfig = new RtmConfig();
rtmConfig.userId = "your_userId";
rtmConfig.appId = "your_appId";
rtmConfig.logConfig = logConfig; // set log config
try {
    mRtmClient = RtmClient.create(rtmConfig);
} catch(Exception e) {
    log(INFO, "create rtm client failed with exception: " e.toString());
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `AgoraRtmClientConfig` 中的 `AgoraRtmLogLevel` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```objc
AgoraRtmClientConfig* rtm_cfg = [[AgoraRtmClientConfig alloc] initWithAppId:@"your_appid" userId:@"your_userid"];

// set log config
AgoraRtmLogConfig* log_cfg = [[AgoraRtmLogConfig alloc] init];
log_cfg.level= AgoraRtmLogLevelError;
log_cfg.filePath= @"your_path";
log_cfg.fileSizeInKB = 512;

rtm_cfg.logConfig = log_cfg;

NSError* initError = nil;
AgoraRtmClientKit* rtm = [[AgoraRtmClientKit alloc] initWithConfig:rtm_cfg delegate:handler error:&initError];
if (rtm != nil) {
    NSLog(@"init rtm success!!");
} else {
    NSLog(@"init rtm failed!!");
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `RTMConfig` 中的 `logLevel` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```javascript showLineNumbers
const { RTM } = AgoraRTM;
const appId = "your_appId";
const userId = "your_userId";
const rtmConfig = { logLevel : "debug" };
const rtm = new RTM(appId, userId, rtmConfig);
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `RtmConfig` 中的 `RtmLogLevel` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```typescript
import { RtmClient, RtmConfig, RtmLogConfig, RtmLogLevel } from '@shengwang/rtm-full';
import { RtmError } from '@shengwang/rtm-full';

const logConfig: RtmLogConfig = {
  filePath: "./logfile/",
  fileSizeInKB: 512,
  level: RtmLogLevel.INFO
};

const rtmConfig: RtmConfig = {
  appId: "your_appId",
  userId: "your_userId",
  logConfig: logConfig
};

try {
  const rtmClient = new RtmClient(rtmConfig);
  console.log("RTM Client Initialize Successful");
} catch (error) {
  if (error instanceof RtmError) {
    console.error(`Initialize failed: ${error.reason} (code: ${error.errorCode})`);
  } else {
    console.error("Failed to initialize RTM client:", error);
  }
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `RtmConfig` 中的 `RTM_LOG_LEVEL` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```csharp showLineNumbers
using Agora.Rtm;

private IRtmClient rtmClient;

LogConfig logConfig = new LogConfig()
// set log file path.
logConfig.filePath = "./logfile/";
// set log file size.
logConfig.fileSizeInKB = 512;
// set log report level.
logConfig.level = LOG_LEVEL.INFO;

RtmConfig config = new RtmConfig();
// initialize logconfig.
config.logConfig = logConfig;
config.appId = "your_appId";
config.userId = "your_userId";
try
{
    rtmClient = RtmClient.CreateAgoraRtmClient(config);
    Debug.Log("RTM Client Initialize Sucessfull");
}
catch (RTMException e)
{
    Debug.Log(string.Format("{0} is failed.", e.Status.Operation ));
    Debug.Log(string.Format("Error code: {0}, due to: {1}", e.Status.ErrorCode, e.Status.Reason));
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `RtmConfig` 中的 `RtmLogLevel` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```dart showLineNumbers
const logConfig = RtmLogConfig(
    filePath: './rtm_logfile/',
    fileSizeInKB: 1024,
    level: warn );

const rtmConfig = RtmConfig( logConfig:logConfig );
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `RtmConfig` 中的 `RTM_LOG_LEVEL` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```cpp
RtmConfig config;
config.appId = "your_appid";
config.userId = "your_name";
config.eventHandler = new RtmEventHandler();

config.logConfig.level = RTM_LOG_LEVEL_INFO;
config.logConfig.filePath = "your_path";
config.logConfig.fileSizeInKB = 10 * 1024;

int errorCode = 0;
IRtmClient* rtmClient = createAgoraRtmClient(config, errorCode);
if (!rtmClient || errorCode != 0) {
  // create rtm client failed
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
当你的应用处于开发、测试阶段时，你可能需要 SDK 输出更详细的信息来定位并修复问题。你可以在初始化 RTM 实例的时候通过设置 `AgoraRtmClientConfig` 中的 `AgoraRtmLogLevel` 来开启日志输出并设置日志信息等级，之后即可在相应平台的日志输出位置查看日志信息。

```swift
do {
    let logConfig = AgoraRtmLogConfig()
    logConfig.level = .error
    logConfig.filePath = "your_path"
    logConfig.fileSizeInKB = 512

    let rtmConfig = AgoraRtmClientConfig(appId: "your_appid", userId: "your_userid")
    rtmConfig.logConfig = logConfig
    // Initializing the RTM client
    let rtmClient = try AgoraRtmClientKit(rtmConfig, delegate: nil)
    if rtmClient != nil {
        print("RTM Client initialized successfully!")
    }
} catch let error {
    print("Failed to initialize RTM client. Error: \(error)")
}
```
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

日志有以下五种等级：

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `INFO`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `NONE`  | `0x0000`: 不输出任何日志。                                                                   |
| `INFO`  | `0x0001`: 输出 `FATAL`、`ERROR`、`WARN`、`INFO` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `WARN`  | `0x0002`: 仅输出 `FATAL`、`ERROR`、`WARN` 级别的日志。                                       |
| `ERROR` | `0x0004`: 仅输出 `FATAL`、`ERROR` 级别的日志。                                               |
| `FATAL` | `0x0008`: 仅输出 `FATAL` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `AgoraRtmLogLevelInfo`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `AgoraRtmLogLevelNone`  | `0x0000`: 不输出任何日志。                                                                   |
| `AgoraRtmLogLevelInfo`  | `0x0001`: 输出 `AgoraRtmLogLevelFatal`、`AgoraRtmLogLevelError`、`AgoraRtmLogLevelWarn`、`AgoraRtmLogLevelInfo` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `AgoraRtmLogLevelWarn`  | `0x0002`: 仅输出 `AgoraRtmLogLevelFatal`、`AgoraRtmLogLevelError`、`AgoraRtmLogLevelWarn` 级别的日志。                                       |
| `AgoraRtmLogLevelError` | `0x0004`: 仅输出 `AgoraRtmLogLevelFatal`、`AgoraRtmLogLevelError` 级别的日志。                                               |
| `AgoraRtmLogLevelFatal` | `0x0008`: 仅输出 `AgoraRtmLogLevelFatal` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `info`。
:::

|                           属性值                            | 描述                                      |
| --- | ------------- |
| `debug` | 输出所有日志。                            |
| `info`  | 输出 `error`、`warn`、`info` 级别的日志。 |
| `warn`  | 输出 `error`、`warn` 级别的日志。         |
| `error` | 输出 `error` 级别的日志。                 |
| `none`  | 不输出任何日志。                          |

你也可以查看[错误排查](/zh-CN/realtime-media/rtm/build/troubleshooting)了解更详细地调试及错误处理方法。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `INFO`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `NONE`  | `0x0000`: 不输出任何日志。                                                                   |
| `INFO`  | `0x0001`: 输出 `FATAL`、`ERROR`、`WARN`、`INFO` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `WARN`  | `0x0002`: 仅输出 `FATAL`、`ERROR`、`WARN` 级别的日志。                                       |
| `ERROR` | `0x0004`: 仅输出 `FATAL`、`ERROR` 级别的日志。                                               |
| `FATAL` | `0x0008`: 仅输出 `FATAL` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `INFO`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `NONE`  | `0x0000`: 不输出任何日志。                                                                   |
| `INFO`  | `0x0001`: 输出 `FATAL`、`ERROR`、`WARN`、`INFO` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `WARN`  | `0x0002`: 仅输出 `FATAL`、`ERROR`、`WARN` 级别的日志。                                       |
| `ERROR` | `0x0004`: 仅输出 `FATAL`、`ERROR` 级别的日志。                                               |
| `FATAL` | `0x0008`: 仅输出 `FATAL` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `info`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `none`  | `0x0000`: 不输出任何日志。                                                                   |
| `info`  | `0x0001`: 输出 `fatal`、`error`、`warn`、`info` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `warn`  | `0x0002`: 仅输出 `fatal`、`error`、`warn` 级别的日志。                                       |
| `error` | `0x0004`: 仅输出 `fatal`、`error` 级别的日志。                                               |
| `fatal` | `0x0008`: 仅输出 `fatal` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `RTM_LOG_LEVEL_INFO`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `RTM_LOG_LEVEL_NONE`  | `0x0000`: 不输出任何日志。                                                                   |
| `RTM_LOG_LEVEL_INFO`  | `0x0001`: 输出 `RTM_LOG_LEVEL_FATAL`、`RTM_LOG_LEVEL_ERROR`、`RTM_LOG_LEVEL_WARN`、`RTM_LOG_LEVEL_INFO` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `RTM_LOG_LEVEL_WARN`  | `0x0002`: 仅输出 `RTM_LOG_LEVEL_FATAL`、`RTM_LOG_LEVEL_ERROR`、`RTM_LOG_LEVEL_WARN` 级别的日志。                                       |
| `RTM_LOG_LEVEL_ERROR` | `0x0004`: 仅输出 `RTM_LOG_LEVEL_FATAL`、`RTM_LOG_LEVEL_ERROR` 级别的日志。                                               |
| `RTM_LOG_LEVEL_FATAL` | `0x0008`: 仅输出 `RTM_LOG_LEVEL_FATAL` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
:::info[信息]
在你的应用上线时，你需要将日志等级参数设置为 `info`。
:::

|                           枚举值                            | 描述                                                                                         |
| --- | ------ |
| `none`  | `0x0000`: 不输出任何日志。                                                                   |
| `info`  | `0x0001`: 输出 `fatal`、`error`、`warn`、`info` 级别的日志。我们推荐你将日志级别设为该等级。 |
| `warn`  | `0x0002`: 仅输出 `fatal`、`error`、`warn` 级别的日志。                                       |
| `error` | `0x0004`: 仅输出 `fatal`、`error` 级别的日志。                                               |
| `fatal` | `0x0008`: 仅输出 `fatal` 级别的日志。                                                        |
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

<a id="cloud-proxy-设置"></a>

## Cloud Proxy 设置 [#cloud-proxy-设置]

完整配置说明请参阅[网络配置中的 Cloud Proxy 设置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/network-configuration#cloud-proxy-设置)。
<a id="proxy-设置"></a>

## Proxy 设置 [#proxy-设置]

完整配置说明请参阅[网络配置中的 Proxy 设置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/network-configuration#proxy-设置)。
<a id="防火墙白名单设置"></a>

## 防火墙白名单设置 [#防火墙白名单设置]

完整配置说明请参阅[网络配置中的防火墙白名单设置](/zh-CN/realtime-media/rtm/build/network-and-private-deployment/network-configuration#防火墙白名单设置)。
