# 登录服务 (/zh-CN/realtime-media/rtm/build/authentication-and-connection/login)

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

你需要登录才能真正连接上 RTM 服务器、访问 RTM 的网络资源，如发送消息、订阅频道等。在登录 RTM 服务之前，你需要确保你的设备处于网络连接的状态并完成了[应用设置](/zh-CN/realtime-media/rtm/build/rtm-initialization/application-setup)。

## 登录服务 [#登录服务]

执行登录操作时，客户端会尝试与 RTM 服务器建立长连接，一旦建立成功，客户端会按照固定的时间间隔向 RTM 服务器传递心跳信息以保持客户端的活跃状态，直到客户端主动退出登录或掉线超时才会中断连接。在此期间，你可以在权限和使用限制范围内访问 RTM 的网络资源。

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
```java
mRtmClient.login("your_token", new ResultCallback<Void>() {
    @Override
    public void onSuccess(Void responseInfo) {
        log(CALLBACK, "login success");
    }

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

你可以通过 `login` 的返回值或监听 `onLinkStateEvent` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `CONNECTING`；登录成功后，其状态会更新为 `CONNECTED` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `onLinkStateEvent` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/android/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
```objc
[rtm loginByToken:@"token" completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
    if (errorInfo == nil) {
        NSLog(@"login success!!");
    } else {
        NSLog(@"login failed, errorCode %d, reason %@", errorInfo.errorCode, errorInfo.reason);
    }
}];
```

你可以通过 `loginByToken` 的返回值或监听 `didReceiveLinkStateEvent` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `AgoraRtmLinkStateConnecting`；登录成功后，其状态会更新为 `AgoraRtmLinkStateConnected` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `didReceiveLinkStateEvent` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/ios/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
```javascript
try {
    const result = await rtm.login({ token: "your_token" });
} catch (status) {
    const { operation, reason, errorCode } = status;
    console.log(`${operation} failed, the error code is ${errorCode}, because of: ${reason}.`);
}
```

你可以通过 `login` 的返回值或监听 `linkState` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `CONNECTING`；登录成功后，其状态会更新为 `CONNECTED` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `linkState` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/web/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />

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

try {
  const response = await rtmClient.login("your_token");
  console.log("Login successful:", response);
} catch (error) {
  console.error("Login failed:", error);
  if (error instanceof RtmError) {
    console.error(`Login failed: ${error.reason} (code: ${error.errorCode})`);
  } else {
    console.error("Login failed");
  }
}
```

你可以通过 `login` 的返回值或监听 `linkState` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `CONNECTING`；登录成功后，其状态会更新为 `CONNECTED` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `linkState` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/harmonyos/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
```csharp
var (status,response) = await rtmClient.LoginAsync(token);
if (status.Error)
{
    Debug.Log(string.Format("{0} is failed, ErrorCode: {1}, due to: {2}", status.Operation, status.ErrorCode, status.Reason));
}
else
{
    Debug.Log("Login Successfully")
}
```

你可以通过 `LoginAsync` 的返回值或监听 `OnConnectionStateChanged` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `CONNECTING`；登录成功后，其状态会更新为 `CONNECTED` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `OnConnectionStateChanged` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/unity/configuration#OnConnectionStateChanged)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
```dart
try {
    var (status, response) = await rtmClient.login('your_Token');
    if (status.error == true ){
       print('${status.operation} failed, errorCode: ${status.errorCode}, due to ${status.reason}');
    } else {
        print('${status.operation} success!');
    }
} catch (e) {
    print('something went wrong: $e');
}
```

你可以通过 `login` 的返回值或监听 `linkState` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `connecting`；登录成功后，其状态会更新为 `connected` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `linkState` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/flutter/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
```cpp
uint64_t requestId;
rtmClient->login("your_token", requestId);
```

调用该方法后，SDK 会触发 `onLoginResult` 回调并返回 API 调用结果。

```cpp
// 异步回调
class RtmEventHandler : public IRtmEventHandler {
    void onLoginResult(const uint64_t requestId, RTM_ERROR_CODE errorCode) {
        if (errorCode != RTM_ERROR_OK) {
            printf("login rtm failed error is %d reason is %s\n", errorCode, getErrorReason(errorCode));
        } else {
            printf("login rtm success\n");
        }
    }
};
```

你可以通过 `login` 的返回值或监听 `onLinkStateEvent` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `RTM_LINK_STATE_CONNECTING`；登录成功后，其状态会更新为 `RTM_LINK_STATE_CONNECTED` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `onLinkStateEvent` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/cpp/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
```swift
rtm.login("token") { response, errorInfo in
    if errorInfo == nil {
        print("login success!!")
    } else {
        print("login failed, errorCode \(errorInfo?.errorCode), reason \(errorInfo?.reason)")
    }
}
```

你可以通过 `login` 的返回值或监听 `didReceiveLinkStateEvent` 事件通知来判断登录是否成功以及登录失败的错误码和错误原因。执行登录操作时，客户端的网络连接状态为 `connecting`；登录成功后，其状态会更新为 `connected` 状态。为持续监测客户端的网络连接状态，声网建议你在应用的整个生命周期内持续监听 `didReceiveLinkStateEvent` 事件通知，详见[事件监听](/zh-CN/api-reference/rtm/swift/configuration#事件监听)。
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

:::info[信息]
用户成功登录 RTM 服务后，应用的 PCU 会增加，这将影响你的账单数据。
:::

## 退出登录 [#退出登录]

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `onPresenceEvent` 事件通知。

```java
mRtmClient.logout(new ResultCallback<Void>() {
    @Override
    public void onSuccess(Void responseInfo) {
        log(CALLBACK, "logout success");
    }

    @Override
    public void onFailure(ErrorInfo errorInfo) {
        log(ERROR, errorInfo.toString());
    }
});
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `didReceivePresenceEvent` 事件通知。

```objc
[rtm logout:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
    if (errorInfo == nil) {
        NSLog(@"logout success!!");
    } else {
        NSLog(@"logout failed, errorCode %d, reason %@", errorInfo.errorCode, errorInfo.reason);
    }
}];
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `presence` 事件通知。

```javascript
try {
    const result = await rtm.logout();
} catch (status) {
    const { operation, reason, errorCode } = status;
    console.log(`${operation} failed, the error code is ${errorCode}, because of: ${reason}.`);
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `presence` 事件通知。

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

try {
  const response = await rtmClient.logout();
  console.log("Logout successful:", response);
} catch (error) {
  console.error("Logout failed:", error);
  if (error instanceof RtmError) {
    console.error(`logout: ${error.reason} (code: ${error.errorCode})`);
  } else {
    console.error("Logout failed");
  }
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `LogoutAsync` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `OnPresenceEvent` 事件通知。

```csharp
var (status,response) = await rtmClient.LogoutAsync();
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `presence` 事件通知。

```dart
try {
    var (status, response) = await rtmClient.logout();
    if (status.error == true ){
       print('${status.operation} failed, errorCode: ${status.errorCode}, due to ${status.reason}');
    } else {
        print('${status.operation} success!');
    }
} catch (e) {
    print('something went wrong: $e');
}
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `onPresenceEvent` 事件通知。

```cpp
uint64_t requestId;
rtmClient->logout(requestId);
```

调用该方法后，SDK 会触发 `onLogoutResult` 回调并返回 API 调用结果。

```cpp
// 异步回调
class RtmEventHandler : public IRtmEventHandler {
    void onLogoutResult(const uint64_t requestId, RTM_ERROR_CODE errorCode) {
        if (errorCode != RTM_ERROR_OK) {
          // logout failed
        } else {
          // logout success
        }
    }

    // ...
};
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
当不再需要使用 RTM 服务时，你可以通过显式调用 `logout` 退出登录。退出登录意味着客户端与 RTM 服务器关闭长连接，你会自动退出或取消订阅所有频道（Stream Channel 及 Message Channel），频道中的其他用户也会收到你的离开频道的 `didReceivePresenceEvent` 事件通知。

```swift
rtm.logout() { response, errorInfo in
    if errorInfo == nil {
        print("logout success!!")
    } else {
        print("logout failed, errorCode \(errorInfo?.errorCode), reason \(errorInfo?.reason)")
    }
}
```
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>

在离开应用时显式地执行退出登录操作是一种良好的实践。退出登录后，你就无法通过 API 访问 RTM 网络资源。

## 销毁 RTM 实例 [#销毁-rtm-实例]

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="android" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `RtmClient` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```java
mRtmClient.release();
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="ios" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `AgoraRtmClientKit` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```objc
[rtm destroy];
rtm = nil;
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="web" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `rtm` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="harmonyos" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `RtmClient` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```typescript
rtmClient.release();
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="unity" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `IRtmClient` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```csharp
var status = rtmClient.Dispose();
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="flutter" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `RtmClient` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```dart
var status = rtmClient.release();
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="cpp" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `IRtmClient` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```cpp
rtmClient->release();
```
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="web" platform="swift" />
如果你不再需要使用 RTM 服务，声网建议你及时销毁 `AgoraRtmClientKit` 实例，以避免内存泄漏，以及错误或异常（如空指针异常）导致性能下降。

```swift
rtm.destroy();
rtm = nil;
```
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
