组件名 | 组件功能 |
会话列表组件 | |
核心聊天组件 | |
添加好友 及 添加群组 组件 | |
黑名单列表 及 新的联系人申请列表 组件 | |
好友列表 及 群组列表 组件 | |
用户信息 及 群组信息 组件 | |
全局搜索/会话内搜索组件 |
环境 | 版本 |
Flutter | 最低要求 Flutter 3.0.0 版本,Dart 2.17.0 版本。 |
Android | Android Studio Dolphin | 2021.3.1 及以上版本,Android Gradle plugin 4.1.0 以上版本。 |
iOS | Xcode 12.0 及以上版本,请确保您的项目已设置有效的开发者签名。 |
平台 | 支持状态 |
iOS | 支持 |
Android | 支持 |
Web | 支持,0.1.5版本起 |
macOS | 支持,2.0.0 版本起 |
Windows | 支持,2.0.0 版本起 |
混合开发 (将 Flutter SDK 添加至现有原生应用) | 1.0.0版本起支持 |
SDKAppID
。UserID
、签名(Key)
、UserSig
这三个,后续登录时会用到。
android/app/src/main/AndroidManifest.xml
,在 <manifest></manifest>
中,添加如下权限。<uses-permissionandroid:name="android.permission.INTERNET"/><uses-permissionandroid:name="android.permission.RECORD_AUDIO"/><uses-permissionandroid:name="android.permission.FOREGROUND_SERVICE"/><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permissionandroid:name="android.permission.VIBRATE"/><uses-permissionandroid:name="android.permission.ACCESS_BACKGROUND_LOCATION"/><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permissionandroid:name="android.permission.CAMERA"/><uses-permissionandroid:name="android.permission.READ_MEDIA_IMAGES"/><uses-permissionandroid:name="android.permission.READ_MEDIA_VIDEO"/>
ios/Podfile
,在文件末尾新增如下权限代码。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['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'config.build_settings['ENABLE_BITCODE'] = 'NO'config.build_settings["ONLY_ACTIVE_ARCH"] = "NO"endtarget.build_configurations.each do |config|config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)','PERMISSION_MICROPHONE=1','PERMISSION_CAMERA=1','PERMISSION_PHOTOS=1',]endendend
tencent_cloud_chat_uikit
,而不需要再安装基础 IM SDK。flutter pub add tencent_cloud_chat_uikit
TIMUIKitCore.getInstance()
,再调用初始化函数 init()
,并将您的sdkAppID
传入。/// main.dartimport 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();@overridevoid initState() {_coreInstance.init(sdkAppID: 0, // Replace 0 with the SDKAppID of your IM application when integrating// language: LanguageEnum.en, // 界面语言配置,若不配置,则跟随系统语言loglevel: LogLevelEnum.V2TIM_LOG_DEBUG,onTUIKitCallbackListener: (TIMCallback callbackValue){}, // [建议配置,详见此部分](https://www.tencentcloud.com/document/product/269/70746?from_cn_redirect=1#callback)listener: V2TimSDKListener());super.initState();}}
_coreInstance.login
方法,登录一个测试账户。import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();_coreInstance.login(userID: userID, userSig: userSig);
UserSig
签发方式是由服务器端生成,并提供面向 App 的接口,在需要 UserSig
时由 App 向业务服务器发起请求获取动态 UserSig
。更多详情请参见 服务端生成 UserSig。onTapItem
事件的处理函数,用于跳转至具体会话聊天页的导航。关于 Chat
类,会在下一步讲解。import 'package:flutter/material.dart';import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';class Conversation extends StatelessWidget {const Conversation({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Message",style: TextStyle(color: Colors.black),),),body: TIMUIKitConversation(onTapItem: (selectedConv) {Navigator.push(context,MaterialPageRoute(builder: (context) => Chat(selectedConversation: selectedConv,),));},),);}}
onTapAvatar
事件的处理函数,用于跳转至联系人的详细信息页。关于 UserProfile
类,会在下一步讲解。import 'package:flutter/material.dart';import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';class Chat extends StatelessWidget {final V2TimConversation selectedConversation;const Chat({Key? key, required this.selectedConversation}) : super(key: key);String? _getConvID() {return selectedConversation.type == 1? selectedConversation.userID: selectedConversation.groupID;}@overrideWidget build(BuildContext context) {return TIMUIKitChat(conversation: selectedConversation,onTapAvatar: (_) {// 如果需要适配桌面端,此处需要参考 Demo 代码修改。Navigator.push(context,MaterialPageRoute(builder: (context) => UserProfile(userID: userID),));}, // Callback for the clicking of the message sender profile photo. This callback can be used with `TIMUIKitProfile`.);}
V2TimConversation selectedConversation
会话对象。此时,您可根据以下方法,手动 new 一个 V2TimConversation
对象实例,传入 TIMUIKitChat 组件中。TIMUIKitChat(conversation: V2TimConversation(conversationID: "c2c_10040818", // 单聊:"c2c_${对方的userID}" ; 群聊:"group_${groupID}"userID: "", // 仅单聊需要此字段,对方userIDgroupID: "", // 仅群聊需要此字段,群groupIDshowName: "", // 顶部 AppBar 显示的标题type: 1, // 单聊传1,群聊传2// 以上是最简化最基础的必要配置,您还可在此指定更多参数配置,根据 V2TimConversation 的注释),// ......其他 TIMUIKitChat 的配置参数);
userID
的情况下,自动根据是否是好友,生成用户详情页。profileWidgetBuilder
传入需自定义的 profile 组件并配合 profileWidgetsOrder
确定纵向排列顺序;如果无法满足,才可使用 builder
。import 'package:flutter/material.dart';import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';class UserProfile extends StatelessWidget {final String userID;const UserProfile({required this.userID, Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Message",style: TextStyle(color: Colors.black),),),body: TIMUIKitProfile(userID: widget.userID,),);}}
context
,仅在应用启动后第一次执行时需要。import 'package:tencent_cloud_chat_uikit/ui/utils/screen_utils.dart';final isDesktopScreen = TUIKitScreenUtils.getFormFactor(context) == DeviceType.Desktop;
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';final bool isAndroid = PlatformUtils().isAndroid; // 判断当前是否是 Android 设备final bool isWeb = PlatformUtils().isWeb; // 判断当前是否是网页final bool isIOS = PlatformUtils().isIOS; // 判断当前是否是 iOS 设备final bool isWindows = PlatformUtils().isWindows; // 判断当前是否是 Windows 桌面系统final bool isMacOS = PlatformUtils().isMacOS; // 判断当前是否是 macOS 桌面系统final bool isMobile = PlatformUtils().isMobile; // 判断当前是否是手机 app 应用,包含了 Android 及 iOS 设备。final bool isDesktop = PlatformUtils().isDesktop; // 判断当前是否是桌面端应用,包含了 Windows 及 macOS 系统。
Widget
。例如,一个组件在移动端需要占据整个页面,具备相应的 Scaffold
和 Appbar
,而在桌面端,仅需作为一个 Modal
弹窗。针对这种场景,我们开发了一个通用的 TUIKitScreenUtils.getDeviceWidget()
方法,传入移动端和桌面端的组件,根据平台类型自动返回对应的组件。TUIKitScreenUtils.getDeviceWidget(desktopWidget: Container(), // 桌面端 Widget。defaultWidget: Container(), // 默认 Widget,必传。当对应平台的 Widget 没有传入时,用此 Widget 兜底。mobileWidget: Container(), // 移动端 Widget。);
Scaffold
和 Appbar
,而在桌面端则不需要。可以将核心组件部分抽离,使用该方法为移动端添加一个 Scaffold
框架,而桌面端则不需要该框。示例代码如下:@overrideWidgetbuild(BuildContext context) {Widget widgetBody() {return const TIMUIKitBlackList(); // 这里替换成实际需要展示的 Widget}return TUIKitScreenUtils.getDeviceWidget(desktopWidget: widgetBody(), // 桌面端直接展示组件defaultWidget: Scaffold( // 如非特殊情况,移动端可以使用 defaultWidget 默认,包含 ScaffoldappBar: AppBar(),body: widgetBody(),));}
TIMUIKitChat
外还不包含 Scaffold
和 Appbar
。Scaffold
和 Appbar
,并监听暴露出来的点击事件和其他需要跳转的事件,处理 Navigator.push()
跳转。TIMUIKitConversation
会话列表组件的 onTapItem
点击某个会话的事件回调,跳转至具体某个会话聊天页面。TIMUIKitConversation(onTapItem: (selectedConv) {Navigator.push(context,MaterialPageRoute(builder: (context) => Chat(selectedConversation: selectedConv,),));});
Scaffold
和 Appbar
。因 TIMUIKitChat
的顶部 Appbar 逻辑较为复杂,例如包含 “对方正在输入中” 及 “未读数” 展示等等功能,因此TIMUIKitChat
包含了 Scaffold
和 Appbar
,其余一级组件不包含。Scaffold
和 Appbar
。Appbar
,您可通过配置主题的方式,配置 appbarBgColor
appbarTextColor
chatHeaderBgColor
chatHeaderTitleTextColor
等参数以自定义颜色及样式。Navigator.push()
导航路由的方式切换不同组件及页面,桌面端不太适合频繁进行整体的导航。左侧 Tab icon | 右侧模块内容 |
聊天 | 会话列表 + 每个具体的聊天 + 联系人信息 + 群组信息 |
通讯录 | (联系人列表 or 群组列表) + (联系人 or 群组详情) |
我的 | 设置 or 配置个人信息 |
头像 | 配置个人信息 |
index
用于确定当前所在页面,左侧防止一个 LeftBar 用于切换 Tab;右侧放置一个使用 Expand
撑开的 IndexedStack
放置核心页面内容。Expand(IndexedStack)
部分,的架构布局设计实践。dart
文件,用于放置 ConversationAndChat
Widget 类,用于承载本部分业务逻辑。Chat
, Conversation
, UserProfile
组件,并基本保持这几个用于承载一级组件的 class 代码不变。ConstrainedBox
用于限制宽度的 Conversation
组件,右侧可用 Expand
撑开放置 Chat
组件。此外,还可以 Stack
配合 AnimatedPositioned
动画修改位置的形式,在最右侧浮动一个 UserProfile
或 GroupProfile
组件,用于点击查看联系人或群组详情,在点击时从屏幕外侧进入,并在用完后,回到屏幕外侧。ConversationAndChat
类需要包含状态,记录当前的 V2TimConversation? currentConversation
会话。onConversationChanged
事件,并将当前切换至的会话,通过 setState
的方式,记录,并传入 Chat
组件,用于更改当前右侧显示的会话聊天。ContactsAndProfile
Widget 类,用于承载本部分业务逻辑。ConstrainedBox
和 Expand
使用。左侧 ConstrainedBox
用于放置 Contact
及 GroupList
等列表组件,右侧 Expand
用于放置 UserProfile
或 GroupProfile
等信息组件。UserProfile
组件,增加一个自定义按钮和一个 onClickSendMessage
方法,用于将用户点击这个自定义按钮的点击事件抛出。具体如何配置参考 Demo 此文件代码。ContactsAndProfile
组件的位置,监听这个事件,维护一份在 state 中,并转发至 ConversationAndChat
Widget 中。Demo 代码didUpdateWidget
动态刷新外部传入的 V2TimConversation
会话,更新当前聊天页面和会话列表所在的会话。Demo 代码Conversation
组件类新增一个 directToChat
方法,让外部可以指定当前所在的会话,以更新展示当前选中的样式。(默认选中的会话是蓝色背景,未选中白色背景,置顶灰色背景)。Demo 代码import 'package:tencent_cloud_chat_uikit/ui/widgets/wide_popup.dart';TUIKitWidePopup.showPopupWindow(context: context,title: Modal名称,operationKey: TUIKitWideModalOperationKey.custom,width: MediaQuery.of(context).size.width * 0.4, // 宽度height: MediaQuery.of(context).size.width * 0.5, //高度child: (onClose) => 具体要展示的内部组件(groupID: groupID,controller: _chatController,onClosed: onClose,),);
TIMUIKitConfig
的 showDesktopModalFunc
方法,并根据提供的参数(如点击确认事件回调 /当前的操作类型 operationKey
/ 位置)等信息,构建您自己的弹窗。operationKey
字段给您当前弹窗的场景,如果根据 operationKey
判定当前弹窗类型,您需要自定义弹窗,请返回 true
否则返回 false
使用 TUIKit 默认 Modal 弹窗。TUIKitWidePopup.showSecondaryConfirmDialog()
方法即可。参数和配置可查看注释说明。TUIKitWidePopup.showPopupWindow()
使用。 TUIKitColumnMenu
菜单列表组件,其中每个菜单项都是一个 ColumnMenuItem
组件,可以定义菜单项的显示 label
文字,左侧 icon
图标,及点击事件。并提供 closeFunc
方法,用于在点击事件末尾,关闭右键菜单。return InkWell(onTapDown: (details){TUIKitWidePopup.showPopupWindow(isDarkBackground: false,operationKey: TUIKitWideModalOperationKey.custom,borderRadius: const BorderRadius.all(Radius.circular(4)),context: context,// 下面的 offset 需要根据实际情况及 details 加以计算。offset: Offset(details.globalPosition.dx + 10, details.globalPosition.dy - 200),child: (closeFunc) => TUIKitColumnMenu(data: [ColumnMenuItem(label: TIM_t("个人中心"), onClick: (){// 你定义的点击事件closeFunc();}),ColumnMenuItem(label: TIM_t("个人中心"), onClick: (){// 你定义的点击事件closeFunc();}),],));},child: Container(),);
TIMUIKitProfile
基本一致。TIMUIKitUnreadCount
小红点组件,其会自动挂载监听。TIMUIKitSearch
全局搜索组件,支持全局搜索联系人/群组/聊天记录,也支持使用 TIMUIKitSearchMsgDetail
在特定会话中搜索聊天记录。两种模式取决于是否传入 conversation
。组件 | 控制器 | 功能 |
刷新历史消息列表/更新单条消息/手动发送额外的消息/为消息设置自定义字段 等 | ||
获取及刷新会话列表/会话置顶/设置会话的草稿/清空会话内所有消息/删除会话/滚动到特定会话 等 | ||
删除联系人好友/置顶当前联系人的会话/将用户加入黑名单/修改被加好友方式/更新联系人备注名/设置联系人消息免打扰/添加联系人好友/更新自己的资料 等 |
final TIMUIKitChatController _chatController = TIMUIKitChatController();
controller
参数中。@overrideWidget build(BuildContext context) {return TIMUIKitChat(controller: _chatController,// ...其他参数);}
_sendLocationMessage(String desc, double longitude, double latitude) async {final locationMessageInfo = await sdkInstance.v2TIMMessageManager.createLocationMessage(desc: desc,longitude: longitude,latitude: latitude);final messageInfo = locationMessageInfo.data!.messageInfo;_chatController.sendMessage(receiverID: _getConvID(),groupID:_getConvID(),convType: _getConvType(),messageInfo: messageInfo);}
compileSdkVersion
不合适怎么办?pubspec.yaml
文件中,指定确保如下两个插件的版本。video_thumbnail: ^0.5.3permission_handler: ^10.0.0flutter_local_notifications: 9.7.0
android/app/build.gradle
文件,保证 android => compileSdkVersion 33
。android {compileSdkVersion 33...}
flutter pub cache cleanflutter pub get
Codepoint 984472 not found in font, aborting.
怎么办?--no-tree-shake-icons
。如:flutter build apk --no-tree-shake-icons --dart-define=SDK_APPID={您的SDKAPPID}
pod install
或 flutter run
ios/Pods
文件夹,及 ios/Podfile.lock
文件,并执行如下命令,重新安装依赖cd iossudo gem install ffipod install --repo-update
设置 => 蓝牙
彻底关闭。flutter run
即可。android\\app\\src\\main\\AndroidManifest.xml
,根据如下,补全 xmlns:tools="http://schemas.android.com/tools"
/ android:label="@string/android_label"
及 tools:replace="android:label"
。<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="替换成您的 Android 端包名"xmlns:tools="http://schemas.android.com/tools"><applicationandroid:label="@string/android_label"tools:replace="android:label"android:icon="@mipmap/ic_launcher" // 指定一个 icon 路径android:usesCleartextTraffic="true"android:requestLegacyExternalStorage="true">
android\\app\\build.gradle
,补全 defaultConfig
中 minSdkVersion
及 targetSdkVersion
。defaultConfig {applicationId "" // 替换成您的Android端包名minSdkVersion 21targetSdkVersion 30}
onTUIKitCallbackListener
监听。TIMCallbackType
确定类型。final CoreServicesImpl _coreInstance = TIMUIKitCore.getInstance();final isInitSuccess = await _coreInstance.init(onTUIKitCallbackListener: (TIMCallback callbackValue){switch(callbackValue.type) {case TIMCallbackType.INFO:// Shows the recommend text for info callback directlyUtils.toast(callbackValue.infoRecommendText!);break;case TIMCallbackType.API_ERROR://Prints the API error to console, and shows the error message.print("Error from TUIKit: ${callbackValue.errorMsg}, Code: ${callbackValue.errorCode}");if (callbackValue.errorCode == 10004 && callbackValue.errorMsg!.contains("not support @all")) {Utils.toast(imt("当前群组不支持@全体成员"));}else{Utils.toast(callbackValue.errorMsg ?? callbackValue.errorCode.toString());}break;case TIMCallbackType.FLUTTER_ERROR:default:// prints the stack trace to console or shows the catch errorif(callbackValue.catchError != null){Utils.toast(callbackValue.catchError.toString());}else{print(callbackValue.stackTrace);}}},);
TIMCallbackType.API_ERROR
)errorMsg
及errorCode
。TIMCallbackType.FLUTTER_ERROR
)stackTrace
(来自FlutterError.onError
)或catchError
(来自 try-catch)。TIMCallbackType.INFO
)infoCode
场景码帮助您确定当前的场景,及默认的提示推荐语infoRecommendText
。场景码开头 | 对应的组件 |
66601 | TIMUIKitAddFriend |
66602 | TIMUIKitAddGroup |
66603 | TIMUIKitBlackList |
66604 | TIMUIKitChat |
66605 | TIMUIKitContact |
66606 | TIMUIKitConversation |
66607 | TIMUIKitGroup |
66608 | TIMUIKitGroupProfile |
66609 | TIMUIKitNewContact |
66610 | TIMUIKitGroupProfile |
66611 | TIMUIKitNewContact |
66612 | TIMUIKitProfile |
66613 | TIMUIKitSearch |
66614 | 通用组件 |
场景码 infoCode | 推荐提示语 infoRecommendText | 场景描述 |
6660101 | 好友申请已发送 | 用户申请添加其他用户为联系人 |
6660102 | 该用户已是好友 | 用户申请添加其他已是好友的用户为好友时,触发 onTapAlreadyFriendsItem 回调 |
6660201 | 群申请已发送 | 用户申请加入需要管理员审批的群聊 |
6660202 | 您已是群成员 | 用户申请加群时,判断用户已经是当前群成员,触发 onTapExistGroup 回调 |
6660401 | 无法定位到原消息 | 当用户需要跳转至@消息或者是引用消息时,在消息列表中查不到目标消息 |
6660402 | 视频保存成功 | 用户在消息列表,点开视频消息后,选择保存视频 |
6660403 | 视频保存失败 | 用户在消息列表,点开视频消息后,选择保存视频 |
6660404 | 说话时间太短 | 用户发送了过短的语音消息 |
6660405 | 发送失败,视频不能大于 100MB | 用户试图发送大于 100MB 的视频 |
6660406 | 图片保存成功 | 用户在消息列表,点开图片大图后,选择保存图片 |
6660407 | 图片保存失败 | 用户在消息列表,点开图片大图后,选择保存图片 |
6660408 | 已复制 | 用户在弹窗内选择复制文字消息 |
6660409 | 暂未实现 | 用户在弹窗内选择非标功能 |
6660410 | 其他文件正在接收中 | 用户点击下载文件消息时,前序下载任务还未完成 |
6660411 | 正在接收中 | 用户点击下载文件消息 |
6660412 | 视频消息仅限 mp4 格式 | 用户发送了一条非 mp4 格式的视频消息 |
6660414 | 正在下载中 | 【桌面端】图片/视频资源正在下载中,暂时无法打开,过一会下载好了才能打开 |
6660415 | 视频文件异常 | 发送的视频文件资源本身是错误或被损坏,无法发送 |
6661002 | 无网络连接,无法查看群成员 | 当用户试图在无网络环境下,修改群资料 |
6661003 | 成功取消管理员身份 | 用户将群内其他用户移除管理员 |
6661201 | 无网络连接,无法修改 | 当用户试图在无网络环境下,修改自己或联系人的资料 |
6661202 | 好友添加成功 | 在资料页添加其他用户为好友,并自动添加成功,无需验证 |
6661203 | 好友申请已发出 | 在资料页添加其他用户为好友,对方设置需要验证 |
6661204 | 当前用户在黑名单 | 在资料页添加其他用户为好友,对方在自己的黑名单内 |
6661205 | 好友添加失败 | 在资料页添加其他用户为好友,添加失败,可能是由于对方禁止加好友 |
6661206 | 好友删除成功 | 在资料页删除其他用户为好友,成功 |
6661207 | 好友删除失败 | 在资料页删除其他用户为好友,失败 |
6661401 | 输入不能为空 | 当用户在录入信息时,输入了空字符串 |
6661402 | 请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法 | 用户退出群或解散群时,为提供返回首页办法 |
6661403 | 设备存储空间不足,建议清理,以获得更好使用体验 | 在login成功后,会自动检测设备存储空间,如果不足1GB,会提示存储空间不足 |
本页内容是否解决了您的问题?