`RoomStore` 是 `AtomicXCore` 中专职房间事务管理的模块，深度集成了会中呼叫能力。本章节旨在指导如何利用 `RoomStore` 高效完成会中呼叫相关功能的开发与接入。

## 核心功能
- **会中呼叫**：房间内任意参与者均可呼叫房间外任意成员加入房间。

- **获取会中呼叫用户列表**：可以获取指定房间的会中呼叫的用户列表。

## 核心概念

在开始集成之前，需要通过下表了解一下`RoomStore`中与会中呼叫相关的几个核心概念：
| **核心概念** | **类型** | **核心职责与描述** |
| --- | --- | --- |
| [RoomCallStatus](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-call-status/index.html) | `enum class` | 代表会中呼叫的状态，包含：<br>- `NONE`（默认态）。<br>- `CALLING`（呼叫中）。<br>- `TIMEOUT`（呼叫超时）。<br>- `REJECTED`（呼叫被拒绝）。 |
| [RoomCallResult](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-call-result/index.html) | `enum class` | 代表会中呼叫的结果，包含：<br>- `SUCCESS`（呼叫成功）。<br>- `ALREADY_IN_CALLING`（已在呼叫中）。<br>- `ALREADY_IN_ROOM`（已在房间中）。 |
| [CallRejectionReason](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-call-rejection-reason/index.html) | `enum class` | 代表呼叫被拒绝的原因，目前仅支持：<br>- `REJECTED`当有其他用户向被呼叫方发起入会邀请时触发（主动拒绝）。<br>- `IN_OTHER_ROOM`（在其他房间中）。 |
| [RoomCall](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-call/index.html) | `data class` | 代表会中呼叫业务的核心数据结构。负责存储呼叫者信息、被呼叫者信息、以及当前呼叫状态。 |
| [RoomListener](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/index.html) | `abstract class` | 代表房间动态的实时事件。其中包含会中呼叫相关的事件。 |
| [RoomStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-store/index.html) | `abstract class` | 这是与房间全生命周期相关的核心类。功能包含：发起会中呼叫，响应会中呼叫，获取房间的会中呼叫列表，并通过订阅其 `RoomListener` 来接收与会中呼叫相关的实时动态事件。 |

## 实现步骤

### 步骤1：组件集成

请参考 接入概览 集成 **AtomicXCore SDK**，并已完成 实现登录逻辑 部分接入。

### 步骤2：呼叫方功能

#### **1. 发起呼叫**

作为呼叫方，调用`RoomStore`的`callUserToRoom`接口，可以批量呼叫用户进房。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.room.CallUserToRoomCompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomCallResult
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

private val roomID = "test_room_001"

// 呼叫用户加入房间
fun callUserToRoom(userIDList: List<String>, timeout: Int = 30, extensionInfo: String? = null) {
    RoomStore.shared()
        .callUserToRoom(roomID, userIDList, timeout, extensionInfo, object : CallUserToRoomCompletionHandler {
            override fun onSuccess(result: Map<String, RoomCallResult>) {
                Log.d("Room", "呼叫用户请求发送成功")
            }

            override fun onFailure(code: Int, desc: String) {
                Log.d("Room", "呼叫用户失败: [错误码: $code]: $desc")
            }
        })
}
```

#### **2. 取消呼叫**

作为呼叫方，调用`RoomStore`的`cancelCall`接口，也可以批量取消正在进行的呼叫申请。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

private val roomID = "test_room_001"

// 取消呼叫
fun cancelCall(userIDList: List<String>) {
    RoomStore.shared().cancelCall(roomID, userIDList, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room", "取消呼叫成功")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "取消呼叫失败: [错误码: $code]: $desc")
        }
    })
}
```

#### **3. 获取呼叫列表信息**

进入房间后，调用`RoomStore`的`getPendingCalls`接口，可以分页查询当前房间正在呼叫的用户列表信息。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.ListResultCompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomCall
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

private val roomID = "test_room_001"

// 获取待处理的呼叫列表
fun getPendingCalls(roomID: String, cursor: String?) {
    RoomStore.shared().getPendingCalls(roomID, cursor, object : ListResultCompletionHandler<RoomCall> {
        override fun onSuccess(result: List<RoomCall>, cursor: String) {
            Log.d("Room", "获取呼叫列表成功，列表信息: $result, 分页游标: $cursor")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "获取呼叫列表失败: [错误码: $code]: $desc")
        }
    })
}
```

#### **4. 订阅会中呼叫事件**

作为呼叫方，订阅 `RoomStore` 的 `RoomListener` 能够实时获取呼叫的生命周期事件。通过监听以下回调，可以精准捕捉呼叫的最终结果并据此更新 UI 状态或执行后续业务逻辑。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.room.CallRejectionReason
import io.trtc.tuikit.atomicxcore.api.room.RoomCall
import io.trtc.tuikit.atomicxcore.api.room.RoomInfo
import io.trtc.tuikit.atomicxcore.api.room.RoomListener
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

// 订阅会中呼叫相关事件
fun subscribeRoomCallEvents() {
    RoomStore.shared().addRoomListener(object : RoomListener() {
        override fun onCallTimeout(roomInfo: RoomInfo, call: RoomCall) {
            Log.d("Room", "呼叫超时 房间信息: $roomInfo, 呼叫者: ${call.caller}")
        }

        override fun onCallAccepted(roomInfo: RoomInfo, call: RoomCall) {
            Log.d("Room", "呼叫已被接受 房间信息: $roomInfo, 被呼叫者: ${call.callee}")
        }

        override fun onCallRejected(roomInfo: RoomInfo, call: RoomCall, reason: CallRejectionReason) {
            Log.d("Room", "呼叫被拒绝 房间信息: $roomInfo, 被呼叫者: ${call.callee}, 拒绝原因: $reason")
        }

        override fun onCallHandledByOtherDevice(roomInfo: RoomInfo, isAccepted: Boolean) {
            Log.d("Room", "呼叫已被其他设备处理 房间信息: $roomInfo 处理结果: $isAccepted")
        }
    })
}
```

**呼叫事件函数详细说明**
| 事件函数 | 触发时机与说明 |
| --- | --- |
| [onCallTimeout](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-timeout.html) | 呼叫超时。当呼叫请求在预设的时间内（由调用 callUserToRoom 时指定）未得到被呼叫方的响应时触发。此时，呼叫自动结束，呼叫方通常需要提示“对方无人接听”。 |
| [onCallAccepted](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-accepted.html) | 呼叫被接受。被呼叫方主动点击了“接听”或“接受”按钮。收到此回调后，表示双方已达成呼叫意图，呼叫方通常应立即执行进入房间或开始推流的操作。 |
| [onCallRejected](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-rejected.html) | 呼叫被拒绝。被呼叫方主动拒绝了通话请求，或者因为被呼叫方当前正处于其他房间中而自动拒绝。回调中通常包含拒绝原因（例如主动拒绝或在其他房间中）。 |
| [onCallHandledByOtherDevice](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-handled-by-other-device.html) | 呼叫已在其他设备处理。当用户在多个设备（如手机和 iPad）同时登录时，如果呼叫已在其中一台设备上被处理（接受或拒绝），当前设备会收到此通知，用于同步 UI 状态并自动消除呼叫界面。 |

### 步骤3：被呼叫方功能

#### **1. 订阅会中呼叫事件**

作为被呼叫方，订阅 `RoomStore` 的 `RoomListener` 可以实时监听并响应来自呼叫方的呼叫行为。以下是构建呼叫提醒界面以及维护呼叫链路状态的关键事件。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.room.RoomCall
import io.trtc.tuikit.atomicxcore.api.room.RoomInfo
import io.trtc.tuikit.atomicxcore.api.room.RoomListener
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
import io.trtc.tuikit.atomicxcore.api.room.RoomUser

// 订阅会中呼叫相关事件
fun subscribeRoomCallEvents() {
    RoomStore.shared().addRoomListener(object : RoomListener() {
        override fun onCallReceived(roomInfo: RoomInfo, call: RoomCall, extensionInfo: String) {
            Log.d("Room", "收到房间呼叫 房间信息: $roomInfo, 呼叫者: ${call.caller}, 扩展信息: $extensionInfo")
        }

        override fun onCallCancelled(roomInfo: RoomInfo, call: RoomCall) {
            Log.d("Room", "呼叫被取消 房间信息: $roomInfo, 呼叫者: ${call.caller}")
        }

        override fun onCallRevokedByAdmin(roomInfo: RoomInfo, call: RoomCall, operator: RoomUser) {
            Log.d("Room", "呼叫被管理员移除 房间信息: $roomInfo, 呼叫者: ${call.caller}, 移除操作者: $operator")
        }
    })
}
```

**事件函数详细说明**
| 事件函数 | 触发时机与说明 |
| --- | --- |
| [onCallReceived](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-received.html) | 收到呼叫邀请。当有其他用户向您发起入会邀请时触发。收到此回调后，被呼叫方通常应立即弹出“呼叫提醒”界面，展示呼叫者信息、房间信息，并提供“接听”和“拒绝”按钮。 |
| [onCallCancelled](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-cancelled.html) | 呼叫被发起方取消。呼叫方在被呼叫方callUserToRoom未做出响应前，主动撤回了呼叫请求。收到此回调后，被呼叫方应立即关闭当前的来电界面，并提示“对方已取消呼叫”，以恢复应用正常操作流程。 |
| [onCallRevokedByAdmin](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/on-call-revoked-by-admin.html) | 呼叫被管理员撤销。房间管理员或后台系统因权限变更、房间解散等原因强行终止了该笔呼叫邀请。收到此通知后，被呼叫方需立即停止呼叫流程并隐藏相关 UI，处理逻辑通常类似于呼叫被取消。 |

#### **2. 接受呼叫、拒绝呼叫**

作为被呼叫方，调用`RoomStore`的`acceptCall`或者`rejectCall`接口，处理接受或者拒绝呼叫邀请。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.CallRejectionReason
import io.trtc.tuikit.atomicxcore.api.room.RoomCall
import io.trtc.tuikit.atomicxcore.api.room.RoomInfo
import io.trtc.tuikit.atomicxcore.api.room.RoomListener
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

// 订阅会中呼叫相关事件
fun subscribeRoomCallEvents() {
    RoomStore.shared().addRoomListener(object : RoomListener() {
        override fun onCallReceived(roomInfo: RoomInfo, call: RoomCall, extensionInfo: String) {
            Log.d("Room", "收到房间呼叫 房间信息: $roomInfo, 呼叫者: ${call.caller}, 扩展信息: $extensionInfo")
            // 接受、拒绝呼叫邀请操作
        }
    })
}

// 接受呼叫邀请
fun acceptCall(roomID: String) {
    RoomStore.shared().acceptCall(roomID, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room", "接受呼叫成功，房间ID: $roomID")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "接受呼叫失败: [错误码: $code] $desc")
        }
    })
}

// 拒绝呼叫邀请
fun rejectCall(roomID: String, reason: CallRejectionReason = CallRejectionReason.REJECTED) {
    RoomStore.shared().rejectCall(roomID, reason, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room", "拒绝呼叫成功，房间ID: $roomID")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "拒绝呼叫失败: [错误码: $code] $desc")
        }
    })
}
```

## API 文档
| **Store/Component** | **功能描述** | **API文档** |
| --- | --- | --- |
| **RoomStore** | 房间全生命周期管理：创建并加入 / 加入 / 离开 / 结束房间 / 更新、获取房间信息 / 房间预约 / 呼叫房间外成员 / 监听房间内被动事件（例如房间解散，房间信息更新等）。 | [API 文档](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-store/index.html) |
