即时通信 IM HarmonyOS(移动端)

TUIKit ArkUI 是基于腾讯云 IM SDK 的一套 鸿蒙 ArkUI 组件库,提供了聊天、会话列表、联系人管理等即时通信功能的完整解决方案。这里说明如何手动集成该组件并实现核心功能。完成本集成后,你的鸿蒙应用将具备聊天、会话列表、联系人管理等即时通信能力,并可选配音视频通话功能。

相关产品
即时通信 IM 产品页,含版本规格、价格与购买入口。

一、关键概念

TUIKit ArkUI 提供了一套完整的即时通信 UI 组件,向下依赖 AtomicXCore 数据层,向上可构建各种功能性 Page。

·Page 层:基于 TUIKit ArkUI 封装的完整功能页面:ChatPage、ContactsPage、ConversationsPage,可直接使用。

·TUIKit ArkUI(UI 组件层):基于 AtomicXCore 构建的 ArkUI 组件,可嵌套到已有的 App 页面中。

·AtomicXCore(数据层):提供数据管理和业务逻辑,包含各种 Store 和 Manager。

二、前提条件

·DevEco Studio 5.0 及以上版本。

·HarmonyOS SDK API 15 及以上版本。

·一个有效的腾讯云账号及 Chat 应用。可参见 开通服务 从控制台获取以下信息:

·SDKAppID:App 在控制台获取的 Chat 应用的 ID,为应用的唯一标识。

·SDKSecretKey:应用的密钥。

注意:说明:

注意:本项目目前仅支持手动集成,暂不支持通过 ohpm 管理器集成。

三、下载源码

从 CNB 下载 TUIKit Harmony 源码或者 GitHub 下载 TUIKit Harmony 源码:

git clone https://cnb.cool/tencent/cloud/trtc/TUIKit_Harmony// 或者 git clone https://github.com/Tencent-RTC/TUIKit_Harmony.git

项目目录结构说明:

atomic_x/ # TUIKit ArkUI(UI 组件层)│ ├── src/main/ets/│ │ ├── messagelist/ # 消息列表组件│ │ ├── messageinput/ # 消息输入组件│ │ ├── conversationlist/ # 会话列表组件│ │ ├── contactlist/ # 联系人列表组件│ │ ├── chatsetting/ # 聊天设置组件│ │ ├── basecomponent/ # 基础组件│ │ └── … # 其他UI组件│ └── src/main/resources/ # 资源文件chat/├── uikit/ # Page 层(参考实现)│ └── src/main/ets/pages/│ ├── ChatPage.ets # 聊天页面│ ├── ConversationsPage.ets # 会话列表页面│ └── ContactsPage.ets # 联系人页面└── demo/ # 示例应用(可选参考)│call/ # 音视频通话组件(推荐集成)└── tuicallkit/ # TUICallKit ArkUI,一行代码在聊天中拉起音视频通话

注意:说明:

注意:TUIKit_Harmony 是包含多个产品的开源仓库,Chat 的 UI 源码位于 chat/ 目录下(chat/uikit 为 UIKit 组件库,chat/demo 为示例工程),其依赖的基础组件 atomic_x 与音视频通话组件 call/ 位于仓库根目录。

四、集成组件

1. 将组件目录完整复制到你的鸿蒙项目中,如下所示,其中 chat/demo 是示例项目,atomic_x 是从 GitHub 上下载的组件源码,依赖关系如下:

2. 在项目 entry 的 oh-package.json5 中添加以下依赖:

注意:说明:

注意:atomic_x 可以放在任何位置,只要在 oh-package.json5 中正确设置相对路径即可。

{ "name": "entry", "version": "1.0.0", "description": "Please describe the basic information.", "main": "", "author": "", "license": "", "dependencies": { "@tencentcloud/atomicxcore": "^5.0.0", "@tencentcloud/atomicx": "file:../../../atomic_x", "chatuikit": "file:../../uikit", "@tencentcloud/tuicallkit": "file:../../../call", //其他依赖项 "@tencent/mmkv": "1.3.5", "@ohos/axios": "2.1.1", "dayjs": "^1.11.7" }, "devDependencies": { "pako": "^2.1.0", "@ohos/crypto-js": "^2.0.1" }}

3. oh-package.json5 修改完毕后,执行以下命令,安装本地 TUIKit 组件。示例:

ohpm install

ohpm install 会自动安装所需的依赖库。

五、配置项目

1. 配置 Build Settings

在项目的 Build Settings 中添加以下配置:

·Compatible SDK:5.0.3(15) 及以上

·项目签名配置

2. 配置 module.json5,路径如 “entry/src/main/module.json5”

添加必要的权限配置:

"requestPermissions": [ { "name": "ohos.permission.GET_NETWORK_INFO" }, { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.MICROPHONE", "reason": "$string:permission_microphone", "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" } }, { "name": "ohos.permission.CAMERA", "reason": "$string:permission_camera", "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" } } ]

3. 模块声明

已有项目集成源码后,需在 build-profile.json5 文件声明模块:

"modules": [ { "name": "entry", "srcPath": "./entry", "targets": [ { "name": "default", "applyToProducts": [ "default" ] } ] }, { "name": "atomic_x", "srcPath": "./atomic_x", //根据实际目录调整 "targets": [ { "name": "default", "applyToProducts": [ "default" ] } ] }, { "name": "chatuikit", "srcPath": "./chat/uikit" //根据实际目录调整 }, { "name": "tuicallkit", "srcPath": "./chat/call" //根据实际目录调整 } ]

4. EntryAbility 必须初始化

在 EntryAbility.ets 中需要完成 MMKV 与 ContextProvider 两个关键组件的初始化:

import { MMKV } from '@tencent/mmkv';import { ContextProvider } from '@tencentcloud/atomicx/src/main/ets/basecomponent/Index';import { TUICallKit } from '@tencentcloud/tuicallkit';export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 1. MMKV 初始化 MMKV.initialize(this.context.getApplicationContext()); // 2. ContextProvider 初始化 ContextProvider.init(this.context); } onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.loadContent('pages/SplashScreenPage', (err) => { TUICallKit.createInstance(this.context).attach(windowStage); }); } onWindowStageDestroy(): void { TUICallKit.createInstance(this.context).detach(); } onConfigurationUpdate(newConfig: Configuration): void { // 3.响应系统配置变更(深色模式、语言切换等) ContextProvider.onConfigurationUpdate(newConfig); }}

六、步骤1:配置用户鉴权

SDKAppID 需要在 即时通信 IM 控制台 创建并获取,userSig 需要按规则计算,详细步骤请参考文档 跑通 Demo。

为快速验证功能,你可以参考 TUIKit_Harmony 源码中 chat/demo/entry/src/main/ets/signature/GenerateTestUserSig.ts 的实现来生成 UserSig。请将该文件或类似逻辑复制到你的项目中,并填入以下参数:

·SDKAPPID:请设置为 步骤1 中获取的实际应用 SDKAppID。

·SECRETKEY:请设置为 步骤2 中获取的实际密钥信息。

七、步骤2:用户登录

登录组件后才能正常使用组件的功能。用户在 App 上点击登录时,可调用 LoginStore 登录 TUIKit ArkUI 组件。

示例代码如下所示:

import { LoginStore } from '@tencentcloud/atomicxcore';// 用户登录LoginStore.shared().login(SDKAPPID, this.userID, userSig, getContext()).then(() => { // login success }).catch((reason: Object) => { // login failed});

注意:警告:

注意:在正式的生产环境中,请在你的服务端生成 UserSig,在需要 UserSig 时由你的 App 向业务服务器发起请求获取动态 UserSig 来进行鉴权。详见 服务端生成 UserSig。

八、步骤3:构建会话列表界面

可基于 TUIKit ArkUI 中的 ConversationList 组件,构建一个会话列表页面。ConversationList 内建的功能是:

·展示用户的会话列表,包含单聊和群聊会话。

·支持用户操作单个会话:置顶、删除、清空会话消息等。

可将 ConversationList 直接集成到现有的 App 页面中,也可新构建一个完整的会话列表页,组装后的一种 UI 效果如下:

将 ConversationList 封装为会话列表页,可参考 chat/uikit/ConversationsPage.ets 文件里的实现,ConversationsPage 主要做了以下工作:

1. 在 ConversationList 上方添加了 headerView。

2. 实现点击会话列表 cell 事件。

3. 支持创建会话和群组功能:

3.1 点击右上角 "+" 按钮可以创建新会话或群组。

3.2 支持从联系人列表选择好友创建单聊。

3.3 支持选择多个好友创建群聊。

核心示例代码如下所示:

import { ConversationList } from '@tencentcloud/atomicx/src/main/ets/conversationlist/Index';import { ThemeState } from '@tencentcloud/atomicx/src/main/ets/basecomponent/Index';import { ConversationInfo } from '@tencentcloud/atomicxcore';@Componentexport struct ConversationsPage { @State showAddMenu: boolean = false; build() { Stack({ alignContent: Alignment.TopStart }) { Column() { this.LargeTitleBuilder() ConversationList({ onConversationClick: (item: ConversationInfo) => { // Customize onConversationClick event }, }) .layoutWeight(1) } .width('100%') .height('100%') .backgroundColor(this.themeState.colors.bgColorOperate) .onClick(() => { // Click + to show this menu. if (this.showAddMenu) { this.showAddMenu = false; } }) if (this.showAddMenu) { Row() .width('100%') .height('100%') .backgroundColor('rgba(0, 0, 0, 0)') .onClick(() => { this.showAddMenu = false; }) } if (this.showAddMenu) { this.AddMenuDialog() } } .width('100%') .height('100%') } @Builder LargeTitleBuilder() { Row() { Text($r('app.string.chat_title')) .fontSize(34) .fontWeight(FontWeight.Bold) .fontColor(this.themeState.colors.textColorPrimary) .layoutWeight(1) Row() { Image($r('app.media.new_chat_icon')) .width(24) .height(24) .onClick(() => { this.showAddMenu = true; }) } } .width('100%') .height(52) .padding({ left: 16, right: 16 }) .backgroundColor(this.themeState.colors.bgColorOperate) }}

九、步骤4:音视频通话

TUICallKit 的初始化分两个阶段:

1. 应用启动阶段(EntryAbility):在 onWindowStageCreate 中调用 TUICallKit.createInstance(this.context).attach(windowStage),以支持全局通话能力(参见上文「EntryAbility 必须初始化」)。

2. 登录成功后(业务页面):在业务页面(如 HomePage)中订阅 call.startCall 事件,即可在 Chat 组件中正常使用音视频通话功能。

如需开通音视频通话服务,请参考 开通音视频服务。

@Entry@Componentstruct HomePage { private callEventObserver?: TUIObserver; aboutToAppear(): void { // 初始化 CallKit 并订阅通话事件 TUICallKit.createInstance(getContext()); this.callEventObserver = new CallStartObserver(); TUIEventBus.getInstance().subscribe('call.startCall', null, this.callEventObserver); } aboutToDisappear(): void { if (this.callEventObserver) { TUIEventBus.getInstance().unsubscribe('call.startCall', null, this.callEventObserver); } }}class CallStartObserver implements TUIObserver { onNotify(event: string, _key: string | null, params: NotifyParams | null): void { if (event === 'call.startCall' && params?.data) { const data = params.data; const participantIds: string[] = (data['participantIds'] as string[]) ?? []; const chatGroupId: string = (data['chatGroupId'] as string) ?? ''; const timeout: number = (data['timeout'] as number) ?? 30; let callParams = new CallKitParams('', timeout, '', chatGroupId); TUICallKit.createInstance(getContext()).calls(participantIds, CallKitMediaType.video, callParams); } }}

十、步骤5:构建聊天界面

可基于 TUIKit ArkUI 中的 MessageList、MessageInput 组件,构建一个聊天页面。

·MessageList 内建的功能是:

·展示单聊或群聊消息列表。

·支持对单条消息操作:查看图片消息大图、播放视频或语音消息、复制文本消息、撤回消息、删除消息等。

·MessageInput 内建的功能是:

·支持用户组建并发送多种类型的消息:文本、表情、图片、语音、视频、文件等。

可将 MessageList 和 MessageInput 直接集成到现有的 App 页面中,也可新构建一个完整的聊天页,组装后的一种 UI 效果如下:

将 MessageList 和 MessageInput 组装为聊天页,可参考 chat/uikit/ChatPage.ets 文件里的实现,ChatPage 主要做了以下工作:

1. 在最上方添加了 headerView,展示会话的名称。

2. 按照移动端用户使用习惯,上下拼接 MessageList 和 MessageInput。

核心示例代码如下所示:

import { MessageList } from '@tencentcloud/atomicx/src/main/ets/messagelist/Index';import { MessageInput } from '@tencentcloud/atomicx/src/main/ets/messageinput/Index';import { Avatar, AvatarContentType, AvatarSize } from '@tencentcloud/atomicx/src/main/ets/basecomponent/Index';export struct ChatPage { … build() { Stack() { Column() { this.LargeTitleBuilder(); MessageList({ conversationID: this.conversationID, locateMessage: this.locateMessage, onUserClick: (userID: string) => { console.log(`[ChatPage] User avatar clicked: ${userID}`); } }) .width('100%') .layoutWeight(1) MessageInput({ conversationID: this.conversationID, }) } .width('100%') .height('100%') .backgroundColor(this.themeState.colors.bgColorOperate) .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM]) } .width('100%') .height('100%') } @Builder LargeTitleBuilder() { Column() { Row() { Row({ space: 8 }) { // Back button Image($rawfile('basecomponent/common_back_icon.svg')) .width(24) .height(24) .fillColor(this.themeState.colors.textColorSecondary) .onClick(() => { if (this.onBack) { this.onBack(); } }) Row({ space: 8 }) { // Avatar Avatar({ content: { type: AvatarContentType.Image, url: this.avatarUrl, name: this.title || '', }, avatarSize: AvatarSize.S, }) Column() { Text(this.title) .fontSize(14) .fontColor(this.themeState.colors.textColorPrimary) .fontWeight(FontWeight.Bold) .textAlign(TextAlign.Start) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) Text(this.status) .fontSize(12) .fontColor(this.themeState.colors.textColorTertiary) .fontWeight(FontWeight.Regular) .textAlign(TextAlign.Start) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) } .alignItems(HorizontalAlign.Start) .layoutWeight(1) .constraintSize({ maxWidth: '60%' }) } .layoutWeight(1) .onClick(() => { this.navigateToProfile(); }) } .layoutWeight(1) .alignItems(VerticalAlign.Center) } .width('100%') .height(56) .padding({ left: 10, right: 10 }) .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.SpaceBetween) // Divider Divider() .width('100%') .height(0.3) .color(this.themeState.colors.strokeColorSecondary) } .width('100%') .backgroundColor(this.themeState.colors.bgColorOperate) }}

十一、步骤6:构建联系人界面

可基于 TUIKit ArkUI 中的 ContactList 组件,构建一个联系人页面。ContactList 内建的功能是:

·查看好友申请列表。

·查看已加入的群列表。

·处理群组邀请和申请。

·管理黑名单列表。

·查看好友。

可将 ContactList 直接集成到现有的 App 中,也可新构建一个完整的联系人列表页,组装后的一种 UI 效果如下:

将 ContactList 封装为联系人列表页,可参考 chat/uikit/ContactsPage.ets 文件里的实现,ContactsPage 主要做了以下工作:

1. 在 ContactList 上方添加了 headerView

2. 实现点击联系人列表 cell 事件。

3. 支持添加联系人和添加群组:

3.1 点击右上角 "+" 按钮可以添加联系人或群组。

3.2 支持根据 UserID 搜索目标联系人。

3.3 支持根据 GroupID 搜索目标群组。

核心示例代码如下所示:

import { ContactInfo } from '@tencentcloud/atomicxcore';import { ContactList } from '@tencentcloud/atomicx/src/main/ets/contactlist/Index';export struct ContactsPage { … build() { Stack({ alignContent: Alignment.TopStart }) { Column() { this.LargeTitleBuilder() ContactList({ onContactClick: this.handleContactSelect, onGroupClick: this.handleGroupSelect, }) .layoutWeight(1) } .width('100%') .height('100%') .backgroundColor(this.themeState.colors.bgColorOperate) } .width('100%') .height('100%') } @Builder LargeTitleBuilder() { Row() { Text($r('app.string.contacts_title')) .fontSize(34) .fontWeight(FontWeight.Bold) .fontColor(this.themeState.colors.textColorPrimary) .fontFamily('PingFang HK') .layoutWeight(1) Row() { Image($r('app.media.new_chat_icon')) .width(24) .height(24) .onClick(() => { this.showAddMenu = true; }) } } .width('100%') .height(ContactsPage.LARGE_TITLE_HEIGHT) .padding({ left: 16, right: 16 }) .backgroundColor(this.themeState.colors.bgColorOperate) } …}

十二、步骤7:完善界面跳转逻辑

ConversationsPage、ChatPage、ContactsPage 中暴露了一些用户点击事件,可自定义事件来实现页面间的交互:

Page 回调 建议跳转逻辑
ConversationsPage onConversationClick: (ConversationInfo)?:(item: ConversationInfo) => void; 点击会话列表中的会话时触发,建议跳转到聊天页面(ChatPage)。
ContactsPage onContactClick?: (item: ContactInfo) => void; 点击联系人 cell 时触发,建议跳转联系人详情页面(C2CChatSetting)。
 onGroupClick?: (item: ContactInfo) => void; 点击群组 cell 时触发,建议跳转群聊页面(ChatPage)。
ChatPage onUserClick?: (userID: string) => void; 点击消息中的用户头像或昵称时触发,建议跳转用户信息页(C2CChatSetting)。
 onChatHeaderClick?: (conversationID:string) => void; 点击导航栏中的头像时触发,建议跳转用户信息页(C2CChatSetting)或群聊信息页(GroupChatSetting)
 onBack?: () => void; 点击返回按钮时触发,建议返回上一级页面。

/chat/demo/entry/src/main/ets/pages/HomePage.ets 作为上述 Page 的粘合层,实现了各个 Page 的回调事件,核心示例代码如下:

import { ConversationInfo, ContactInfo, MessageInfo } from '@tencentcloud/atomicxcore';// 点击会话列表 cell 跳转ConversationsPage({ onConversationClick: (item: ConversationInfo) => { this.handleConversationClick(item); }})// 点击联系人页面跳转ContactsPage({ onContactClick: (contact: ContactInfo) => { this.handleContactClick(contact); }, onGroupClick: (group: ContactInfo) => { this.handleGroupClick(group); }})// ChatDialog 是对 ChatPage 外层封装了导航栏的页面// onUserClick 和 onChatHeaderClick 的实现会透传到 ChatPage@CustomDialogexport struct ChatDialog { controller: CustomDialogController; conversationID: string = ''; title: string = ''; status: string = ''; avatarUrl: string = ''; locateMessage?: MessageInfo = undefined; onBack?: () => void; onUserClick?: (userID: string) => void; onChatHeaderClick?: (conversationID: string) => void; build() { ChatPage({ conversationID: this.conversationID, title: this.title, status: this.status, avatarUrl: this.avatarUrl, locateMessage: this.locateMessage, onBack: () => { if (this.onBack) { this.onBack(); } this.controller.close(); }, onUserClick: (userID: string) => { this.onUserClick(userID); }, onChatHeaderClick: (conversationID: string) => { this.onChatHeaderClick(conversationID); } }) }}

可参考上述回调说明及参考代码,实现 Page 之间交互逻辑。

十三、打包与集成方式

1. atomic_x.har 打包配置。

文件路径:atomic_x/oh-package.json5。

{ "name": "@tencentcloud/atomicx", ··· "dependencies": { "@tencentcloud/atomicxcore": "^5.0.0", "@tencentcloud/imsdk": "^9.0.7652", "@tencent/mmkv": "1.3.5" }}

2. chatuikit.har 打包配置。

文件路径:chat/uikit/oh-package.json5。

{ "name": "chatuikit", ··· "dependencies": { "@tencentcloud/atomicxcore": "^5.0.0", "@tencentcloud/atomicx": "file:./atomic_x.har" }}

3. Demo 应用入口依赖配置。

文件路径:chat/demo/entry/oh-package.json5。

"dependencies": { ··· "@tencentcloud/atomicxcore": "^5.0.0", "@tencentcloud/atomicx": "file:./atomic_x.har", "chatuikit": "file:./chatuikit.har", ··· }

4. 打开文件 chat/demo/build-profile.json5,删除 atomic_x、chatuikit 模块,点击 File > Invalidate Caches 执行 IDE 缓存清理。

5. 如果 demo 运行时资源报错 Error: Invalid resource ID: 0,是由于 HAR 集成时跨模块资源 id 映射为 0 导致,请修改 atomic_x 模块 getStringSync($r('app.string.xxx').id) → getStringByNameSync('xxx') 如下修改后,请注意按照步骤4清理缓存,重新打包集成。

– getContext().resourceManager.getStringSync($r('app.string.message_type_image').id);+ getContext().resourceManager.getStringByNameSync('message_type_image');

十四、功能常见问题

登录失败,提示签名错误

请检查 SDKAppID 和 UserSig 是否正确,UserSig 是否已过期。可以参考上文 配置用户鉴权 重新生成 UserSig。

如何移除音视频通话功能?

如果你不需要集成音视频通话功能,可按以下步骤完全移除:

·移除依赖:删除 entry/oh-package.json5 中 dependencies 里的 "@tencentcloud/tuicallkit":

·移除模块声明:删除 build-profile.json5 中 modules 里 tuicallkit 的条目。

·移除初始化代码:删除 EntryAbility 中 TUICallKit 的 attach / detach 调用,以及入口页(如 HomePage)中 TUICallKit.createInstance 与 call.startCall 事件的订阅代码。

十五、联系我们

如果你在接入或使用过程中有任何疑问或者建议,欢迎 联系我们 提交反馈。

赞 (0)
上一篇 4天前
下一篇 4天前