TUIRoomKit 是腾讯云提供的一站式多人音视频房间解决方案，集成了完整的 UI 组件和核心功能。通过本文档，开发者可以快速了解如何将 TUIRoomKit 集成到项目中，实现多人音视频房间功能。本文还将详细介绍如何快速替换图片资源、本地化文案等个性化配置，帮助开发者打造符合品牌特色的音视频应用。
| 房间准备页 | 标准房间主页 | 大型研讨会房间主页 | 成员管理 |
| --- | --- | --- | --- |
|  |  |  |  |

## 前提条件

### 开通服务

请参考 开通服务 领取 TUIRoomKit 体验版，并在 [应用管理](https://console.cloud.tencent.com/trtc) 页面获取以下信息：
- **SDKAppID**：应用标识（必填），腾讯云基于 SDKAppID 完成计费统计。

- **SDKSecretKey**：应用密钥，用于初始化配置文件的密钥信息。

### 环境准备
| 平台 | 版本 |
| --- | --- |
| Flutter | 3.29.3 及以上版本。 |
| Android | 最低兼容 Android 5.0 （SDK API Level 21）及以上版本。 |
| iOS | iOS 14.0 及更高。 |

## 快速接入

### 步骤1：集成 TUIRoomKit 组件

在您的工程 `pubspec.yaml` 文件中，添加 [tencent_conference_uikit](https://pub.dev/packages/tencent_conference_uikit)插件依赖。
``` yaml
dependencies:
    tencent_conference_uikit: 最新版本
```

执行以下命令安装组件：
``` plaintext
flutter pub get
```

### 步骤2：工程配置
- 使用 **Xcode **打开您的工程，选择**项目 **> **Build Settings **> **Deployment**，将其下的 **Strip Style** 设置为 `Non-Global Symbols`，以保留所需要的全局符号信息。

- 若您需要在 **iOS **端使用音视频功能，需要授权麦克风和摄像头的使用权限（`Android`端已在 SDK 中声明相关权限，您无需手动进行相关配置）。

   在您 App 的`Info.plist`（路径：`ios/Runner/Info.plist`）中添加以下两项，分别对应麦克风和摄像头在系统弹出授权对话框时的提示信息。

   ``` xml
   <key>NSCameraUsageDescription</key>
   <string>TUIRoomKit 需要访问您的相机权限</string>
   <key>NSMicrophoneUsageDescription</key>
   <string>TUIRoomKit 需要访问您的麦克风权限</string>
   ```

   完成以上添加后，在您的 **ios/Podfile **中添加以下预处理器定义，用于启用相机与麦克风权限。

   ``` ruby
   post_install do |installer|
     installer.pods_project.targets.each do |target|
       flutter_additional_ios_build_settings(target)
         target.build_configurations.each do |config|
           config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
         '$(inherited)',
         'PERMISSION_MICROPHONE=1',
         'PERMISSION_CAMERA=1',
         ]
       end
     end
   end
   ```

### 步骤3：配置页面导航和多语言功能

为了确保 TUIRoomKit 能够正常管理页面导航和显示多语言界面，需要在 Flutter 应用框架中进行以下配置：
- 在 `navigatorObservers` 中添加 `RoomNavigatorObserver.instance`，用于监听页面路由变化和管理组件生命周期。

- 在 `localizationsDelegates` 中添加相关本地化代理，确保界面文案能够根据系统语言正确显示。

- 使用 `ComponentTheme` 包裹在 `MaterialApp` 外层，确保所有 RoomKit 组件都能访问主题配置。

   以 MaterialApp 框架为例，示例代码如下：

   ``` java
   import 'package:tencent_conference_uikit/tencent_conference_uikit.dart';

   // 您自己的APP主类
   class XXX extends StatelessWidget {
     const XXX({super.key});

    @override
     Widget build(BuildContext context) {
       return ComponentTheme(  // 使用 ComponentTheme 包裹在 MaterialApp 外层，确保所有 RoomKit 组件都能访问主题配置。
         child: MaterialApp(
           // 添加 RoomKit 导航观察者，用于监听页面路由变化和生命周期管理
           navigatorObservers: [RoomNavigatorObserver.instance],
           // 添加本地化代理，支持多语言文案显示
           localizationsDelegates: [
             ...RoomLocalizations.localizationsDelegates,
             ...BarrageLocalizations.localizationsDelegates,
           ],
           supportedLocales: const [Locale('en'), Locale('zh')],
           // 您APP的其他配置
           ......
         ),
       );
     }
   }
   ```

   配置后，组件将支持多语言并能正确处理页面跳转。

### 步骤4：登录

代码集成完成后，需要完成登录操作，这是**使用 TUIRoomKit 的关键步骤**。只有在登录成功后，才能正常使用 TUIRoomKit 的各项功能，因此请仔细检查相关参数配置是否正确：

> **说明：**
>

> 在示例代码中，直接进行了登录接口的调用。但在实际项目场景下，强烈推荐**您在完成自己的用户身份验证等相关登录操作后，再调用 TUIRoomKit 的登录服务**。这样可以避免因过早调用登录服务，导致业务逻辑混乱或数据不一致的问题，同时也能更好地适配您项目中现有的用户管理和权限控制体系。
>

【Dart】
``` java
import 'package:atomic_x_core/atomicxcore.dart';  // TUIRoomKit内部有对atomic_x_core的依赖,这里直接import即可。

var loginResult = await LoginStore.shared.login(
    sdkAppID: 1400000001,    // 替换为您的 SDKAPPID
    userID: 'userID',        // 替换为您的 UserID
    userSig: 'userSig',      // 替换为您的 UserSig
);

if (loginResult.isSuccess) {
  // login success
} else {
  // login error
}
```

**登录接口参数说明：**
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `sdkAppID` | `int` | 从 [控制台](https://console.cloud.tencent.com/trtc) 获取，通常是以 `140` 或 `160` 开头的 10 位整数。 |
| `userID` | `String` | 当前用户的唯一 ID，仅包含英文字母、数字、连字符和下划线。为避免多端登录冲突，**请勿使用**`1`、`123`**等简单 ID**。 |
| `userSig` | `String` | 用于腾讯云鉴权的票据。更多信息请参见 如何计算及使用 UserSig。<br>【注意事项】<br>- 开发环境：可以采用本地 `GenerateTestUserSig.genTestSig` 函数生成 userSig 或者通过 [UserSig 辅助工具](https://console.cloud.tencent.com/im/tool-usersig) 生成临时的 userSig。<br>- 生产环境：为了防止密钥泄露，请务必采用服务端生成 userSig 的方式。详细信息请参考 服务端生成 UserSig。 |

### 步骤5：设置头像和昵称

首次登录的用户没有头像和昵称信息，需要通过 `LoginStore` 的 `setSelfInfo` 接口设置个人信息：
``` java
import 'package:atomic_x_core/atomicxcore.dart';

final result = await LoginStore.shared.setSelfInfo(
    userInfo: UserProfile(userID: 'userID', nickname: 'userName', avatarURL: 'avatarURL'),
);

if (result.isSuccess) {
    debugPrint("setSelfInfo success");
} else {
    debugPrint("setSelfInfo failed code:${result.errorCode}, message:${result.errorMessage}");
}
```

**setSelfInfo接口参数/返回值说明：**
| 参数/返回值 | 类型 | 说明 |
| --- | --- | --- |
| `userProfile` | `UserProfile` | 个人用户信息核心模型，包含：<br>- userID：要设置用户信息的用户 ID。<br>- nickname：昵称信息。<br>- avatarURL：头像链接。 |
| 返回值 | `Future<CompletionHandler>` | 设置个人信息接口的结果回调。若失败会返回错误码和错误信息。 |

### 步骤6：创建房间

在 `TUIRoomKit` 组件中，`RoomMainWidget` 是集成了完整的多人音视频房间功能的核心界面，以下将向开发者演示如何以房主身份将 `RoomMainWidget` 嵌入到应用中。

#### **实现方式：**
1. **构造进房的配置项**：进入房间后是否需要自动打开音视频设备的配置项。

2. **配置房间创建选项**：配置房间名称等信息。

3. **初始化房间主页面**：通过房主身份初始化房间主页面。

4. **导航到房间页面**：将 `RoomMainWidget` 推入导航栈。

   > **说明：**
   >

   > 移动端仅支持创建标准房间，如您需要创建大型研讨会房间，请参考 Web 快速接入 使用Web端创建。
   >

#### **示例代码：**
``` java
import 'package:tencent_conference_uikit/tencent_conference_uikit.dart';

// YourMainPage 代表您加载房间主页面的页面
class YourMainPage extends StatelessWidget {
  const YourMainPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => _createRoom(context),
          child: const Text('创建房间'),
        ),
      ),
    );
  }

  void _createRoom(BuildContext context) {
    // 1. 构造进房的配置项
    const config = ConnectConfig(
      autoEnableCamera: true,      // 进房后是否自动开启摄像头
      autoEnableMicrophone: true,  // 进房后是否自动开启麦克风
      autoEnableSpeaker: true,     // 进房后是否自动开启扬声器
    );

    // 2. 配置房间创建选项
    final options = CreateRoomOptions(
      roomName: 'roomName',  // 房间名称
    );

    // 3. 初始化房间主页面
    final behavior = RoomBehavior.create(options);

    // 4. 导航到房间页面
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => RoomMainWidget(
          roomID: 'roomID',
          behavior: behavior,
          config: config,
        ),
      ),
    );
  }
}
```

**RoomMainWidget 构造函数参数详细说明：**
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `roomID` | `String` | - 字符串类型的房间唯一标识符。<br>- 限制长度为 0-48 字节。<br>- 建议仅包含数字、英文字母（区分大小写）、下划线（_）和连字符（-）。避免使用空格和中文字符。 |
| `behavior` | `RoomBehavior` | - 房间主页面初始化来源。<br>- 参数含义：<br>- create: 房主身份创建房间，此方式需要构造创建房间配置项，关于CreateRoomOptions的详细用法请参考：CreateRoomOptions 结构体详细说明。<br>- enter：参与者身份加入房间。 |
| `config` | `ConnectConfig` | 进房后音视频设备控制的配置项。 |

**ConnectConfig 参数详细说明****：**
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| autoEnableMicrophone | `bool` | - 进房后是否自动开启麦克风。<br>- 参数含义：<br>- true: 自动开启 （默认值）。<br>- false: 不自动开启。 |
| autoEnableCamera | `bool` | - 进房后是否自动开启摄像头。<br>- 参数含义：<br>- true: 自动开启 （默认值）。<br>- false: 不自动开启。 |
| autoEnableSpeaker | `bool` | - 进房后是否自动开启扬声器。<br>- 参数含义：<br>- true: 自动开启 （默认值）。<br>- false: 不自动开启。 |

### 步骤7：加入房间

以下示例将向开发者演示如何以参与者身份将`RoomMainWidget`嵌入到应用中。

#### **实现方式：**
1. **构造进房的配置项**：进入房间后是否需要自动打开音视频设备的配置项。

2. **初始化房间主页面**：通过参与者身份初始化房间主页面。

3. **导航到房间页面**：将 `RoomMainWidget` 推入导航栈。

#### 代码示例：
``` java
import 'package:tencent_conference_uikit/tencent_conference_uikit.dart';

// YourMainPage 代表您加载房间主页面的页面
class YourMainPage extends StatelessWidget {
  const YourMainPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => _enterRoom(context),
          child: const Text('加入房间'),
        ),
      ),
    );
  }

  void _enterRoom(BuildContext context) {
    // 1. 构造进房的配置项
    const config = ConnectConfig(
      autoEnableCamera: true,      // 进房后是否自动开启摄像头
      autoEnableMicrophone: true,  // 进房后是否自动开启麦克风
      autoEnableSpeaker: true,     // 进房后是否自动开启扬声器
    );

    // 2. 初始化房间主页面
    const behavior = RoomBehavior.enter();

    // 3. 导航到房间页面
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => RoomMainWidget(
          roomID: 'roomID',
          behavior: behavior,
          config: config,
        ),
      ),
    );
  }
}
```

**参数详细说明请参考：**

[RoomMainWidget 构造函数参数详细说明]( 构造函数参数详细说明)和 [ConnectConfig 参数详细说明]( 参数详细说明)

> **说明：**
>

> 使用TUIRoomKit组件进入大型研讨会房间时，需确保Web端创建的研讨会房间的房间ID以 `webinar_` 开头。
>

## 核心功能

接入`RoomMainWidget`代码后，开发者将得到一个完整的多人音视频页面，内部包含成员管理，音视频设备控制，房间信息展示等功能，这是 `TUIRoomKit` 组件的核心。
| 标准房间 | 大型研讨会房间 |
| --- | --- |
|  |  |

## 界面定制

> **注意：**
>

> 界面定制、图标定制、文案定制这部分章节内容，涉及到需要修改 TUIRoomKit 组件源码，通过 pub 依赖管理器集成 TUIRoomKit 为"不可变"的依赖项。每次执行 flutter pub get 时，Flutter 会：
>
> 1. 检查 pubspec.lock 中记录的版本号。
> 2. 从远程仓库重新下载对应版本的源码。
> 3. 用下载的原始代码覆盖 .pub-cache/ 目录下的现有文件。

> **因此，任何对缓存目录的手动修改都只是临时性的，下次执行安装命令时即被还原。**
>

>
>

> **推荐解决方案：**
>
> 1. Fork [TUIKit_Flutter](https://github.com/Tencent-RTC/TUIKit_Flutter/tree/main) 的官方仓库。
> 2. 在 fork 的仓库中修改并提交。
> 3. 修改 pubspec.yaml ，指向**自定义仓库和分支。**
> `dependencies:`
> `  tencent_conference_uikit:`
> `    git:`
> `      url: https://github.com/your-username/TUIKit_Flutter.git`
> `      ref: your-branch`
> `      path: room`

`RoomMainWidget`房间主页面内功能丰富，可定制化度高，开发者可以根据实际产品需求，对 UI 进行定制化修改，以适配业务交互场景。以下将详细为开发者展示`RoomMainWidget`页面中视图组件，便于开发者快速修改。
| 标准房间 | 大型研讨会房间 |
| --- | --- |
|  |  |

`RoomMainWidget`**中组件详细说明**
| 组件 | 功能描述 | 定制化建议 |
| --- | --- | --- |
| [RoomMainWidget](https://github.com/Tencent-RTC/TUIKit_Flutter/blob/main/room/lib/widget/room_main_widget.dart) | 房间主视图容器，负责协调各子组件的布局与数据流转。 | 可调整整体背景、安全区域适配、组件显隐逻辑。 |
| [RoomTopBarWidget](https://github.com/Tencent-RTC/TUIKit_Flutter/blob/main/room/lib/widget/main/room_top_bar_widget.dart) | 顶部导航栏，包含房间信息、摄像头和声音控制、退出房间功能入口。 | 可替换图标、调整背景透明度、添加自定义按钮（如录制、 窗口化）。 |
| [RoomWidget](https://github.com/Tencent-RTC/TUIKit_Flutter/blob/main/room/lib/widget/main/room_widget.dart) | 视频流展示区域，采用瀑布流布局管理多个用户视频画面。 | 可修改布局算法（行列数、间距）、分页指示器样式、空状态视图。 |
| [ParticipantVideoItemWidget](https://github.com/Tencent-RTC/TUIKit_Flutter/blob/main/room/lib/widget/main/room_widget/participant_video_item_widget.dart) | 单个视频流单元格，承载用户视频画面与基本信息。 | 可自定义视频渲染层、用户信息面板（头像、徽章）、互动控件（语音波形）。 |
| [RoomBottomBarWidget](https://github.com/Tencent-RTC/TUIKit_Flutter/blob/main/room/lib/widget/main/room_bottom_bar_widget.dart) | 底部工具栏，集成麦克风、摄像头、成员管理操作按钮。 | 可重新排列按钮顺序、修改按钮样式（颜色、尺寸）、添加业务相关功能（如屏幕分享、会中呼叫、美颜）。 |

## 图标定制

接入 TUIRoomKit 组件后，开发者可以根据实际 UI 交互需求直接替换组件下的图标资源，以适配开发者的业务场景。

TUIRoomKit 使用 `assets/images/` 目录管理 UI 所需的图片资源，您可以直接替换该目录下的图片文件来自定义界面所需的图标。

**常用的图片文件列表**
| 图标 | 文件名 | 说明 |
| --- | --- | --- |
|  | room_camera_off.png | 摄像头关闭图标 |
|  | room_camera_on.png | 摄像头开启图标 |
|  | room_mic_off.png | 麦克风关闭图标 |
|  | room_mic_on_empty.png | 麦克风开启图标 |
|  | room_administrator_icon.png | 管理员身份标识图标 |
|  | room_owner_icon.png | 房主身份标识图标 |

## 文案定制

TUIRoomKit 使用 Flutter 标准的 ARB 文件来管理 UI 所需的文案显示，您可以直接修改 `lib/base/language/i10n/` 目录下的语言文件来调整需要的文案：

## 常见问题

### 每次进房都需要调用登录吗？

不需要。通常您只需要完成一次 `LoginStore.shared.login` 调用即可，我们建议您将 `LoginStore.shared.login` 和

`LoginStore.shared.logout` 与自己的登录业务关联。

### iOS在release下运行/打包后无法进房？

使用 Xcode 打开您的工程，选择项目 > Build Settings > Deployment，将其下的 Strip Style 设置为 `Non-Global Symbols`，以保留所需要的全局符号信息。

### pubspec.yaml文件有没有示例配置可以参考？

您可以参考 [GitHub TUIKit_Flutter Example](https://github.com/Tencent-RTC/TUIKit_Flutter/tree/main/application) 工程 `pubspec.yaml` 示例文件。

### 进房后无画面？

请前往**手机设置** > **App >****相机**，检查摄像头权限是否开启，可参考如下示例：
| iOS | Android |
| --- | --- |
|  |  |
