Repository: JiangJuHong/FlutterTencentImPlugin Branch: master Commit: 84a314326778 Files: 268 Total size: 560.3 KB Directory structure: gitextract_zorfcym6/ ├── .all-contributorsrc ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README_3.0_upgrade.md ├── android/ │ ├── .gitignore │ ├── build.gradle │ ├── consumer-proguard-rules.txt │ ├── gradle/ │ │ └── wrapper/ │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ ├── settings.gradle │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ └── top/ │ └── huic/ │ └── tencent_im_plugin/ │ ├── DownloadCallBack.java │ ├── TencentImPlugin.java │ ├── ValueCallBack.java │ ├── VoidCallBack.java │ ├── entity/ │ │ ├── CustomConversationEntity.java │ │ ├── CustomConversationResultEntity.java │ │ ├── CustomFriendAddApplication.java │ │ ├── CustomMessageEntity.java │ │ ├── FindFriendApplicationEntity.java │ │ ├── FindGroupApplicationEntity.java │ │ └── FindMessageEntity.java │ ├── enums/ │ │ ├── ListenerTypeEnum.java │ │ └── MessageNodeType.java │ ├── listener/ │ │ ├── CustomAdvancedMsgListener.java │ │ ├── CustomConversationListener.java │ │ ├── CustomFriendshipListener.java │ │ ├── CustomGroupListener.java │ │ ├── CustomSDKListener.java │ │ └── CustomSignalingListener.java │ ├── message/ │ │ ├── AbstractMessageNode.java │ │ ├── CustomMessageNode.java │ │ ├── FaceMessageNode.java │ │ ├── FileMessageNode.java │ │ ├── GroupTipsMessageNode.java │ │ ├── ImageMessageNode.java │ │ ├── LocationMessageNode.java │ │ ├── SoundMessageNode.java │ │ ├── TextMessageNode.java │ │ ├── VideoMessageNode.java │ │ └── entity/ │ │ ├── AbstractMessageEntity.java │ │ ├── CustomMessageEntity.java │ │ ├── FaceMessageEntity.java │ │ ├── FileMessageEntity.java │ │ ├── GroupTipsMessageEntity.java │ │ ├── ImageMessageEntity.java │ │ ├── LocationMessageEntity.java │ │ ├── SoundMessageEntity.java │ │ ├── TextMessageEntity.java │ │ └── VideoMessageEntity.java │ └── util/ │ ├── BeanUtils.java │ ├── CommonUtil.java │ ├── JsonUtil.java │ └── TencentImUtils.java ├── example/ │ ├── .gitignore │ ├── .metadata │ ├── README.md │ ├── android/ │ │ ├── .gitignore │ │ ├── app/ │ │ │ ├── agconnect-services.json │ │ │ ├── build.gradle │ │ │ ├── key.jks │ │ │ └── src/ │ │ │ ├── debug/ │ │ │ │ └── AndroidManifest.xml │ │ │ ├── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── top/ │ │ │ │ │ └── huic/ │ │ │ │ │ └── tencent_im_plugin_example/ │ │ │ │ │ └── MainActivity.java │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ └── launch_background.xml │ │ │ │ └── values/ │ │ │ │ └── styles.xml │ │ │ └── profile/ │ │ │ └── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle/ │ │ │ └── wrapper/ │ │ │ └── gradle-wrapper.properties │ │ ├── gradle.properties │ │ └── settings.gradle │ ├── ios/ │ │ ├── .gitignore │ │ ├── Flutter/ │ │ │ ├── AppFrameworkInfo.plist │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Podfile │ │ ├── Runner/ │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── LaunchImage.imageset/ │ │ │ │ ├── Contents.json │ │ │ │ └── README.md │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ └── Runner-Bridging-Header.h │ │ ├── Runner.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace/ │ │ │ │ └── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── xcschemes/ │ │ │ └── Runner.xcscheme │ │ └── Runner.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── lib/ │ │ ├── main.dart │ │ ├── page/ │ │ │ ├── chat.dart │ │ │ ├── home.dart │ │ │ ├── interfaces_test.dart │ │ │ ├── login.dart │ │ │ └── main/ │ │ │ ├── components/ │ │ │ │ ├── conversation.dart │ │ │ │ ├── friend.dart │ │ │ │ └── group.dart │ │ │ └── main.dart │ │ └── utils/ │ │ └── GenerateTestUserSig.dart │ ├── pubspec.yaml │ └── test/ │ └── widget_test.dart ├── ios/ │ ├── .gitignore │ ├── Assets/ │ │ └── .gitkeep │ ├── Classes/ │ │ ├── SwiftTencentImPlugin.swift │ │ ├── TencentImPlugin.h │ │ ├── TencentImPlugin.m │ │ ├── entity/ │ │ │ ├── CustomConversationEntity.swift │ │ │ ├── CustomConversationResultEntity.swift │ │ │ ├── CustomCreateGroupMemberEntity.swift │ │ │ ├── CustomFriendAddApplicationEntity.swift │ │ │ ├── CustomFriendApplicationEntity.swift │ │ │ ├── CustomFriendApplicationResultEntity.swift │ │ │ ├── CustomFriendCheckResultEntity.swift │ │ │ ├── CustomFriendGroupEntity.swift │ │ │ ├── CustomFriendInfoEntity.swift │ │ │ ├── CustomFriendInfoResultEntity.swift │ │ │ ├── CustomFriendOperationResultEntity.swift │ │ │ ├── CustomGroupApplicationEntity.swift │ │ │ ├── CustomGroupApplicationResultEntity.swift │ │ │ ├── CustomGroupAtInfoEntity.swift │ │ │ ├── CustomGroupChangeInfoEntity.swift │ │ │ ├── CustomGroupInfoEntity.swift │ │ │ ├── CustomGroupInfoResultEntity.swift │ │ │ ├── CustomGroupMemberChangeInfoEntity.swift │ │ │ ├── CustomGroupMemberFullInfoEntity.swift │ │ │ ├── CustomGroupMemberInfoResultEntity.swift │ │ │ ├── CustomGroupMemberOperationResultEntity.swift │ │ │ ├── CustomMessageReceiptEntity.swift │ │ │ ├── CustomOfflinePushInfoEntity.swift │ │ │ ├── CustomSignalingInfoEntity.swift │ │ │ ├── CustomUserEntity.swift │ │ │ ├── FindFriendApplicationEntity.swift │ │ │ ├── FindGroupApplicationEntity.swift │ │ │ ├── FindMessageEntity.swift │ │ │ └── MessageEntity.swift │ │ ├── enums/ │ │ │ ├── DownloadType.swift │ │ │ ├── ListenerType.swift │ │ │ └── MessageNodeType.swift │ │ ├── listener/ │ │ │ ├── CustomAPNSListener.swift │ │ │ ├── CustomAdvancedMsgListener.swift │ │ │ ├── CustomConversationListener.swift │ │ │ ├── CustomFriendshipListener.swift │ │ │ ├── CustomGroupListener.swift │ │ │ ├── CustomSDKListener.swift │ │ │ └── CustomSignalingListener.swift │ │ ├── message/ │ │ │ ├── AbstractMessageNode.swift │ │ │ ├── CustomMessageNode.swift │ │ │ ├── FaceMessageNode.swift │ │ │ ├── FileMessageNode.swift │ │ │ ├── GroupTipsMessageNode.swift │ │ │ ├── ImageMessageNode.swift │ │ │ ├── LocationMessageNode.swift │ │ │ ├── SoundMessageNode.swift │ │ │ ├── TextMessageNode.swift │ │ │ ├── VideoMessageNode.swift │ │ │ └── entity/ │ │ │ ├── AbstractMessageEntity.swift │ │ │ ├── CustomMessageEntity.swift │ │ │ ├── FaceMessageEntity.swift │ │ │ ├── FileMessageEntity.swift │ │ │ ├── LocationMessageEntity.swift │ │ │ ├── SoundMessageEntity.swift │ │ │ ├── TextMessageEntity.swift │ │ │ ├── VideoMessageEntity.swift │ │ │ ├── group_tips/ │ │ │ │ └── GroupTipsMessageEntity.swift │ │ │ └── image/ │ │ │ ├── ImageEntity.swift │ │ │ └── ImageMessageEntity.swift │ │ └── utils/ │ │ ├── CommonUtils.swift │ │ ├── JsonUtil.swift │ │ └── TencentImUtil.swift │ └── tencent_im_plugin.podspec ├── lib/ │ ├── entity/ │ │ ├── conversation_entity.dart │ │ ├── conversation_result_entity.dart │ │ ├── download_progress_entity.dart │ │ ├── error_entity.dart │ │ ├── find_friend_application_entity.dart │ │ ├── find_group_application_entity.dart │ │ ├── find_message_entity.dart │ │ ├── friend_add_application_entity.dart │ │ ├── friend_application_entity.dart │ │ ├── friend_application_result_entity.dart │ │ ├── friend_check_result_entity.dart │ │ ├── friend_group_entity.dart │ │ ├── friend_info_entity.dart │ │ ├── friend_info_result_entity.dart │ │ ├── friend_operation_result_entity.dart │ │ ├── group_administrator_op_entity.dart │ │ ├── group_application_entity.dart │ │ ├── group_application_processed_entity.dart │ │ ├── group_application_result_entity.dart │ │ ├── group_at_info_entity.dart │ │ ├── group_attribute_changed_entity.dart │ │ ├── group_changed_entity.dart │ │ ├── group_create_member_entity.dart │ │ ├── group_dismissed_or_recycled_entity.dart │ │ ├── group_info_entity.dart │ │ ├── group_info_result_entity.dart │ │ ├── group_member_changed_entity.dart │ │ ├── group_member_enter_entity.dart │ │ ├── group_member_entity.dart │ │ ├── group_member_info_result_entity.dart │ │ ├── group_member_invited_or_kicked_entity.dart │ │ ├── group_member_leave_entity.dart │ │ ├── group_member_operation_result_entity.dart │ │ ├── group_receive_join_application_entity.dart │ │ ├── group_receive_rest_entity.dart │ │ ├── message_entity.dart │ │ ├── message_receipt_entity.dart │ │ ├── message_search_param.dart │ │ ├── message_send_fail_entity.dart │ │ ├── message_send_progress_entity.dart │ │ ├── offline_push_info_entity.dart │ │ ├── signaling_common_entity.dart │ │ ├── signaling_info_entity.dart │ │ └── user_entity.dart │ ├── entity_factory.dart │ ├── enums/ │ │ ├── conversation_type_enum.dart │ │ ├── download_type_enum.dart │ │ ├── friend_application_agree_type_enum.dart │ │ ├── friend_application_type_enum.dart │ │ ├── friend_relation_type_enum.dart │ │ ├── friend_status_enum.dart │ │ ├── friend_type_enum.dart │ │ ├── get_message_type_enum.dart │ │ ├── group_add_opt_enum.dart │ │ ├── group_application_handler_result_enum.dart │ │ ├── group_application_handler_status_enum.dart │ │ ├── group_application_type_enum.dart │ │ ├── group_at_type_enum.dart │ │ ├── group_info_changed_type_enum.dart │ │ ├── group_member_filter_enum.dart │ │ ├── group_member_role_enum.dart │ │ ├── group_system_type.dart │ │ ├── group_tips_group_info_type.dart │ │ ├── group_tips_type_enum.dart │ │ ├── group_type_enum.dart │ │ ├── image_type_enum.dart │ │ ├── log_print_level.dart │ │ ├── login_status_enum.dart │ │ ├── message_elem_type_enum.dart │ │ ├── message_priority_enum.dart │ │ ├── message_status_enum.dart │ │ ├── operation_result_enum.dart │ │ ├── pendency_examine_type_enum.dart │ │ ├── pendency_type_enum.dart │ │ ├── receive_message_opt_enum.dart │ │ ├── signaling_action_type_enum.dart │ │ ├── sns_tips_type.dart │ │ ├── tencent_im_listener_type_enum.dart │ │ ├── user_allow_type_enum.dart │ │ └── user_gender_enum.dart │ ├── list_util.dart │ ├── listener/ │ │ └── tencent_im_plugin_listener.dart │ ├── message_node/ │ │ ├── custom_message_node.dart │ │ ├── face_message_node.dart │ │ ├── file_message_node.dart │ │ ├── group_tips_message_node.dart │ │ ├── image_message_node.dart │ │ ├── location_message_node.dart │ │ ├── message_node.dart │ │ ├── sound_message_node.dart │ │ ├── text_message_node.dart │ │ └── video_message_node.dart │ ├── tencent_im_plugin.dart │ └── utils/ │ └── enum_util.dart └── pubspec.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .all-contributorsrc ================================================ { "files": [ "README.md" ], "imageSize": 100, "commit": false, "contributors": [ { "login": "kxr224", "name": "cyrus", "avatar_url": "https://avatars.githubusercontent.com/u/28681083?v=4", "profile": "https://github.com/kxr224", "contributions": [ "bug" ] }, { "login": "songjiabin", "name": "宋佳宾", "avatar_url": "https://avatars.githubusercontent.com/u/13177100?v=4", "profile": "https://github.com/songjiabin", "contributions": [ "code" ] }, { "login": "ligui-iOS", "name": "ligui-iOS", "avatar_url": "https://avatars.githubusercontent.com/u/20856361?v=4", "profile": "https://github.com/ligui-iOS", "contributions": [ "code" ] }, { "login": "laiiihz", "name": "LAIIIHZ", "avatar_url": "https://avatars.githubusercontent.com/u/35956195?v=4", "profile": "http://laiiihz.github.io", "contributions": [ "code" ] } ], "contributorsPerLine": 7, "projectName": "FlutterTencentImPlugin", "projectOwner": "JiangJuHong", "repoType": "github", "repoHost": "https://github.com", "skipCi": true } ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: https://www.yuque.com/jiangjuhong/tencent-im-flutter/ygi582 # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .gitignore ================================================ .DS_Store .dart_tool/ .packages .pub/ .idea *.iml build/ ================================================ FILE: .metadata ================================================ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # # This file should be version controlled and should not be manually edited. version: revision: d345a3b303ce041846ff895eb49a104bef133c4b channel: master project_type: plugin ================================================ FILE: CHANGELOG.md ================================================ ## 0.1.0 * 集成腾讯云IMSDK,包含Android 和 IOS ## 0.1.1 * 修复Android设备上找不到符号的BUG ## 0.1.2 * 修复IOS上Json字符串中包含特殊字符的问题 * 修复IOS监听器无效的问题 ## 0.1.3 * 修复 MessageEntity 中 sessionType 始终为空的问题 ## 0.1.4 * 修复 GroupTipsNode 节点nil对象引起闪退问题 ## 0.1.5 * 修复 GroupTipsNode 节点nil对象引起闪退问题 ## 0.1.6 * 修复IOS上添加好友必须传递所有参数的问题 * 修改 getParam 方法代码结构 ## 0.1.7 * 修复IOS上获得未决列表时解析异常的问题 ## 0.1.8 * 修复Android设备上自定义消息未解码的问题 ## 0.1.9 * 修复安卓上获得单个会话异常 ## 0.1.10 * 修复IOS设备上回调数据非JSON类型时多了个 "" ## 0.1.11 * 修复消息解析异常 ## 0.1.12 * 移除base64 工具类 * 解决fastjson byte[] 序列化为base64字符串的问题 ## 0.1.13 * 修复运行异常 ## 0.1.14 * 完成消息撤回功能 ## 0.1.15 * 增加删除单条消息功能 * 修改json工具类,解决非字符串类型以字符串类型返回 ## 0.1.16 * 修复字符串数组解析JSON时格式问题 ## 0.1.17 * 增加设置消息自定义字符串和自定义整型 ## 0.1.18 * 增加发送消息后返回消息对象 ## 0.1.19 * 兼容所有发送消息后返回消息对象 ## 0.1.20 * 会话列表增加能够获得发送人信息 ## 0.1.21 * 发送新消息后,返回的数据对象有问题 ## 0.1.22 * 修复 setMessageCustomInt 和 setMessageCustomString 报错的问题 ## 0.2.0 1. 将发送消息统一更改为 sendMessage ,使用不同消息节点即可发送不同消息 1. MessageEntity 增加 note 属性,对非自定消息可直接用于展示 1. 发送节点和接收实体合二为一,发送时仅需设置构造器参数即可,接收时会自动填充内容 1. 视频、语音,将不再自动下载,提供语音/视频下载方法 1. 视频、语音和图片提供上传/下载进度监听器,分别为:ListenerTypeEnum.UploadProgress/ListenerTypeEnum.DownloadProgress 1. 除 PendencyPageEntity 和 GroupPendencyPageEntity 外的所有Entity 重写 == 和 hashCode,可直接进行判断是否相等 ## 0.2.1 * 修订文档 ## 0.2.2 * 修改类名称 ## 0.2.3 * 修复枚举名称 ## 0.2.4 * 图片节点增加清晰度参数 * 图片增加默认值填充 ## 0.2.5 * 移除图片节点转换 ## 0.2.6 修复ImageNode无法赋值的问题 ## 0.2.7 修复自定义消息无法赋值的问题 ## 0.2.8 修复删除会话无法删除本地消息的问题 ## 0.2.9 * 修复MessageEntity传递方式 * getMessages 和 getLocalMessages 增加根据lastMessage来筛选 ## 0.2.10 * 修复 getMessage 和 getLocalMessage 根据lastMessage筛选 无效的问题 ## 0.2.11 * 修复IOS无法获得消息的问题 ## 0.2.12 * 修复Android获得消息报错 ## 0.2.13 * 增加通用节点 Other ## 0.2.14 * 增加GroupTips节点 ## 0.2.15 * 升级版本,无改动 ## 0.2.16 * 优化:无论是群聊还是个人都会触发撤回回调 ## 0.2.17 * 优化:群提示通知、群通知节点,使用同一个实体 ## 0.2.18 * 修复:群提示节点userList始终为空的问题 ## 0.2.19 * 增加: SNSSystemElem 的解析 ## 0.2.20 * 增加:findMessage、saveMessage * 增加:init 时可配置日志相关内容 ## 0.2.21 * 修复:IOS onReConnFailed、onConnFailed和onDisconnect 回调时崩溃的问题 ## 0.2.22 * 修复:获取会话用户时,有时候获取不到 ## 0.2.23 * 解决代码错误 ## 0.2.24 * 修复Android:获取会话用户时,有时候获取不到 ## 0.2.25 * 取消Android logout 方法的校验 * 修改离线获取会话列表 * 修改离线获取会话列表 * 修改离线获取消息 ## 0.2.26 * 增加监听器文档说明 * 修改 modifyMemberInfo 参数不一致的问题 * 修复Android创建群聊时,无法设置群成员的问题 * 修复IOS创建群聊无法设置群成员问题 ## 0.2.27 * 升级IM SDK版本为 4.8.10 * 增加离线推送 ## 0.2.28 * 修复 setToken int 无法转换为 long 的问题 * 离线推送注册增加文档说明 ## 0.2.30 * 修复 Android Int 转换为 Long 时报错 ## 0.2.31 * 创建群组的群成员设置为可选属性 ## 0.2.32 * 修复IOS applyJoinGroup 包错问题 * 修复Demo NewMessages 监听器添加数据失败 ## 0.2.33 * 修复IOS申请加入群组闪退问题 * 修改申请加入群组 reason 为必传 ## 0.2.34 * 修复 Native 和 Flutter 模型参数不一致 ## 0.2.35 * 解决群未决处理TIMGroupPendencyItem的selfIdentifier为空的问题 ## 0.2.36 * 解决发送图片后可能出现的错误 * createGroup 接口增加 customInfo 信息 * 替换Demo中视频缩略图获取的方案 * 解决IOS Pod Install 后会报错 ## 0.2.37 * 更换离线推送Token字符串解析方式(原方式不支持APNS) ## 0.2.38 * 修改 android getConversation 传入非存在sessionId的时候闪退问题 ## 0.2.39 * 增加 GroupSystem 节点解析 ## 0.2.40 * 增加 TIMProfileSystemElem 节点解析 ## 0.2.41 * 修复IOS设备下 deleteConversation 接口无法接收返回值的问题 ## 0.2.42 * 修复IOS运行报错 ## 0.2.43 * 修复 ValueCallBack 错误码和描述信息反了的问题 * 对登录操作不再做 isEmpty 验证 ## 0.2.44 * 优化文本节点隐晦出现BUG的问题 ## 1.0.0 * 集成 SDK 5.1.1 ## 1.0.1 * 优化Demo ## 1.0.2 * 修复回调调用异常的问题 ## 1.0.3 * 修复对象解析错误异常 ## 1.0.4 * 修复 getFriendGroups 接口参数为必传的问题 ## 1.0.5 * 升级SDK到 5.1.2 * 增加 getGroupOnlineMemberCount 接口 ## 1.0.6 * 修复 C2CReadReceipt 回调异常的问题 ## 1.1.0 * 优化会话相关接口,提供内部转换 * 增加 getHistoryMessageList 和 markMessageAsRead 接口 ## 1.1.1 * 修改混淆文件 ## 1.1.2 * 修复 SignalingCommonEntity 实体转换失败的问题 ## 1.1.3 * 修复消息发送进度回调数据转换异常的问题 ## 1.1.4 * 修复 addFriend 添加好友异常的问题 ## 1.1.5 * 修复 MessageRevoked 监听没有参数问题 ## 1.1.6 * 增加 GroupTips 数据节点解析 ## 1.2.0 * 1. Android 和 IOS 将所有监听器的参数二次转换为 json 取消 * 2. 适配Flutter ## 1.2.1 * 增加 setMessageLocalCustomStr 和 setMessageLocalCustomInt 接口 ## 1.2.2 * 修复下载进度出现Optiona的问题 ## 1.2.3 * 修复部分回调没有正确接收到参数的问题 * Demo增加生成签名 * 修复部分回调在 IOS 端下包含 Optional 的问题 * 升级SDK版本为 5.1.10 ## 1.2.4 * 修复 setMessageLocalCustomStr 执行失败的问题 * Demo增加发起会话 * 修复 onReceiveNewInvitation 解包失败的问题 ## 1.2.5 * 修复回调非主线程闪退问题 ## 1.2.6 * 修复获得会话传递nextSeq异常的问题 ## 1.2.7 * 修复Android端fastjson打包闪退的问题 * DownloadProgress 回调增加 type 属性 * 消息重发接口 * IOS发送消息进度和失败消息的ID未解包的问题 ## 1.2.8 * 新增 downloadFile 接口 * 新增 findMessages 接口 * 对部分关键实体实体重写 == 操作符(非所有实体) * 修复IOS端不能发送视频的问题 * 修复 BeanUtils 访问权限导致调用内部方法报错的问题 ## 1.2.9 * 修复文件发送失败的问题 ## 1.2.10 * 修复发送文件FileName不生效的问题 ## 1.2.11 * 修复 Android getGroupOnlineMemberCount 接口无法解析的问题 ## 1.2.12 * 修复信令data为空的问题 ## 1.2.13 * 修复unInit后再次init,会导致监听器重复的问题 * 修复IOS上at列表为空时会导致闪退 * 修复ios上at功能异常的问题 * 增加getVersion、和getServerTime接口 * 增加群自定义字段 * 升级SDK为 5.1.50 * 自定义节点增加 desc 和 ext 字段 * 用户资料增加 role 和 level 字段 * 更新getHistoryMessageList接口,增加type属性 * 消息对象增加 random ## 1.2.14 * fix "修复IOS环境下自定义节点 desc 和 ext 无法使用的问题" * fix "修复 inviteInGroup 接口在Android下会闪退的问题" * feat "更新内部依赖插件版本" * docs "更新文档" ## 2.0.0 * feat 增加空安全 ## 2.0.1 * docs 格式化文档 ## 2.0.2 * 优化空安全 ## 2.0.3 * fix 修复android调用createGroup返回的群ID中含有字符串的问题 * feat Demo中增加创建群聊 * feat 升级SDK版本为 5.1.62 * fix 修复ios setGroupInfo 接口会清空其它字段的问题 * fix 修复ios setSelfInfo 无效的问题 ## 2.0.4 * feat 增加FindFriendApplicationEntity 快速创建方法 ## 2.0.5 * feat FileMessageNode 节点中,filePath 和 fileName 增加可为空选择 ## 3.0.0 * feat 调整所有空返回值结果为明确指定 * feat 升级版本到最新增强版 `5.5.897` * feat ``setGroupReceiveMessageOpt`` 设置群接收消息选项接口 * feat ``setC2CReceiveMessageOpt`` 设置C2C接收消息选项接口 * feat ``ReceiveMessageOptEnum`` 接收消息选项枚举类 * feat ``pinConversation`` 置顶会话接口 * feat ``getTotalUnreadMessageCount`` 获得会话总未读数接口 * feat ``conversation`` 增加 ``pinned`` 会话是否置顶属性 * feat `MessageStatusEnum` 增加 Imported 属性 * Remove ``setReceiveMessageOpt`` 接口 * Remove ``GroupReceiveMessageOptEnum`` 枚举 * fix 修复 SignalingInfoEntity 反序列化报错的问题 * fix 修复信令邀请回调没有群ID的问题 * fix 修复IOS信令相关接口闪退的问题 * fix 修复Android CustomMessageEntity 创建抛出空指针问题 * fix 修复Android getGroupMemberList 接口nextSeq传递无效的问题 * fix 修复部分接口在ios设置自定义字段无效 * fix 修复Android和IOS Tag_Profile_Custom_ 不统一问题 ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2013-2018 Docker, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================
[![](https://img.shields.io/badge/flutter2.0-NullSafety-1)](#) [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) [![](https://img.shields.io/badge/Version-社区版-1)](#) [![](https://img.shields.io/pub/v/tencent_im_plugin.svg)](https://pub.dartlang.org/packages/tencent_im_plugin) [![](https://img.shields.io/github/license/JiangJuHong/FlutterTencentImPlugin)](https://www.apache.org/licenses/LICENSE-2.0) [![](https://img.shields.io/badge/qq群-850923396-1)](https://jq.qq.com/?_wv=1027&k=QxCWMlUf)
# What is FlutterTencentIm ? # 终章 ## 致所有FlutterTencentIm贡献者及用户 ```` 即日起,FlutterTencentIm停止维护,永久保留仓库代码。感谢所有贡献者的帮助,同时感谢所有用户长期以来的支持。 如果您的项目中还需要集成TIM服务,请移至: https://cloud.tencent.com/document/product/269/51940 或 https://github.com/TencentCloud/chat-sdk-flutter/tree/main/example。 关闭说明: 1. 腾讯终于推出了官方SDK,维护更稳定,推荐使用 一个项目的征途结束了,开源的步伐永远不滞。 欢迎加入Flutter讨论群,QQ群号: 850923396 ```` FlutterTencentIM是基于[腾讯云即时通讯](https://cloud.tencent.com/product/im)服务进行的Flutter封装,为Flutter提供即时通讯服务. # 3. X has arrived? 最新计划为3.x,大致更改内容如下: 【注意: 这是未完成的内容,请谨慎使用】3.x对原有接口进行了细微调整,您可根据 [升级文档](/README_3.0_upgrade.md) 进行升级 | 功能列表 | 进度 | |:-----------------------|:-----| | 保持基础接口不变 | ✅ | | SDK从原有标准版升级为增强版 | ✅ | | 增加增强版所有功能 | ☑️ | # Notice 💐💐 新版插件支持空安全(`null-safety`),如需查看非空安全版本,请切换分支到:`sdk-5.1.x-non-null-safety`💐💐 💐 FlutterTencentIm 开放 Pull Request,merge 成功后会在 README.md 上留下您的大名并超链到您的 Github 主页! # 官方版和社区版的区别 * 两者的区别:本质上官方版和社区版都是基于IM的SDK进行封装,官方版的更偏向三端写法类似(Android、IOS、Flutter),社区版则提供更便捷的使用方式(1分钟上手即用)(例: FlutterImPlugin.login)。 * 该如何选择:根据个人编码习惯选择即可。 * 维护的周期:社区版和官方版均在持续迭代,发现异常将会在第一时间进行修复。 # Sdk Version | 平台 | SDK版本 | |:--------|:-------| | Android | 5.5.897 | | IOS | 5.5.897 | # Links * [Document](https://www.yuque.com/jiangjuhong/tencent-im-flutter/zk6p14) * [Chat](https://jq.qq.com/?_wv=1027&k=QxCWMlUf) * [Sponsor](https://www.yuque.com/jiangjuhong/tencent-im-flutter/ygi582) # Customization 如果您的项目有定制化需求,可通过QQ(690717394) 或 邮箱(690717394@qq.com) 联系我,该项服务为有偿服务,具体价格根据需求量进行决定。 # Other Plugins ```` 我同时维护的还有以下插件,如果您感兴趣与我一起进行维护,请通过Github联系我,欢迎 issues 和 PR。 ```` | 平台 | 插件 | 描述 | 版本 | |:--------|:------------------------------------------------------------------------------------------------|:--------------------------|:------------------------------------------------------------------------------------------------------------------------------------| | Flutter | [FlutterVideoPlayerLibrary-Desc](https://github.com/JiangJuHong/FlutterVideoPlayerLibrary-Desc) | Flutter 最好用的播放器(UI库) | - | | Flutter | [FlutterPerfectVolumeControl](https://github.com/JiangJuHong/FlutterPerfectVolumeControl) | Flutter 完美的音量控制器插件 | [![pub package](https://img.shields.io/pub/v/perfect_volume_control.svg)](https://pub.dartlang.org/packages/perfect_volume_control) | | Flutter | [FlutterTencentImPlugin](https://github.com/JiangJuHong/FlutterTencentImPlugin) | 腾讯云IM插件 | [![pub package](https://img.shields.io/pub/v/tencent_im_plugin.svg)](https://pub.dartlang.org/packages/tencent_im_plugin) | | Flutter | [FlutterTencentRtcPlugin](https://github.com/JiangJuHong/FlutterTencentRtcPlugin) | 腾讯云Rtc插件 | [![pub package](https://img.shields.io/pub/v/tencent_rtc_plugin.svg)](https://pub.dartlang.org/packages/tencent_rtc_plugin) | | Flutter | [FlutterXiaoMiPushPlugin](https://github.com/JiangJuHong/FlutterXiaoMiPushPlugin) | 小米推送SDK插件 | [![pub package](https://img.shields.io/pub/v/xiao_mi_push_plugin.svg)](https://pub.dartlang.org/packages/xiao_mi_push_plugin) | | Flutter | [FlutterHuaWeiPushPlugin](https://github.com/JiangJuHong/FlutterHuaWeiPushPlugin) | 华为推送(HMS Push)插件 | [![pub package](https://img.shields.io/pub/v/hua_wei_push_plugin.svg)](https://pub.dartlang.org/packages/hua_wei_push_plugin) | | Flutter | [FlutterTextSpanField](https://github.com/JiangJuHong/FlutterTextSpanField) | 自定义文本样式输入框 | [![pub package](https://img.shields.io/pub/v/text_span_field.svg)](https://pub.dartlang.org/packages/text_span_field) | | Flutter | [FlutterClipboardListener](https://github.com/JiangJuHong/FlutterClipboardListener) | 粘贴板监听器 | [![pub package](https://img.shields.io/pub/v/clipboard_listener.svg)](https://pub.dartlang.org/packages/clipboard_listener) | | Flutter | [FlutterQiniucloudLivePlugin](https://github.com/JiangJuHong/FlutterQiniucloudLivePlugin) | Flutter 七牛云直播云插件 | 暂未发布,通过 git 集成 | ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

cyrus

🐛

宋佳宾

💻

ligui-iOS

💻

LAIIIHZ

💻
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! ================================================ FILE: README_3.0_upgrade.md ================================================ # 3.0升级文档 ## 通用变化 * 将 `setReceiveMessageOpt` 替换为 `setGroupReceiveMessageOpt` * 将 `GroupReceiveMessageOptEnum` 替换为 `ReceiveMessageOptEnum` * `MessageStatusEnum` 增加 Imported 属性 ## 新增内容 * 新增 ``setGroupReceiveMessageOpt`` 设置群接收消息选项接口 * 新增 ``setC2CReceiveMessageOpt`` 设置C2C接收消息选项接口 * 新增 ``ReceiveMessageOptEnum`` 接收消息选项枚举类 * 新增 ``pinConversation`` 置顶会话接口 * 新增 ``getTotalUnreadMessageCount`` 获得会话总未读数接口 * 新增 ``conversation`` 增加 ``pinned`` 会话是否置顶属性 * 新增 ``insertC2CMessageToLocalStorage`` 添加C2C会话接口 * 新增 ``setOfflinePushConfig`` 接口增加 tpns 参数 * 新增 ``searchGroups`` 搜索群接口 * 新增 ``searchGroupMembers`` 搜索群成员接口 * 新增 ``UserEntity`` 增加 生日(birthday) 属性 ## 移除内容 * 移除 ``setReceiveMessageOpt`` 接口 * 移除 ``GroupReceiveMessageOptEnum`` 枚举 ================================================ FILE: android/.gitignore ================================================ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures ================================================ FILE: android/build.gradle ================================================ group 'top.huic.tencent_im_plugin' version '1.0' buildscript { repositories { // maven { url 'https://maven.aliyun.com/repository/google' } // maven { url 'https://maven.aliyun.com/repository/jcenter' } // maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.5.3' } } rootProject.allprojects { repositories { // maven { url 'https://maven.aliyun.com/repository/google' } // maven { url 'https://maven.aliyun.com/repository/jcenter' } // maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } google() jcenter() } } apply plugin: 'com.android.library' android { compileSdkVersion 28 defaultConfig { minSdkVersion 16 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { abiFilters "armeabi-v7a" } // library 混淆 -> 随 library 引用,自动添加到 apk 打包混淆 consumerProguardFiles 'consumer-proguard-rules.txt' } lintOptions { disable 'InvalidPackage' } dependencies { api 'com.tencent.imsdk:imsdk-plus:6.1.2155' api 'com.alibaba:fastjson:1.1.72.android' } } ================================================ FILE: android/consumer-proguard-rules.txt ================================================ # 腾讯云IM -keep class com.tencent.** { *; } # FastJson -dontwarn com.alibaba.fastjson.** -keep class com.alibaba.fastjson.**{*;} # 泛型 -keepattributes Signature # 不混淆Serializable接口的子类 -keepclassmembers class * implements java.io.Serializable { *; } # 忽略实体类 -keep class top.huic.tencent_im_plugin.** {*;} ================================================ FILE: android/gradle/wrapper/gradle-wrapper.properties ================================================ #Thu Dec 05 14:15:15 CST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip ================================================ FILE: android/gradle.properties ================================================ org.gradle.jvmargs=-Xmx1536M android.enableR8=true android.useAndroidX=true android.enableJetifier=true ================================================ FILE: android/settings.gradle ================================================ rootProject.name = 'tencent_im_plugin' ================================================ FILE: android/src/main/AndroidManifest.xml ================================================ ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/DownloadCallBack.java ================================================ package top.huic.tencent_im_plugin; import com.tencent.imsdk.v2.V2TIMDownloadCallback; import com.tencent.imsdk.v2.V2TIMElem; import java.util.HashMap; import io.flutter.plugin.common.MethodChannel; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * 下载回调 */ public class DownloadCallBack implements V2TIMDownloadCallback { /** * 结果方法 */ private MethodChannel.Result result; /** * 下载路径 */ private String path; /** * 消息ID */ private String msgId; /** * 下载类型 */ private DownloadTypeEnum type; public DownloadCallBack() { } public DownloadCallBack(String path) { this.path = path; } public DownloadCallBack(MethodChannel.Result result, String path, String msgId, DownloadTypeEnum type) { this.result = result; this.path = path; this.msgId = msgId; this.type = type; } @Override public void onProgress(final V2TIMElem.V2ProgressInfo v2ProgressInfo) { TencentImPlugin.invokeListener(ListenerTypeEnum.DownloadProgress, new HashMap() { { put("type", type.getValue()); put("msgId", msgId); put("currentSize", v2ProgressInfo.getCurrentSize()); put("totalSize", v2ProgressInfo.getTotalSize()); } }); } /** * 成功事件 */ @Override public void onSuccess() { if (result != null) { result.success(path); } } /** * 失败事件 * * @param code 错误码 * @param desc 错误描述 */ @Override public void onError(int code, String desc) { if (this.result != null) { result.error(String.valueOf(code), desc, desc); } } /** * 下载类型枚举 */ public enum DownloadTypeEnum { /** * 语音 */ Sound(0), /** * 视频 */ Video(1), /** * 视频缩略图 */ VideoThumbnail(2), /** * 视频缩略图 */ File(3); /** * 枚举对应的常量值 */ private Integer value; DownloadTypeEnum(Integer value) { this.value = value; } public Integer getValue() { return value; } } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/TencentImPlugin.java ================================================ package top.huic.tencent_im_plugin; import android.content.Context; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.tencent.imsdk.v2.V2TIMConversation; import com.tencent.imsdk.v2.V2TIMConversationResult; import com.tencent.imsdk.v2.V2TIMCreateGroupMemberInfo; import com.tencent.imsdk.v2.V2TIMFriendApplication; import com.tencent.imsdk.v2.V2TIMFriendApplicationResult; import com.tencent.imsdk.v2.V2TIMFriendCheckResult; import com.tencent.imsdk.v2.V2TIMFriendGroup; import com.tencent.imsdk.v2.V2TIMFriendInfo; import com.tencent.imsdk.v2.V2TIMFriendInfoResult; import com.tencent.imsdk.v2.V2TIMFriendOperationResult; import com.tencent.imsdk.v2.V2TIMGroupApplication; import com.tencent.imsdk.v2.V2TIMGroupApplicationResult; import com.tencent.imsdk.v2.V2TIMGroupInfo; import com.tencent.imsdk.v2.V2TIMGroupInfoResult; import com.tencent.imsdk.v2.V2TIMGroupMemberFullInfo; import com.tencent.imsdk.v2.V2TIMGroupMemberInfoResult; import com.tencent.imsdk.v2.V2TIMGroupMemberOperationResult; import com.tencent.imsdk.v2.V2TIMGroupMemberSearchParam; import com.tencent.imsdk.v2.V2TIMGroupSearchParam; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMMessageListGetOption; import com.tencent.imsdk.v2.V2TIMMessageSearchParam; import com.tencent.imsdk.v2.V2TIMMessageSearchResult; import com.tencent.imsdk.v2.V2TIMOfflinePushConfig; import com.tencent.imsdk.v2.V2TIMOfflinePushInfo; import com.tencent.imsdk.v2.V2TIMReceiveMessageOptInfo; import com.tencent.imsdk.v2.V2TIMSDKConfig; import com.tencent.imsdk.v2.V2TIMSendCallback; import com.tencent.imsdk.v2.V2TIMSignalingInfo; import com.tencent.imsdk.v2.V2TIMUserFullInfo; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry.Registrar; import top.huic.tencent_im_plugin.entity.CustomConversationEntity; import top.huic.tencent_im_plugin.entity.CustomConversationResultEntity; import top.huic.tencent_im_plugin.entity.CustomFriendAddApplication; import top.huic.tencent_im_plugin.entity.CustomMessageEntity; import top.huic.tencent_im_plugin.entity.FindMessageEntity; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; import top.huic.tencent_im_plugin.enums.MessageNodeType; import top.huic.tencent_im_plugin.listener.CustomAdvancedMsgListener; import top.huic.tencent_im_plugin.listener.CustomConversationListener; import top.huic.tencent_im_plugin.listener.CustomFriendshipListener; import top.huic.tencent_im_plugin.listener.CustomGroupListener; import top.huic.tencent_im_plugin.listener.CustomSDKListener; import top.huic.tencent_im_plugin.listener.CustomSignalingListener; import top.huic.tencent_im_plugin.message.AbstractMessageNode; import top.huic.tencent_im_plugin.message.entity.AbstractMessageEntity; import top.huic.tencent_im_plugin.util.CommonUtil; import top.huic.tencent_im_plugin.util.JsonUtil; import top.huic.tencent_im_plugin.util.TencentImUtils; /** * TencentImPlugin */ public class TencentImPlugin implements FlutterPlugin, MethodCallHandler { /** * 全局上下文 */ public static Context context; /** * 与Flutter的通信管道 */ private static MethodChannel channel; /** * Sdk监听器 */ private final CustomSDKListener sdkListener = new CustomSDKListener(); /** * 消息监听器 */ private final CustomAdvancedMsgListener advancedMsgListener = new CustomAdvancedMsgListener(); /** * 会话监听器 */ private final CustomConversationListener conversationListener = new CustomConversationListener(); /** * 群监听器 */ private final CustomGroupListener groupListener = new CustomGroupListener(); /** * 关系链监听器 */ private final CustomFriendshipListener friendshipListener = new CustomFriendshipListener(); /** * 信令监听器 */ private final CustomSignalingListener signalingListener = new CustomSignalingListener(); public TencentImPlugin() { } private TencentImPlugin(Context context, MethodChannel channel) { TencentImPlugin.context = context; TencentImPlugin.channel = channel; JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.mask; } @Override public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) { final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "tencent_im_plugin"); channel.setMethodCallHandler(new TencentImPlugin(flutterPluginBinding.getApplicationContext(), channel)); } // This static function is optional and equivalent to onAttachedToEngine. It supports the old // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting // plugin registration via this function while apps migrate to use the new Android APIs // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. // // It is encouraged to share logic between onAttachedToEngine and registerWith to keep // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called // depending on the user's project. onAttachedToEngine or registerWith must both be defined // in the same class. public static void registerWith(Registrar registrar) { final MethodChannel channel = new MethodChannel(registrar.messenger(), "tencent_im_plugin"); channel.setMethodCallHandler(new TencentImPlugin(registrar.context(), channel)); } @Override public void onMethodCall(MethodCall call, Result result) { try { Method method = this.getClass().getDeclaredMethod(call.method, MethodCall.class, Result.class); method.setAccessible(true); method.invoke(this, call, result); } catch (NoSuchMethodException e) { result.notImplemented(); } catch (IllegalAccessException e) { result.notImplemented(); } catch (InvocationTargetException ignored) { } } @Override public void onDetachedFromEngine(FlutterPluginBinding binding) { } /** * 腾讯云Im初始化事件 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void initSDK(MethodCall methodCall, Result result) { String appid = CommonUtil.getParam(methodCall, result, "appid"); Integer logPrintLevel = methodCall.argument("logPrintLevel"); // 初始化 SDK V2TIMSDKConfig sdkConfig = new V2TIMSDKConfig(); if (logPrintLevel != null) { sdkConfig.setLogLevel(logPrintLevel); } V2TIMManager.getInstance().initSDK(context, Integer.parseInt(appid), sdkConfig, sdkListener); // 绑定消息监听 V2TIMManager.getMessageManager().addAdvancedMsgListener(this.advancedMsgListener); // 绑定会话监听器 V2TIMManager.getConversationManager().setConversationListener(this.conversationListener); // 绑定群监听器 V2TIMManager.getInstance().setGroupListener(this.groupListener); // 绑定关系链监听器 V2TIMManager.getFriendshipManager().setFriendListener(this.friendshipListener); // 绑定信令监听器 V2TIMManager.getSignalingManager().addSignalingListener(this.signalingListener); result.success(null); } /** * 反初始化 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void unInitSDK(MethodCall methodCall, Result result) { V2TIMManager.getInstance().unInitSDK(); V2TIMManager.getMessageManager().removeAdvancedMsgListener(this.advancedMsgListener); V2TIMManager.getSignalingManager().removeSignalingListener(this.signalingListener); result.success(null); } /** * 获得SDK版本 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getVersion(MethodCall methodCall, Result result) { result.success(V2TIMManager.getInstance().getVersion()); } /** * 获得服务器当前时间 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getServerTime(MethodCall methodCall, Result result) { result.success(V2TIMManager.getInstance().getServerTime()); } /** * 腾讯云 IM 登录 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void login(MethodCall methodCall, final Result result) { String userID = CommonUtil.getParam(methodCall, result, "userID"); String userSig = CommonUtil.getParam(methodCall, result, "userSig"); // 登录操作 V2TIMManager.getInstance().login(userID, userSig, new VoidCallBack(result)); } /** * 腾讯云 IM 退出登录 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void logout(MethodCall methodCall, final Result result) { V2TIMManager.getInstance().logout(new VoidCallBack(result)); } /** * 获得登录状态 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getLoginStatus(MethodCall methodCall, final Result result) { result.success(V2TIMManager.getInstance().getLoginStatus()); } /** * 腾讯云 获得当前登录用户 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getLoginUser(MethodCall methodCall, final Result result) { result.success(V2TIMManager.getInstance().getLoginUser()); } /** * 邀请某个人 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void invite(MethodCall methodCall, final Result result) { String invitee = CommonUtil.getParam(methodCall, result, "invitee"); String data = CommonUtil.getParam(methodCall, result, "data"); Boolean onlineUserOnly = CommonUtil.getParam(methodCall, result, "onlineUserOnly"); String offlinePushInfoStr = CommonUtil.getParam(methodCall, result, "offlinePushInfo"); int timeout = CommonUtil.getParam(methodCall, result, "timeout"); // 将离线推送配置转换为JSON对象以及离线推送对象 JSONObject jsonObject = JSON.parseObject(offlinePushInfoStr); V2TIMOfflinePushInfo offlinePushInfo = JSON.parseObject(offlinePushInfoStr, V2TIMOfflinePushInfo.class); if (jsonObject.get("disablePush") != null) { offlinePushInfo.disablePush(jsonObject.getBoolean("disablePush")); } // 发送邀请,并同步返回结果 result.success(V2TIMManager.getSignalingManager().invite(invitee, data, onlineUserOnly, offlinePushInfo, timeout, new VoidCallBack(null))); } /** * 邀请群内的某些人 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void inviteInGroup(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); List inviteeList = new ArrayList<>(Arrays.asList(CommonUtil.getParam(methodCall, result, "inviteeList").toString().split(","))); String data = CommonUtil.getParam(methodCall, result, "data"); Boolean onlineUserOnly = CommonUtil.getParam(methodCall, result, "onlineUserOnly"); int timeout = CommonUtil.getParam(methodCall, result, "timeout"); // 发送邀请,并同步返回结果 result.success(V2TIMManager.getSignalingManager().inviteInGroup(groupID, inviteeList, data, onlineUserOnly, timeout, new VoidCallBack(null))); } /** * 邀请方取消邀请 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void cancel(MethodCall methodCall, final Result result) { String inviteID = CommonUtil.getParam(methodCall, result, "inviteID"); String data = CommonUtil.getParam(methodCall, result, "data"); V2TIMManager.getSignalingManager().cancel(inviteID, data, new VoidCallBack(result)); } /** * 接收方接收邀请 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void accept(MethodCall methodCall, final Result result) { String inviteID = CommonUtil.getParam(methodCall, result, "inviteID"); String data = CommonUtil.getParam(methodCall, result, "data"); V2TIMManager.getSignalingManager().accept(inviteID, data, new VoidCallBack(result)); } /** * 接收方拒绝邀请 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void reject(MethodCall methodCall, final Result result) { String inviteID = CommonUtil.getParam(methodCall, result, "inviteID"); String data = CommonUtil.getParam(methodCall, result, "data"); V2TIMManager.getSignalingManager().reject(inviteID, data, new VoidCallBack(result)); } /** * 获得信令信息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getSignalingInfo(MethodCall methodCall, final Result result) { String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { result.success(JsonUtil.toJSONString(V2TIMManager.getSignalingManager().getSignalingInfo(message))); } }); } /** * 添加邀请信令(可以用于群离线推送消息触发的邀请信令) * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void addInvitedSignaling(MethodCall methodCall, final Result result) { String info = CommonUtil.getParam(methodCall, result, "info"); V2TIMManager.getSignalingManager().addInvitedSignaling(JSON.parseObject(info, V2TIMSignalingInfo.class), new VoidCallBack(result)); } /** * 发送消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void sendMessage(MethodCall methodCall, final Result result) { String nodeStr = CommonUtil.getParam(methodCall, result, "node"); Map node = JSON.parseObject(nodeStr, Map.class); // 设置节点信息获得V2TIMMessage对象 AbstractMessageNode messageNode = MessageNodeType.getMessageNodeTypeByV2TIMConstant(Integer.valueOf(node.get("nodeType").toString())).getMessageNodeInterface(); AbstractMessageEntity messageEntity = (AbstractMessageEntity) JSON.parseObject(nodeStr, messageNode.getEntityClass()); V2TIMMessage message = messageNode.getV2TIMMessage(messageEntity); // 发送消息 this._sendMessage(message, methodCall, result); } /** * 重发消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void resendMessage(final MethodCall methodCall, final Result result) { String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { _sendMessage(message, methodCall, result); } }); } /** * 发送消息 * * @param message V2TIMMessage消息对象 * @param methodCall Flutter方法调用对象 * @param result Flutter 返回结果 */ private void _sendMessage(V2TIMMessage message, MethodCall methodCall, final Result result) { String receiver = methodCall.argument("receiver"); final String groupID = methodCall.argument("groupID"); boolean ol = CommonUtil.getParam(methodCall, result, "ol"); Integer priority = CommonUtil.getParam(methodCall, result, "priority"); String offlinePushInfo = methodCall.argument("offlinePushInfo"); Integer localCustomInt = methodCall.argument("localCustomInt"); String localCustomStr = methodCall.argument("localCustomStr"); if (localCustomInt != null) { message.setLocalCustomInt(localCustomInt); } if (localCustomStr != null) { message.setLocalCustomData(localCustomStr); } final String[] msgId = new String[1]; V2TIMSendCallback callback = new V2TIMSendCallback() { @Override public void onError(final int i, final String s) { TencentImPlugin.invokeListener(ListenerTypeEnum.MessageSendFail, new HashMap() { { put("msgId", msgId[0]); put("code", i); put("desc", s); } }); } @Override public void onSuccess(V2TIMMessage o) { TencentImPlugin.invokeListener(ListenerTypeEnum.MessageSendSucc, new CustomMessageEntity(o)); } @Override public void onProgress(final int i) { TencentImPlugin.invokeListener(ListenerTypeEnum.MessageSendProgress, new HashMap() { { put("msgId", msgId[0]); put("progress", i); } }); } }; // 发送消息 msgId[0] = V2TIMManager.getMessageManager().sendMessage(message, receiver, groupID, priority, ol, offlinePushInfo == null ? null : JSON.parseObject(offlinePushInfo, V2TIMOfflinePushInfo.class), callback); result.success(msgId[0]); } /** * 撤回消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void revokeMessage(MethodCall methodCall, final Result result) { String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { V2TIMManager.getMessageManager().revokeMessage(message, new VoidCallBack(result)); } }); } /** * 获得单聊历史记录 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getC2CHistoryMessageList(MethodCall methodCall, final Result result) { final String userID = CommonUtil.getParam(methodCall, result, "userID"); final int count = CommonUtil.getParam(methodCall, result, "count"); final String lastMsgStr = methodCall.argument("lastMsg"); // 返回回调对象 final ValueCallBack> resultCallBack = new ValueCallBack>(result) { @Override public void onSuccess(List v2TIMMessages) { List resultData = new ArrayList<>(v2TIMMessages.size()); for (V2TIMMessage v2TIMMessage : v2TIMMessages) { resultData.add(new CustomMessageEntity(v2TIMMessage)); } result.success(JsonUtil.toJSONString(resultData)); } }; // 根据是否传递最后一条消息进行特殊处理 if (lastMsgStr == null) { V2TIMManager.getMessageManager().getC2CHistoryMessageList(userID, count, null, resultCallBack); } else { TencentImUtils.getMessageByFindMessageEntity(lastMsgStr, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { V2TIMManager.getMessageManager().getC2CHistoryMessageList(userID, count, message, resultCallBack); } }); } } /** * 获得群聊历史记录 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupHistoryMessageList(MethodCall methodCall, final Result result) { final String groupID = CommonUtil.getParam(methodCall, result, "groupID"); final int count = CommonUtil.getParam(methodCall, result, "count"); String lastMsgStr = methodCall.argument("lastMsg"); // 返回回调对象 final ValueCallBack> resultCallBack = new ValueCallBack>(result) { @Override public void onSuccess(List v2TIMMessages) { List resultData = new ArrayList<>(v2TIMMessages.size()); for (V2TIMMessage v2TIMMessage : v2TIMMessages) { resultData.add(new CustomMessageEntity(v2TIMMessage)); } result.success(JsonUtil.toJSONString(resultData)); } }; // 根据是否传递最后一条消息进行特殊处理 if (lastMsgStr == null) { V2TIMManager.getMessageManager().getGroupHistoryMessageList(groupID, count, null, resultCallBack); } else { TencentImUtils.getMessageByFindMessageEntity(lastMsgStr, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { V2TIMManager.getMessageManager().getGroupHistoryMessageList(groupID, count, message, resultCallBack); } }); } } /** * 获得消息记录 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getHistoryMessageList(MethodCall methodCall, final Result result) { final String groupID = methodCall.argument("groupID"); final String userID = methodCall.argument("userID"); final int count = CommonUtil.getParam(methodCall, result, "count"); final int type = CommonUtil.getParam(methodCall, result, "type"); String lastMsgStr = methodCall.argument("lastMsg"); // 返回回调对象 final ValueCallBack> resultCallBack = new ValueCallBack>(result) { @Override public void onSuccess(List v2TIMMessages) { List resultData = new ArrayList<>(v2TIMMessages.size()); for (V2TIMMessage v2TIMMessage : v2TIMMessages) { resultData.add(new CustomMessageEntity(v2TIMMessage)); } result.success(JsonUtil.toJSONString(resultData)); } }; // 根据是否传递最后一条消息进行特殊处理 final V2TIMMessageListGetOption opt = new V2TIMMessageListGetOption(); opt.setUserID(userID); opt.setGroupID(groupID); opt.setGetType(type); opt.setCount(count); if (lastMsgStr == null) { V2TIMManager.getMessageManager().getHistoryMessageList(opt, resultCallBack); } else { TencentImUtils.getMessageByFindMessageEntity(lastMsgStr, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { opt.setLastMsg(message); V2TIMManager.getMessageManager().getHistoryMessageList(opt, resultCallBack); } }); } } /** * 设置单聊已读 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void markC2CMessageAsRead(MethodCall methodCall, final Result result) { String userID = CommonUtil.getParam(methodCall, result, "userID"); V2TIMManager.getMessageManager().markC2CMessageAsRead(userID, new VoidCallBack(result)); } /** * 设置群聊已读 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void markGroupMessageAsRead(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); V2TIMManager.getMessageManager().markGroupMessageAsRead(groupID, new VoidCallBack(result)); } /** * 删除本地消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteMessageFromLocalStorage(MethodCall methodCall, final Result result) { String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { V2TIMManager.getMessageManager().deleteMessageFromLocalStorage(message, new VoidCallBack(result)); } }); } /** * 删除本地及漫游消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteMessages(MethodCall methodCall, final Result result) { String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(JSON.parseArray(message, FindMessageEntity.class), new ValueCallBack>(result) { @Override public void onSuccess(List ms) { V2TIMManager.getMessageManager().deleteMessages(ms, new VoidCallBack(result)); } }); } /** * 向群组消息列表中添加一条消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void insertGroupMessageToLocalStorage(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String sender = CommonUtil.getParam(methodCall, result, "sender"); String nodeStr = CommonUtil.getParam(methodCall, result, "node"); Map node = JSON.parseObject(nodeStr, Map.class); // 获得消息对象 AbstractMessageNode messageNode = MessageNodeType.getMessageNodeTypeByV2TIMConstant(Integer.valueOf(node.get("nodeType").toString())).getMessageNodeInterface(); AbstractMessageEntity messageEntity = (AbstractMessageEntity) JSON.parseObject(nodeStr, messageNode.getEntityClass()); // 添加消息 V2TIMManager.getMessageManager().insertGroupMessageToLocalStorage(messageNode.getV2TIMMessage(messageEntity), groupID, sender, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { result.success(null); } }); } /** * 向群组消息列表中添加一条消息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void insertC2CMessageToLocalStorage(MethodCall methodCall, final Result result) { String userID = CommonUtil.getParam(methodCall, result, "userID"); String sender = CommonUtil.getParam(methodCall, result, "sender"); String nodeStr = CommonUtil.getParam(methodCall, result, "node"); Map node = JSON.parseObject(nodeStr, Map.class); // 获得消息对象 AbstractMessageNode messageNode = MessageNodeType.getMessageNodeTypeByV2TIMConstant(Integer.valueOf(node.get("nodeType").toString())).getMessageNodeInterface(); AbstractMessageEntity messageEntity = (AbstractMessageEntity) JSON.parseObject(nodeStr, messageNode.getEntityClass()); // 添加消息 V2TIMManager.getMessageManager().insertC2CMessageToLocalStorage(messageNode.getV2TIMMessage(messageEntity), userID, sender, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { result.success(null); } }); } /** * 下载视频 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void downloadVideo(MethodCall methodCall, final Result result) { final String path = CommonUtil.getParam(methodCall, result, "path"); String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { message.getVideoElem().downloadVideo(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.Video)); } }); } /** * 下载视频缩略图 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void downloadVideoThumbnail(MethodCall methodCall, final Result result) { final String path = CommonUtil.getParam(methodCall, result, "path"); String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { message.getVideoElem().downloadSnapshot(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.VideoThumbnail)); } }); } /** * 下载语音 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void downloadSound(MethodCall methodCall, final Result result) { final String path = CommonUtil.getParam(methodCall, result, "path"); String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { message.getSoundElem().downloadSound(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.Sound)); } }); } /** * 下载文件 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void downloadFile(MethodCall methodCall, final Result result) { final String path = CommonUtil.getParam(methodCall, result, "path"); String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { message.getFileElem().downloadFile(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.File)); } }); } /** * 设置消息本地Str * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setMessageLocalCustomStr(MethodCall methodCall, final Result result) { final String data = CommonUtil.getParam(methodCall, result, "data"); String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { message.setLocalCustomData(data); result.success(null); } }); } /** * 设置消息本地Int * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setMessageLocalCustomInt(MethodCall methodCall, final Result result) { final Integer data = CommonUtil.getParam(methodCall, result, "data"); String message = CommonUtil.getParam(methodCall, result, "message"); TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessage message) { message.setLocalCustomInt(data); result.success(null); } }); } /** * 查找消息列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void findMessages(MethodCall methodCall, final Result result) { String messages = CommonUtil.getParam(methodCall, result, "messages"); TencentImUtils.getMessageByFindMessageEntity(JSON.parseArray(messages, FindMessageEntity.class), new ValueCallBack>(result) { @Override public void onSuccess(List v2TIMMessages) { List ms = new ArrayList<>(v2TIMMessages.size()); for (V2TIMMessage v2TIMMessage : v2TIMMessages) { ms.add(new CustomMessageEntity(v2TIMMessage)); } result.success(JsonUtil.toJSONString(ms)); } }); } /** * 创建群 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void createGroup(MethodCall methodCall, final Result result) { String info = CommonUtil.getParam(methodCall, result, "info"); String memberListStr = methodCall.argument("memberList"); V2TIMManager.getGroupManager().createGroup(JSON.parseObject(info, V2TIMGroupInfo.class), memberListStr == null ? null : JSON.parseArray(memberListStr, V2TIMCreateGroupMemberInfo.class), new ValueCallBack(result)); } /** * 加入群 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void joinGroup(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String message = CommonUtil.getParam(methodCall, result, "message"); V2TIMManager.getInstance().joinGroup(groupID, message, new VoidCallBack(result)); } /** * 退出群 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void quitGroup(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); V2TIMManager.getInstance().quitGroup(groupID, new VoidCallBack(result)); } /** * 解散群 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void dismissGroup(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); V2TIMManager.getInstance().dismissGroup(groupID, new VoidCallBack(result)); } /** * 获得已加入的群列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getJoinedGroupList(MethodCall methodCall, final Result result) { V2TIMManager.getGroupManager().getJoinedGroupList(new ValueCallBack>(result)); } /** * 拉取群资料 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupsInfo(MethodCall methodCall, final Result result) { String groupIDList = CommonUtil.getParam(methodCall, result, "groupIDList"); V2TIMManager.getGroupManager().getGroupsInfo(Arrays.asList(groupIDList.split(",")), new ValueCallBack>(result)); } /** * 修改群资料 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setGroupInfo(MethodCall methodCall, final Result result) { String info = CommonUtil.getParam(methodCall, result, "info"); V2TIMManager.getGroupManager().setGroupInfo(JSON.parseObject(info, V2TIMGroupInfo.class), new VoidCallBack(result)); } /** * 搜索群 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void searchGroups(MethodCall methodCall, final Result result) { List keywordList = CommonUtil.getParam(methodCall, result, "keywordList"); Boolean isSearchGroupID = CommonUtil.getParam(methodCall, result, "isSearchGroupID"); Boolean isSearchGroupName = CommonUtil.getParam(methodCall, result, "isSearchGroupName"); // 群搜索 V2TIMGroupSearchParam param = new V2TIMGroupSearchParam(); param.setKeywordList(keywordList); param.setSearchGroupName(isSearchGroupName); param.setSearchGroupID(isSearchGroupID); V2TIMManager.getGroupManager().searchGroups(param, new ValueCallBack>(result)); } /** * 搜索群成员 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void searchGroupMembers(MethodCall methodCall, final Result result) { List keywordList = CommonUtil.getParam(methodCall, result, "keywordList"); List groupIDList = CommonUtil.getParam(methodCall, result, "groupIDList"); Boolean isSearchMemberNameCard = CommonUtil.getParam(methodCall, result, "isSearchMemberNameCard"); Boolean isSearchMemberUserID = CommonUtil.getParam(methodCall, result, "isSearchMemberUserID"); Boolean isSearchMemberRemark = CommonUtil.getParam(methodCall, result, "isSearchMemberRemark"); Boolean isSearchMemberNickName = CommonUtil.getParam(methodCall, result, "isSearchMemberNickName"); // 搜索群成员 V2TIMGroupMemberSearchParam param = new V2TIMGroupMemberSearchParam(); param.setKeywordList(keywordList); param.setGroupIDList(groupIDList); param.setSearchMemberNameCard(isSearchMemberNameCard); param.setSearchMemberUserID(isSearchMemberUserID); param.setSearchMemberRemark(isSearchMemberRemark); param.setSearchMemberNickName(isSearchMemberNickName); V2TIMManager.getGroupManager().searchGroupMembers(param, new ValueCallBack>>(result)); } /** * 修改C2C消息接收选项 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setC2CReceiveMessageOpt(MethodCall methodCall, final Result result) { List ids = CommonUtil.getParam(methodCall, result, "ids"); int opt = CommonUtil.getParam(methodCall, result, "opt"); V2TIMManager.getMessageManager().setC2CReceiveMessageOpt(ids, opt, new VoidCallBack(result)); } /** * 修改群消息接收选项 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setGroupReceiveMessageOpt(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); int opt = CommonUtil.getParam(methodCall, result, "opt"); V2TIMManager.getMessageManager().setGroupReceiveMessageOpt(groupID, opt, new VoidCallBack(result)); } /** * 获得C2C消息接收选项 */ private void getC2CReceiveMessageOpt(MethodCall call, final Result result) { V2TIMManager.getMessageManager().getC2CReceiveMessageOpt(call.>arguments(), new ValueCallBack>(result) { @Override public void onSuccess(List v2TIMReceiveMessageOptInfos) { Map res = new HashMap<>(v2TIMReceiveMessageOptInfos.size(), 1); for (V2TIMReceiveMessageOptInfo item : v2TIMReceiveMessageOptInfos) { res.put(item.getUserID(), item.getC2CReceiveMessageOpt()); } result.success(res); } }); } /** * 初始化群属性,会清空原有的群属性列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void initGroupAttributes(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String attributes = CommonUtil.getParam(methodCall, result, "attributes"); V2TIMManager.getGroupManager().initGroupAttributes(groupID, JSON.parseObject(attributes, HashMap.class), new VoidCallBack(result)); } /** * 设置群属性。已有该群属性则更新其 value 值,没有该群属性则添加该属性。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setGroupAttributes(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String attributes = CommonUtil.getParam(methodCall, result, "attributes"); V2TIMManager.getGroupManager().setGroupAttributes(groupID, JSON.parseObject(attributes, HashMap.class), new VoidCallBack(result)); } /** * 删除指定群属性,keys 传 null 则清空所有群属性。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteGroupAttributes(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String keys = methodCall.argument("keys"); V2TIMManager.getGroupManager().deleteGroupAttributes(groupID, keys == null ? null : Arrays.asList(keys.split(",")), new VoidCallBack(result)); } /** * 获取指定群属性,keys 传 null 则获取所有群属性。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupAttributes(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String keys = methodCall.argument("keys"); V2TIMManager.getGroupManager().getGroupAttributes(groupID, keys == null ? null : Arrays.asList(keys.split(",")), new ValueCallBack>(result)); } /** * 获取指定群在线人数 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupOnlineMemberCount(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); V2TIMManager.getGroupManager().getGroupOnlineMemberCount(groupID, new ValueCallBack(result) { @Override public void onSuccess(Integer data) { result.success(data); } }); } /** * 获取群成员列表。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupMemberList(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); int filter = CommonUtil.getParam(methodCall, result, "filter"); long nextSeq = Long.parseLong(CommonUtil.getParam(methodCall, result, "nextSeq").toString()); V2TIMManager.getGroupManager().getGroupMemberList(groupID, filter, nextSeq, new ValueCallBack(result)); } /** * 获取指定的群成员资料。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupMembersInfo(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String memberList = CommonUtil.getParam(methodCall, result, "memberList"); V2TIMManager.getGroupManager().getGroupMembersInfo(groupID, Arrays.asList(memberList.split(",")), new ValueCallBack>(result)); } /** * 修改指定的群成员资料。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setGroupMemberInfo(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String info = CommonUtil.getParam(methodCall, result, "info"); V2TIMManager.getGroupManager().setGroupMemberInfo(groupID, JSON.parseObject(info, V2TIMGroupMemberFullInfo.class), new VoidCallBack(result)); } /** * 禁言。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void muteGroupMember(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String userID = CommonUtil.getParam(methodCall, result, "userID"); int seconds = CommonUtil.getParam(methodCall, result, "seconds"); V2TIMManager.getGroupManager().muteGroupMember(groupID, userID, seconds, new VoidCallBack(result)); } /** * 邀请他人入群。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void inviteUserToGroup(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String userList = CommonUtil.getParam(methodCall, result, "userList"); V2TIMManager.getGroupManager().inviteUserToGroup(groupID, Arrays.asList(userList.split(",")), new ValueCallBack>(result)); } /** * 踢人。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void kickGroupMember(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String memberList = CommonUtil.getParam(methodCall, result, "memberList"); String reason = CommonUtil.getParam(methodCall, result, "reason"); V2TIMManager.getGroupManager().kickGroupMember(groupID, Arrays.asList(memberList.split(",")), reason, new ValueCallBack>(result)); } /** * 切换群成员角色。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setGroupMemberRole(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String userID = CommonUtil.getParam(methodCall, result, "userID"); int role = CommonUtil.getParam(methodCall, result, "role"); V2TIMManager.getGroupManager().setGroupMemberRole(groupID, userID, role, new VoidCallBack(result)); } /** * 转让群主。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void transferGroupOwner(MethodCall methodCall, final Result result) { String groupID = CommonUtil.getParam(methodCall, result, "groupID"); String userID = CommonUtil.getParam(methodCall, result, "userID"); V2TIMManager.getGroupManager().transferGroupOwner(groupID, userID, new VoidCallBack(result)); } /** * 获得群申请列表。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getGroupApplicationList(MethodCall methodCall, final Result result) { V2TIMManager.getGroupManager().getGroupApplicationList(new ValueCallBack(result)); } /** * 同意某一条加群申请。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void acceptGroupApplication(MethodCall methodCall, final Result result) { String application = CommonUtil.getParam(methodCall, result, "application"); final String reason = CommonUtil.getParam(methodCall, result, "reason"); TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(application, new ValueCallBack(result) { @Override public void onSuccess(V2TIMGroupApplication v2TIMGroupApplication) { V2TIMManager.getGroupManager().acceptGroupApplication(v2TIMGroupApplication, reason, new VoidCallBack(result)); } }); } /** * 拒绝某一条加群申请。 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void refuseGroupApplication(MethodCall methodCall, final Result result) { final String application = CommonUtil.getParam(methodCall, result, "application"); final String reason = CommonUtil.getParam(methodCall, result, "reason"); TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(application, new ValueCallBack(result) { @Override public void onSuccess(V2TIMGroupApplication v2TIMGroupApplication) { V2TIMManager.getGroupManager().refuseGroupApplication(v2TIMGroupApplication, reason, new VoidCallBack(result)); } }); } /** * 标记申请列表为已读 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setGroupApplicationRead(MethodCall methodCall, final Result result) { V2TIMManager.getGroupManager().setGroupApplicationRead(new VoidCallBack(result)); } /** * 获得会话列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getConversationList(MethodCall methodCall, final Result result) { Long nextSeq = Long.parseLong(CommonUtil.getParam(methodCall, result, "nextSeq").toString()); Integer count = CommonUtil.getParam(methodCall, result, "count"); V2TIMManager.getConversationManager().getConversationList(nextSeq, count, new ValueCallBack(result) { @Override public void onSuccess(V2TIMConversationResult v2TIMConversationResult) { result.success(JsonUtil.toJSONString(new CustomConversationResultEntity(v2TIMConversationResult))); } }); } /** * 获得指定会话 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getConversation(MethodCall methodCall, final Result result) { String conversationID = CommonUtil.getParam(methodCall, result, "conversationID"); V2TIMManager.getConversationManager().getConversation(conversationID, new ValueCallBack(result) { @Override public void onSuccess(V2TIMConversation v2TIMConversation) { result.success(JsonUtil.toJSONString(new CustomConversationEntity(v2TIMConversation))); } }); } /** * 删除会话 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteConversation(MethodCall methodCall, final Result result) { String conversationID = CommonUtil.getParam(methodCall, result, "conversationID"); V2TIMManager.getConversationManager().deleteConversation(conversationID, new VoidCallBack(result)); } /** * 设置会话草稿 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setConversationDraft(MethodCall methodCall, final Result result) { String conversationID = CommonUtil.getParam(methodCall, result, "conversationID"); String draftText = methodCall.argument("draftText"); V2TIMManager.getConversationManager().setConversationDraft(conversationID, draftText, new VoidCallBack(result)); } /** * 会话置顶 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void pinConversation(MethodCall methodCall, final Result result) { String conversationID = CommonUtil.getParam(methodCall, result, "conversationID"); boolean isPinned = methodCall.argument("isPinned"); V2TIMManager.getConversationManager().pinConversation(conversationID, isPinned, new VoidCallBack(result)); } /** * 获得未读会话总数 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getTotalUnreadMessageCount(MethodCall methodCall, final Result result) { V2TIMManager.getConversationManager().getTotalUnreadMessageCount(new ValueCallBack(result)); } /** * 获得用户信息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getUsersInfo(MethodCall methodCall, final Result result) { String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getInstance().getUsersInfo(Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 修改个人资料 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setSelfInfo(MethodCall methodCall, final Result result) { String info = CommonUtil.getParam(methodCall, result, "info"); V2TIMManager.getInstance().setSelfInfo(JSON.parseObject(info, V2TIMUserFullInfo.class), new VoidCallBack(result)); } /** * 添加到黑名单 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void addToBlackList(MethodCall methodCall, final Result result) { String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getFriendshipManager().addToBlackList(Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 从黑名单中删除 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteFromBlackList(MethodCall methodCall, final Result result) { String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getFriendshipManager().deleteFromBlackList(Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 获得黑名单列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getBlackList(MethodCall methodCall, final Result result) { V2TIMManager.getFriendshipManager().getBlackList(new ValueCallBack>(result)); } /** * 腾讯云 设置离线推送Token * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setOfflinePushConfig(MethodCall methodCall, final Result result) { String token = CommonUtil.getParam(methodCall, result, "token"); Long bussid = Long.parseLong(CommonUtil.getParam(methodCall, result, "bussid").toString()); Boolean tpns = CommonUtil.getParam(methodCall, result, "tpns"); V2TIMManager.getOfflinePushManager().setOfflinePushConfig(new V2TIMOfflinePushConfig(bussid, token, tpns), new VoidCallBack(result)); } /** * 腾讯云 设置未读桌标 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setUnreadBadge(MethodCall methodCall, final Result result) { int number = CommonUtil.getParam(methodCall, result, "number"); V2TIMManager.getOfflinePushManager().doBackground(number, new VoidCallBack(result)); } /** * 腾讯云 获得好友列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getFriendList(MethodCall methodCall, final Result result) { V2TIMManager.getFriendshipManager().getFriendList(new ValueCallBack>(result)); } /** * 获得指定好友信息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getFriendsInfo(MethodCall methodCall, final Result result) { String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getFriendshipManager().getFriendsInfo(Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 设置好友资料 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setFriendInfo(MethodCall methodCall, final Result result) { String info = CommonUtil.getParam(methodCall, result, "info"); V2TIMManager.getFriendshipManager().setFriendInfo(JSON.parseObject(info, V2TIMFriendInfo.class), new VoidCallBack(result)); } /** * 添加好友 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void addFriend(MethodCall methodCall, final Result result) { String info = CommonUtil.getParam(methodCall, result, "info"); V2TIMManager.getFriendshipManager().addFriend(JSON.parseObject(info, CustomFriendAddApplication.class), new ValueCallBack(result)); } /** * 删除好友 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteFromFriendList(MethodCall methodCall, final Result result) { String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); int deleteType = CommonUtil.getParam(methodCall, result, "deleteType"); V2TIMManager.getFriendshipManager().deleteFromFriendList(Arrays.asList(userIDList.split(",")), deleteType, new ValueCallBack>(result)); } /** * 检查好友关系 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void checkFriend(MethodCall methodCall, final Result result) { String userID = CommonUtil.getParam(methodCall, result, "userID"); int checkType = CommonUtil.getParam(methodCall, result, "checkType"); V2TIMManager.getFriendshipManager().checkFriend(Collections.singletonList(userID), checkType, new ValueCallBack>(result) { @Override public void onSuccess(List v2TIMFriendCheckResults) { result.success(v2TIMFriendCheckResults.size() == 0 ? null : JsonUtil.toJSONString(v2TIMFriendCheckResults.get(0))); } }); } /** * 获得好友申请列表 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getFriendApplicationList(MethodCall methodCall, final Result result) { V2TIMManager.getFriendshipManager().getFriendApplicationList(new ValueCallBack(result)); } /** * 好友同意申请 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void acceptFriendApplication(MethodCall methodCall, final Result result) { final String application = CommonUtil.getParam(methodCall, result, "application"); final int responseType = CommonUtil.getParam(methodCall, result, "responseType"); TencentImUtils.getFriendApplicationByFindGroupApplicationEntity(application, new ValueCallBack(result) { @Override public void onSuccess(V2TIMFriendApplication v2TIMFriendApplication) { V2TIMManager.getFriendshipManager().acceptFriendApplication(v2TIMFriendApplication, responseType, new ValueCallBack(result)); } }); } /** * 好友拒绝申请 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void refuseFriendApplication(MethodCall methodCall, final Result result) { String application = CommonUtil.getParam(methodCall, result, "application"); TencentImUtils.getFriendApplicationByFindGroupApplicationEntity(application, new ValueCallBack(result) { @Override public void onSuccess(V2TIMFriendApplication v2TIMFriendApplication) { V2TIMManager.getFriendshipManager().refuseFriendApplication(v2TIMFriendApplication, new ValueCallBack(result)); } }); } /** * 删除好友申请 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteFriendApplication(MethodCall methodCall, final Result result) { String application = CommonUtil.getParam(methodCall, result, "application"); TencentImUtils.getFriendApplicationByFindGroupApplicationEntity(application, new ValueCallBack(result) { @Override public void onSuccess(V2TIMFriendApplication v2TIMFriendApplication) { V2TIMManager.getFriendshipManager().deleteFriendApplication(v2TIMFriendApplication, new VoidCallBack(result)); } }); } /** * 设置好友申请为已读 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void setFriendApplicationRead(MethodCall methodCall, final Result result) { V2TIMManager.getFriendshipManager().setFriendApplicationRead(new VoidCallBack(result)); } /** * 新建好友分组 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void createFriendGroup(MethodCall methodCall, final Result result) { String groupName = CommonUtil.getParam(methodCall, result, "groupName"); String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getFriendshipManager().createFriendGroup(groupName, Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 获得分组信息 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void getFriendGroups(MethodCall methodCall, final Result result) { String groupNameList = methodCall.argument("groupNameList"); V2TIMManager.getFriendshipManager().getFriendGroups(groupNameList == null ? null : Arrays.asList(groupNameList.split(",")), new ValueCallBack>(result)); } /** * 删除好友分组 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteFriendGroup(MethodCall methodCall, final Result result) { String groupNameList = CommonUtil.getParam(methodCall, result, "groupNameList"); V2TIMManager.getFriendshipManager().deleteFriendGroup(Arrays.asList(groupNameList.split(",")), new VoidCallBack(result)); } /** * 修改分组名称 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void renameFriendGroup(MethodCall methodCall, final Result result) { String oldName = CommonUtil.getParam(methodCall, result, "oldName"); String newName = CommonUtil.getParam(methodCall, result, "newName"); V2TIMManager.getFriendshipManager().renameFriendGroup(oldName, newName, new VoidCallBack(result)); } /** * 添加好友到分组 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void addFriendsToFriendGroup(MethodCall methodCall, final Result result) { String groupName = CommonUtil.getParam(methodCall, result, "groupName"); String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getFriendshipManager().addFriendsToFriendGroup(groupName, Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 从分组中删除好友 * * @param methodCall 方法调用对象 * @param result 返回结果对象 */ private void deleteFriendsFromFriendGroup(MethodCall methodCall, final Result result) { String groupName = CommonUtil.getParam(methodCall, result, "groupName"); String userIDList = CommonUtil.getParam(methodCall, result, "userIDList"); V2TIMManager.getFriendshipManager().deleteFriendsFromFriendGroup(groupName, Arrays.asList(userIDList.split(",")), new ValueCallBack>(result)); } /** * 搜索本地消息 */ private void searchLocalMessages(MethodCall call, final Result result) { V2TIMMessageSearchParam param = new V2TIMMessageSearchParam(); param.setConversationID(call.argument("conversationId")); param.setKeywordList(call.>argument("keyword")); param.setKeywordListMatchType(call.argument("keywordMatchType")); param.setSenderUserIDList(call.>argument("senderUserIds")); param.setMessageTypeList(call.>argument("messageTypes")); param.setSearchTimePosition(call.argument("searchTimePosition")); param.setSearchTimePeriod(call.argument("searchTimePeriod")); param.setPageSize(call.argument("pageSize")); param.setPageIndex(call.argument("pageIndex")); V2TIMManager.getMessageManager().searchLocalMessages(param, new ValueCallBack(result) { @Override public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) { } }); } /** * 调用监听器 * * @param type 类型 * @param params 参数 */ public static void invokeListener(ListenerTypeEnum type, Object params) { final Map resultParams = new HashMap<>(2, 1); resultParams.put("type", type); resultParams.put("params", params); CommonUtil.runMainThreadMethod(new Runnable() { @Override public void run() { channel.invokeMethod("onListener", JsonUtil.toJSONString(resultParams)); } }); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/ValueCallBack.java ================================================ package top.huic.tencent_im_plugin; import com.tencent.imsdk.v2.V2TIMValueCallback; import io.flutter.plugin.common.MethodChannel.Result; import top.huic.tencent_im_plugin.util.JsonUtil; /** * 值改变回调 * * @author 蒋具宏 */ public class ValueCallBack implements V2TIMValueCallback { /** * 回调 */ private Result result; public ValueCallBack(Result result) { this.result = result; } /** * 成功事件 * * @param t 结果 */ @Override public void onSuccess(T t) { if (result != null) { if(t instanceof Number || t instanceof String || t instanceof Boolean){ result.success(t); }else{ result.success(JsonUtil.toJSONString(t)); } } } /** * 失败事件 * * @param code 错误码 * @param desc 错误描述 */ @Override public void onError(int code, String desc) { if (this.result != null) { result.error(String.valueOf(code), desc, desc); } } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/VoidCallBack.java ================================================ package top.huic.tencent_im_plugin; import com.tencent.imsdk.v2.V2TIMCallback; import io.flutter.plugin.common.MethodChannel; /** * 操作结果回调 * * @author 蒋具宏 */ public class VoidCallBack implements V2TIMCallback { /** * 回调 */ private MethodChannel.Result result; public VoidCallBack(MethodChannel.Result result) { this.result = result; } @Override public void onError(int code, String desc) { if (result != null) { result.error(String.valueOf(code), "Execution Error", desc); } } @Override public void onSuccess() { if (result != null) { result.success(null); } } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/CustomConversationEntity.java ================================================ package top.huic.tencent_im_plugin.entity; import com.tencent.imsdk.v2.V2TIMConversation; import com.tencent.imsdk.v2.V2TIMGroupAtInfo; import java.util.List; import top.huic.tencent_im_plugin.util.BeanUtils; /** * 自定义会话实体 */ public class CustomConversationEntity { /** * 会话ID */ String conversationID; /** * 会话类型 */ int type; /** * 用户ID */ String userID; /** * 群ID */ String groupID; /** * 显示名称 */ String showName; /** * 头像 */ String faceUrl; /** * 接收消息选项(群会话有效) */ int recvOpt; /** * 群类型 */ String groupType; /** * 未读数量 */ int unreadCount; /** * 最后一条消息 */ CustomMessageEntity lastMessage; /** * 草稿文本 */ String draftText; /** * 草稿时间 */ Long draftTimestamp; /** * 是否置顶 */ boolean pinned; /** * \@信息列表 */ List groupAtInfoList; public CustomConversationEntity() { } public CustomConversationEntity(V2TIMConversation data) { BeanUtils.copyProperties(data, this, "lastMessage"); if (data.getLastMessage() != null) { this.lastMessage = new CustomMessageEntity(data.getLastMessage()); } } public String getConversationID() { return conversationID; } public void setConversationID(String conversationID) { this.conversationID = conversationID; } public int getType() { return type; } public void setType(int type) { this.type = type; } public String getUserID() { return userID; } public void setUserID(String userID) { this.userID = userID; } public String getGroupID() { return groupID; } public void setGroupID(String groupID) { this.groupID = groupID; } public String getShowName() { return showName; } public void setShowName(String showName) { this.showName = showName; } public String getFaceUrl() { return faceUrl; } public void setFaceUrl(String faceUrl) { this.faceUrl = faceUrl; } public int getRecvOpt() { return recvOpt; } public void setRecvOpt(int recvOpt) { this.recvOpt = recvOpt; } public String getGroupType() { return groupType; } public void setGroupType(String groupType) { this.groupType = groupType; } public int getUnreadCount() { return unreadCount; } public void setUnreadCount(int unreadCount) { this.unreadCount = unreadCount; } public CustomMessageEntity getLastMessage() { return lastMessage; } public void setLastMessage(CustomMessageEntity lastMessage) { this.lastMessage = lastMessage; } public String getDraftText() { return draftText; } public void setDraftText(String draftText) { this.draftText = draftText; } public Long getDraftTimestamp() { return draftTimestamp; } public void setDraftTimestamp(Long draftTimestamp) { this.draftTimestamp = draftTimestamp; } public List getGroupAtInfoList() { return groupAtInfoList; } public void setGroupAtInfoList(List groupAtInfoList) { this.groupAtInfoList = groupAtInfoList; } public boolean isPinned() { return pinned; } public void setPinned(boolean pinned) { this.pinned = pinned; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/CustomConversationResultEntity.java ================================================ package top.huic.tencent_im_plugin.entity; import com.tencent.imsdk.v2.V2TIMConversation; import com.tencent.imsdk.v2.V2TIMConversationResult; import java.util.ArrayList; import java.util.List; import top.huic.tencent_im_plugin.util.BeanUtils; /** * 自定义会话结果实体 */ public class CustomConversationResultEntity { /** * 下一次分页拉取的游标 */ private Long nextSeq; /** * 会话列表是否已经拉取完毕 */ private Boolean finished; /** * 会话列表 */ private List conversationList; public CustomConversationResultEntity() { } public CustomConversationResultEntity(V2TIMConversationResult data) { BeanUtils.copyProperties(data, this, "conversationList"); if (data.getConversationList() != null) { List conversationList = new ArrayList<>(data.getConversationList().size()); for (V2TIMConversation item : data.getConversationList()) { conversationList.add(new CustomConversationEntity(item)); } this.conversationList = conversationList; } } public Long getNextSeq() { return nextSeq; } public void setNextSeq(Long nextSeq) { this.nextSeq = nextSeq; } public Boolean getFinished() { return finished; } public void setFinished(Boolean finished) { this.finished = finished; } public List getConversationList() { return conversationList; } public void setConversationList(List conversationList) { this.conversationList = conversationList; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/CustomFriendAddApplication.java ================================================ package top.huic.tencent_im_plugin.entity; import com.tencent.imsdk.v2.V2TIMFriendAddApplication; /** * 自定义好友添加申请实体 */ public class CustomFriendAddApplication extends V2TIMFriendAddApplication { public CustomFriendAddApplication() { super(null); } public CustomFriendAddApplication(String userID) { super(userID); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/CustomMessageEntity.java ================================================ package top.huic.tencent_im_plugin.entity; import com.tencent.imsdk.v2.V2TIMElem; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMOfflinePushInfo; import java.io.Serializable; import java.util.List; import top.huic.tencent_im_plugin.enums.MessageNodeType; import top.huic.tencent_im_plugin.message.AbstractMessageNode; import top.huic.tencent_im_plugin.message.entity.AbstractMessageEntity; import top.huic.tencent_im_plugin.util.BeanUtils; /** * 自定义消息实体 * * @author 蒋具宏 */ public class CustomMessageEntity implements Serializable { /** * 消息 ID */ private String msgID; /** * 消息时间戳 */ private Long timestamp; /** * 消息发送者 userID */ private String sender; /** * 消息发送者昵称 */ private String nickName; /** * 好友备注。如果没有拉取过好友信息或者不是好友,返回 null */ private String friendRemark; /** * 发送者头像 url */ private String faceUrl; /** * 群组消息,nameCard 为发送者的群名片 */ private String nameCard; /** * 群组消息,groupID 为接收消息的群组 ID,否则为 null */ private String groupID; /** * 单聊消息,userID 为会话用户 ID,否则为 null。 假设自己和 userA 聊天,无论是自己发给 userA 的消息还是 userA 发给自己的消息,这里的 userID 均为 userA */ private String userID; /** * 消息发送状态 */ private Integer status; /** * 消息类型 */ private Integer elemType; /** * 消息自定义数据(本地保存,不会发送到对端,程序卸载重装后失效) */ private String localCustomData; /** * 消息自定义数据(本地保存,不会发送到对端,程序卸载重装后失效) */ private Integer localCustomInt; /** * 消息发送者是否是自己 */ private Boolean self; /** * 消息自己是否已读 */ private Boolean read; /** * 消息对方是否已读(只有 C2C 消息有效) */ private Boolean peerRead; /** * 消息优先级 */ private Integer priority; /** * 消息的离线推送信息 */ private V2TIMOfflinePushInfo offlinePushInfo; /** * 群@用户列表 */ private List groupAtUserList; /** * 消息的序列号 * 群聊中的消息序列号云端生成,在群里是严格递增且唯一的。 单聊中的序列号是本地生成,不能保证严格递增且唯一。 */ private Long seq; /** * 描述信息 */ private String note; /** * 节点信息 */ private AbstractMessageEntity node; /** * 消息随机码 */ private long random; public CustomMessageEntity() { } public CustomMessageEntity(V2TIMMessage message) { BeanUtils.copyProperties(message, this); // 解析接口 MessageNodeType nodeType = MessageNodeType.getMessageNodeTypeByV2TIMConstant(this.elemType); if (nodeType != MessageNodeType.None) { AbstractMessageNode _node = nodeType.getMessageNodeInterface(); V2TIMElem elem = nodeType.getElemByMessage(message); this.note = _node.getNote(elem); this.node = _node.analysis(elem); } } public String getMsgID() { return msgID; } public void setMsgID(String msgID) { this.msgID = msgID; } public Long getTimestamp() { return timestamp; } public void setTimestamp(Long timestamp) { this.timestamp = timestamp; } public String getSender() { return sender; } public void setSender(String sender) { this.sender = sender; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public String getFriendRemark() { return friendRemark; } public void setFriendRemark(String friendRemark) { this.friendRemark = friendRemark; } public String getFaceUrl() { return faceUrl; } public void setFaceUrl(String faceUrl) { this.faceUrl = faceUrl; } public String getNameCard() { return nameCard; } public void setNameCard(String nameCard) { this.nameCard = nameCard; } public String getGroupID() { return groupID; } public void setGroupID(String groupID) { this.groupID = groupID; } public String getUserID() { return userID; } public void setUserID(String userID) { this.userID = userID; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public Integer getElemType() { return elemType; } public void setElemType(Integer elemType) { this.elemType = elemType; } public String getLocalCustomData() { return localCustomData; } public void setLocalCustomData(String localCustomData) { this.localCustomData = localCustomData; } public Integer getLocalCustomInt() { return localCustomInt; } public void setLocalCustomInt(Integer localCustomInt) { this.localCustomInt = localCustomInt; } public Boolean getSelf() { return self; } public void setSelf(Boolean self) { this.self = self; } public Boolean getRead() { return read; } public void setRead(Boolean read) { this.read = read; } public Boolean getPeerRead() { return peerRead; } public void setPeerRead(Boolean peerRead) { this.peerRead = peerRead; } public Integer getPriority() { return priority; } public void setPriority(Integer priority) { this.priority = priority; } public V2TIMOfflinePushInfo getOfflinePushInfo() { return offlinePushInfo; } public void setOfflinePushInfo(V2TIMOfflinePushInfo offlinePushInfo) { this.offlinePushInfo = offlinePushInfo; } public List getGroupAtUserList() { return groupAtUserList; } public void setGroupAtUserList(List groupAtUserList) { this.groupAtUserList = groupAtUserList; } public Long getSeq() { return seq; } public void setSeq(Long seq) { this.seq = seq; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } public AbstractMessageEntity getNode() { return node; } public void setNode(AbstractMessageEntity node) { this.node = node; } public long getRandom() { return random; } public void setRandom(long random) { this.random = random; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/FindFriendApplicationEntity.java ================================================ package top.huic.tencent_im_plugin.entity; /** * 查找好友申请实体 */ public class FindFriendApplicationEntity { /** * 用户ID */ String userID; /** * 类型 */ int type; public String getUserID() { return userID; } public void setUserID(String userID) { this.userID = userID; } public int getType() { return type; } public void setType(int type) { this.type = type; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/FindGroupApplicationEntity.java ================================================ package top.huic.tencent_im_plugin.entity; /** * 查找群申请实体 */ public class FindGroupApplicationEntity { /** * 来自用户 */ String fromUser; /** * 群ID */ String groupID; public String getFromUser() { return fromUser; } public void setFromUser(String fromUser) { this.fromUser = fromUser; } public String getGroupID() { return groupID; } public void setGroupID(String groupID) { this.groupID = groupID; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/entity/FindMessageEntity.java ================================================ package top.huic.tencent_im_plugin.entity; /** * 查找消息实体 */ public class FindMessageEntity { /** * 消息ID */ private String msgId; public FindMessageEntity() { } public FindMessageEntity(String msgId) { this.msgId = msgId; } public String getMsgId() { return msgId; } public void setMsgId(String msgId) { this.msgId = msgId; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/enums/ListenerTypeEnum.java ================================================ package top.huic.tencent_im_plugin.enums; /** * 监听器类型枚举 */ public enum ListenerTypeEnum { /** * 新消息通知 */ NewMessage, /** * C2C已读回执 */ C2CReadReceipt, /** * 消息撤回 */ MessageRevoked, /** * 同步服务开始 */ SyncServerStart, /** * 同步服务完成 */ SyncServerFinish, /** * 同步服务失败 */ SyncServerFailed, /** * 新会话 */ NewConversation, /** * 会话刷新 */ ConversationChanged, /** * 好友申请新增通知 */ FriendApplicationListAdded, /** * 好友申请删除通知 */ FriendApplicationListDeleted, /** * 好友申请已读通知 */ FriendApplicationListRead, /** * 好友新增通知 */ FriendListAdded, /** * 好友删除通知 */ FriendListDeleted, /** * 黑名单新增通知 */ BlackListAdd, /** * 黑名单删除通知 */ BlackListDeleted, /** * 好友资料更新通知 */ FriendInfoChanged, /** * 有用户加入群 */ MemberEnter, /** * 有用户离开群 */ MemberLeave, /** * 有用户被拉入群 */ MemberInvited, /** * 有用户被踢出群 */ MemberKicked, /** * 群成员信息被修改 */ MemberInfoChanged, /** * 创建群 */ GroupCreated, /** * 群被解散 */ GroupDismissed, /** * 群被回收 */ GroupRecycled, /** * 群信息被修改 */ GroupInfoChanged, /** * 有新的加群申请 */ ReceiveJoinApplication, /** * 加群信息已被管理员处理 */ ApplicationProcessed, /** * 指定管理员身份 */ GrantAdministrator, /** * 取消管理员身份 */ RevokeAdministrator, /** * 主动退出群组 */ QuitFromGroup, /** * 收到 RESTAPI 下发的自定义系统消息 */ ReceiveRESTCustomData, /** * 收到群属性更新的回调 */ GroupAttributeChanged, /** * 正在连接到腾讯云服务器 */ Connecting, /** * 网络连接成功 */ ConnectSuccess, /** * 网络连接失败 */ ConnectFailed, /** * 踢下线 */ KickedOffline, /** * 当前用户的资料发生了更新 */ SelfInfoUpdated, /** * 用户登录的 userSig 过期(用户需要重新获取 userSig 后登录) */ UserSigExpired, /** * 收到信令邀请 */ ReceiveNewInvitation, /** * 信令被邀请者接受邀请 */ InviteeAccepted, /** * 信令被邀请者拒绝邀请 */ InviteeRejected, /** * 信令邀请被取消 */ InvitationCancelled, /** * 信令邀请超时 */ InvitationTimeout, /** * 下载进度 */ DownloadProgress, /** * 消息发送成功 */ MessageSendSucc, /** * 消息发送失败 */ MessageSendFail, /** * 消息发送进度更新 */ MessageSendProgress, } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/enums/MessageNodeType.java ================================================ package top.huic.tencent_im_plugin.enums; import com.tencent.imsdk.v2.V2TIMElem; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.AbstractMessageNode; import top.huic.tencent_im_plugin.message.CustomMessageNode; import top.huic.tencent_im_plugin.message.FaceMessageNode; import top.huic.tencent_im_plugin.message.FileMessageNode; import top.huic.tencent_im_plugin.message.GroupTipsMessageNode; import top.huic.tencent_im_plugin.message.ImageMessageNode; import top.huic.tencent_im_plugin.message.LocationMessageNode; import top.huic.tencent_im_plugin.message.SoundMessageNode; import top.huic.tencent_im_plugin.message.TextMessageNode; import top.huic.tencent_im_plugin.message.VideoMessageNode; /** * 消息节点类型 * * @author 蒋具宏 */ public enum MessageNodeType { /** * 没有元素 */ None(null) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return null; } }, /** * 文本 */ Text(new TextMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getTextElem(); } }, /** * 自定义 */ Custom(new CustomMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getCustomElem(); } }, /** * 图片 */ Image(new ImageMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getImageElem(); } }, /** * 语音 */ Sound(new SoundMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getSoundElem(); } }, /** * 视频 */ Video(new VideoMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getVideoElem(); } }, /** * 文件 */ File(new FileMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getFileElem(); } }, /** * 位置 */ Location(new LocationMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getLocationElem(); } }, /** * 表情 */ Face(new FaceMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getFaceElem(); } }, /** * 群提示 */ GroupTips(new GroupTipsMessageNode()) { @Override public V2TIMElem getElemByMessage(V2TIMMessage message) { return message.getGroupTipsElem(); } }; /** * 消息节点接口 * 通过枚举的方法反向绑定接口,和业务强关联 */ private AbstractMessageNode messageNodeInterface; MessageNodeType(AbstractMessageNode messageNodeInterface) { this.messageNodeInterface = messageNodeInterface; } /** * 获得消息节点接口 */ public AbstractMessageNode getMessageNodeInterface() { return messageNodeInterface; } /** * 根据Message获得节点信息 * * @param message 消息对象 * @return 节点对象 */ public abstract V2TIMElem getElemByMessage(V2TIMMessage message); /** * 根据TIM V2版本的常量进行获取 * * @param constant 常量值 * @return 结果 */ public static MessageNodeType getMessageNodeTypeByV2TIMConstant(int constant) { return MessageNodeType.values()[constant]; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/listener/CustomAdvancedMsgListener.java ================================================ package top.huic.tencent_im_plugin.listener; import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMMessageReceipt; import java.util.List; import top.huic.tencent_im_plugin.TencentImPlugin; import top.huic.tencent_im_plugin.entity.CustomMessageEntity; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * 消息相关监听器 */ public class CustomAdvancedMsgListener extends V2TIMAdvancedMsgListener { /** * 新消息通知 */ @Override public void onRecvNewMessage(V2TIMMessage msg) { super.onRecvNewMessage(msg); TencentImPlugin.invokeListener(ListenerTypeEnum.NewMessage, new CustomMessageEntity(msg)); } /** * C2C已读回执 */ @Override public void onRecvC2CReadReceipt(List receiptList) { super.onRecvC2CReadReceipt(receiptList); TencentImPlugin.invokeListener(ListenerTypeEnum.C2CReadReceipt, receiptList); } /** * 消息撤回 */ @Override public void onRecvMessageRevoked(String msgID) { super.onRecvMessageRevoked(msgID); TencentImPlugin.invokeListener(ListenerTypeEnum.MessageRevoked, msgID); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/listener/CustomConversationListener.java ================================================ package top.huic.tencent_im_plugin.listener; import com.tencent.imsdk.v2.V2TIMConversation; import com.tencent.imsdk.v2.V2TIMConversationListener; import java.util.ArrayList; import java.util.List; import top.huic.tencent_im_plugin.TencentImPlugin; import top.huic.tencent_im_plugin.entity.CustomConversationEntity; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * 自定义会话监听 */ public class CustomConversationListener extends V2TIMConversationListener { /** * 同步服务开始 */ @Override public void onSyncServerStart() { super.onSyncServerStart(); TencentImPlugin.invokeListener(ListenerTypeEnum.SyncServerStart, null); } /** * 同步服务完成 */ @Override public void onSyncServerFinish() { super.onSyncServerFinish(); TencentImPlugin.invokeListener(ListenerTypeEnum.SyncServerFinish, null); } /** * 同步服务失败 */ @Override public void onSyncServerFailed() { super.onSyncServerFailed(); TencentImPlugin.invokeListener(ListenerTypeEnum.SyncServerFailed, null); } /** * 新会话 */ @Override public void onNewConversation(List conversationList) { super.onNewConversation(conversationList); List data = new ArrayList<>(conversationList.size()); for (V2TIMConversation v2TIMConversation : conversationList) { data.add(new CustomConversationEntity(v2TIMConversation)); } TencentImPlugin.invokeListener(ListenerTypeEnum.NewConversation, data); } /** * 会话刷新 */ @Override public void onConversationChanged(List conversationList) { super.onConversationChanged(conversationList); List data = new ArrayList<>(conversationList.size()); for (V2TIMConversation v2TIMConversation : conversationList) { data.add(new CustomConversationEntity(v2TIMConversation)); } TencentImPlugin.invokeListener(ListenerTypeEnum.ConversationChanged, data); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/listener/CustomFriendshipListener.java ================================================ package top.huic.tencent_im_plugin.listener; import com.tencent.imsdk.v2.V2TIMFriendApplication; import com.tencent.imsdk.v2.V2TIMFriendInfo; import com.tencent.imsdk.v2.V2TIMFriendshipListener; import java.util.List; import top.huic.tencent_im_plugin.TencentImPlugin; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * 自定义关系链监听器 */ public class CustomFriendshipListener extends V2TIMFriendshipListener { /** * 好友申请新增通知,两种情况会收到这个回调: *

* 自己申请加别人好友 * 别人申请加自己好友 */ @Override public void onFriendApplicationListAdded(List applicationList) { super.onFriendApplicationListAdded(applicationList); TencentImPlugin.invokeListener(ListenerTypeEnum.FriendApplicationListAdded, applicationList); } /** * 好友申请删除通知,四种情况会收到这个回调 *

* 调用 deleteFriendApplication 主动删除好友申请 * 调用 refuseFriendApplication 拒绝好友申请 * 调用 acceptFriendApplication 同意好友申请且同意类型为 V2TIM_FRIEND_ACCEPT_AGREE 时 * 申请加别人好友被拒绝 */ @Override public void onFriendApplicationListDeleted(List userIDList) { super.onFriendApplicationListDeleted(userIDList); TencentImPlugin.invokeListener(ListenerTypeEnum.FriendApplicationListDeleted, userIDList); } /** * 好友申请已读通知,如果调用 setFriendApplicationRead 设置好友申请列表已读,会收到这个回调(主要用于多端同步) */ @Override public void onFriendApplicationListRead() { super.onFriendApplicationListRead(); TencentImPlugin.invokeListener(ListenerTypeEnum.FriendApplicationListRead, null); } /** * 好友新增通知 */ @Override public void onFriendListAdded(List users) { super.onFriendListAdded(users); TencentImPlugin.invokeListener(ListenerTypeEnum.FriendListAdded, users); } /** * 好友删除通知,,两种情况会收到这个回调: *

* 自己删除好友(单向和双向删除都会收到回调) * 好友把自己删除(双向删除会收到) */ @Override public void onFriendListDeleted(List userList) { super.onFriendListDeleted(userList); TencentImPlugin.invokeListener(ListenerTypeEnum.FriendListDeleted, userList); } /** * 黑名单新增通知 */ @Override public void onBlackListAdd(List infoList) { super.onBlackListAdd(infoList); TencentImPlugin.invokeListener(ListenerTypeEnum.BlackListAdd, infoList); } /** * 黑名单删除通知 */ @Override public void onBlackListDeleted(List userList) { super.onBlackListDeleted(userList); TencentImPlugin.invokeListener(ListenerTypeEnum.BlackListDeleted, userList); } /** * 好友资料更新通知 */ @Override public void onFriendInfoChanged(List infoList) { super.onFriendInfoChanged(infoList); TencentImPlugin.invokeListener(ListenerTypeEnum.FriendInfoChanged, infoList); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/listener/CustomGroupListener.java ================================================ package top.huic.tencent_im_plugin.listener; import com.tencent.imsdk.v2.V2TIMGroupChangeInfo; import com.tencent.imsdk.v2.V2TIMGroupListener; import com.tencent.imsdk.v2.V2TIMGroupMemberChangeInfo; import com.tencent.imsdk.v2.V2TIMGroupMemberInfo; import java.util.HashMap; import java.util.List; import java.util.Map; import top.huic.tencent_im_plugin.TencentImPlugin; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * 自定义群监听 */ public class CustomGroupListener extends V2TIMGroupListener { /** * 有用户加入群(全员能够收到) */ @Override public void onMemberEnter(final String groupID, final List memberList) { super.onMemberEnter(groupID, memberList); TencentImPlugin.invokeListener(ListenerTypeEnum.MemberEnter, new HashMap() { { put("groupID", groupID); put("memberList", memberList); } }); } /** * 有用户离开群(全员能够收到) */ @Override public void onMemberLeave(final String groupID, final V2TIMGroupMemberInfo member) { super.onMemberLeave(groupID, member); TencentImPlugin.invokeListener(ListenerTypeEnum.MemberLeave, new HashMap() { { put("groupID", groupID); put("member", member); } }); } /** * 某些人被拉入某群(全员能够收到) */ @Override public void onMemberInvited(final String groupID, final V2TIMGroupMemberInfo opUser, final List memberList) { super.onMemberInvited(groupID, opUser, memberList); TencentImPlugin.invokeListener(ListenerTypeEnum.MemberInvited, new HashMap() { { put("groupID", groupID); put("opUser", opUser); put("memberList", memberList); } }); } /** * 某些人被踢出某群(全员能够收到) */ @Override public void onMemberKicked(final String groupID, final V2TIMGroupMemberInfo opUser, final List memberList) { super.onMemberKicked(groupID, opUser, memberList); TencentImPlugin.invokeListener(ListenerTypeEnum.MemberKicked, new HashMap() { { put("groupID", groupID); put("opUser", opUser); put("memberList", memberList); } }); } /** * 群成员信息被修改(全员能收到) */ @Override public void onMemberInfoChanged(final String groupID, final List v2TIMGroupMemberChangeInfoList) { super.onMemberInfoChanged(groupID, v2TIMGroupMemberChangeInfoList); TencentImPlugin.invokeListener(ListenerTypeEnum.MemberInfoChanged, new HashMap() { { put("groupID", groupID); put("changInfo", v2TIMGroupMemberChangeInfoList); } }); } /** * 创建群(主要用于多端同步) */ @Override public void onGroupCreated(String groupID) { super.onGroupCreated(groupID); TencentImPlugin.invokeListener(ListenerTypeEnum.GroupCreated, groupID); } /** * 群被解散了(全员能收到) */ @Override public void onGroupDismissed(final String groupID, final V2TIMGroupMemberInfo opUser) { super.onGroupDismissed(groupID, opUser); TencentImPlugin.invokeListener(ListenerTypeEnum.GroupDismissed, new HashMap() { { put("groupID", groupID); put("opUser", opUser); } }); } /** * 群被回收(全员能收到) */ @Override public void onGroupRecycled(final String groupID, final V2TIMGroupMemberInfo opUser) { super.onGroupRecycled(groupID, opUser); TencentImPlugin.invokeListener(ListenerTypeEnum.GroupRecycled, new HashMap() { { put("groupID", groupID); put("opUser", opUser); } }); } /** * 群信息被修改(全员能收到) */ @Override public void onGroupInfoChanged(final String groupID, final List changeInfos) { super.onGroupInfoChanged(groupID, changeInfos); TencentImPlugin.invokeListener(ListenerTypeEnum.GroupInfoChanged, new HashMap() { { put("groupID", groupID); put("changInfo", changeInfos); } }); } /** * 有新的加群请求(只有群主或管理员会收到) */ @Override public void onReceiveJoinApplication(final String groupID, final V2TIMGroupMemberInfo member, final String opReason) { super.onReceiveJoinApplication(groupID, member, opReason); TencentImPlugin.invokeListener(ListenerTypeEnum.ReceiveJoinApplication, new HashMap() { { put("groupID", groupID); put("member", member); put("opReason", opReason); } }); } /** * 加群请求已经被群主或管理员处理了(只有申请人能够收到) */ @Override public void onApplicationProcessed(final String groupID, final V2TIMGroupMemberInfo opUser, final boolean isAgreeJoin, final String opReason) { super.onApplicationProcessed(groupID, opUser, isAgreeJoin, opReason); TencentImPlugin.invokeListener(ListenerTypeEnum.ApplicationProcessed, new HashMap() { { put("groupID", groupID); put("opUser", opUser); put("isAgreeJoin", isAgreeJoin); put("opReason", opReason); } }); } /** * 指定管理员身份 */ @Override public void onGrantAdministrator(final String groupID, final V2TIMGroupMemberInfo opUser, final List memberList) { super.onGrantAdministrator(groupID, opUser, memberList); TencentImPlugin.invokeListener(ListenerTypeEnum.GrantAdministrator, new HashMap() { { put("groupID", groupID); put("opUser", opUser); put("memberList", memberList); } }); } /** * 取消管理员身份 */ @Override public void onRevokeAdministrator(final String groupID, final V2TIMGroupMemberInfo opUser, final List memberList) { super.onRevokeAdministrator(groupID, opUser, memberList); TencentImPlugin.invokeListener(ListenerTypeEnum.RevokeAdministrator, new HashMap() { { put("groupID", groupID); put("opUser", opUser); put("memberList", memberList); } }); } /** * 主动退出群组(主要用于多端同步,直播群(AVChatRoom)不支持) */ @Override public void onQuitFromGroup(String groupID) { super.onQuitFromGroup(groupID); TencentImPlugin.invokeListener(ListenerTypeEnum.QuitFromGroup, groupID); } /** * 收到 RESTAPI 下发的自定义系统消息 */ @Override public void onReceiveRESTCustomData(final String groupID, final byte[] customData) { super.onReceiveRESTCustomData(groupID, customData); TencentImPlugin.invokeListener(ListenerTypeEnum.ReceiveRESTCustomData, new HashMap() { { put("groupID", groupID); put("customData", new String(customData)); } }); } /** * 收到群属性更新的回调 */ @Override public void onGroupAttributeChanged(final String groupID, final Map groupAttributeMap) { super.onGroupAttributeChanged(groupID, groupAttributeMap); TencentImPlugin.invokeListener(ListenerTypeEnum.GroupAttributeChanged, new HashMap() { { put("groupID", groupID); put("attributes", groupAttributeMap); } }); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/listener/CustomSDKListener.java ================================================ package top.huic.tencent_im_plugin.listener; import com.tencent.imsdk.v2.V2TIMSDKListener; import com.tencent.imsdk.v2.V2TIMUserFullInfo; import java.util.HashMap; import top.huic.tencent_im_plugin.TencentImPlugin; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * SDK基本监听器 */ public class CustomSDKListener extends V2TIMSDKListener { /** * 正在连接到腾讯云服务器 */ @Override public void onConnecting() { super.onConnecting(); TencentImPlugin.invokeListener(ListenerTypeEnum.Connecting, null); } /** * 网络连接成功 */ @Override public void onConnectSuccess() { super.onConnectSuccess(); TencentImPlugin.invokeListener(ListenerTypeEnum.ConnectSuccess, null); } /** * 网络连接失败 */ @Override public void onConnectFailed(final int code, final String error) { super.onConnectFailed(code, error); TencentImPlugin.invokeListener(ListenerTypeEnum.ConnectFailed, new HashMap() { { put("code", code); put("error", error); } }); } /** * 踢下线通知 */ @Override public void onKickedOffline() { super.onKickedOffline(); TencentImPlugin.invokeListener(ListenerTypeEnum.KickedOffline, null); } /** * 当前用户的资料发生了更新 */ @Override public void onSelfInfoUpdated(V2TIMUserFullInfo info) { super.onSelfInfoUpdated(info); TencentImPlugin.invokeListener(ListenerTypeEnum.SelfInfoUpdated, info); } /** * 用户登录的 userSig 过期(用户需要重新获取 userSig 后登录) */ @Override public void onUserSigExpired() { super.onUserSigExpired(); TencentImPlugin.invokeListener(ListenerTypeEnum.UserSigExpired, null); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/listener/CustomSignalingListener.java ================================================ package top.huic.tencent_im_plugin.listener; import com.tencent.imsdk.v2.V2TIMSignalingListener; import java.util.HashMap; import java.util.List; import top.huic.tencent_im_plugin.TencentImPlugin; import top.huic.tencent_im_plugin.enums.ListenerTypeEnum; /** * 自定义信令监听器 */ public class CustomSignalingListener extends V2TIMSignalingListener { /** * 收到新邀请时 */ @Override public void onReceiveNewInvitation(final String inviteID, final String inviter, final String groupID, final List inviteeList, final String data) { super.onReceiveNewInvitation(inviteID, inviter, groupID, inviteeList, data); TencentImPlugin.invokeListener(ListenerTypeEnum.ReceiveNewInvitation, new HashMap() { { put("inviteID", inviteID); put("inviter", inviter); put("groupID", groupID); put("inviteeList", inviteeList); put("data", data); } }); } /** * 被邀请者接受邀请 */ @Override public void onInviteeAccepted(final String inviteID, final String invitee, final String data) { super.onInviteeAccepted(inviteID, invitee, data); TencentImPlugin.invokeListener(ListenerTypeEnum.InviteeAccepted, new HashMap() { { put("inviteID", inviteID); put("invitee", invitee); put("data", data); } }); } /** * 被邀请者拒绝邀请 */ @Override public void onInviteeRejected(final String inviteID, final String invitee, final String data) { super.onInviteeRejected(inviteID, invitee, data); TencentImPlugin.invokeListener(ListenerTypeEnum.InviteeRejected, new HashMap() { { put("inviteID", inviteID); put("invitee", invitee); put("data", data); } }); } /** * 邀请被取消 */ @Override public void onInvitationCancelled(final String inviteID, final String inviter, final String data) { super.onInvitationCancelled(inviteID, inviter, data); TencentImPlugin.invokeListener(ListenerTypeEnum.InvitationCancelled, new HashMap() { { put("inviteID", inviteID); put("inviter", inviter); put("data", data); } }); } /** * 邀请超时 */ @Override public void onInvitationTimeout(final String inviteID, final List inviteeList) { super.onInvitationTimeout(inviteID, inviteeList); TencentImPlugin.invokeListener(ListenerTypeEnum.InvitationTimeout, new HashMap() { { put("inviteID", inviteID); put("inviteeList", inviteeList); } }); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/AbstractMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.entity.AbstractMessageEntity; /** * 消息节点接口 * * @param 节点类型,对应腾讯云 TIMElem */ public abstract class AbstractMessageNode { /** * 获得发送的消息体 * * @param entity 消息实体 * @return 结果 */ public V2TIMMessage getV2TIMMessage(E entity) { throw new RuntimeException("This node does not support sending"); } /** * 根据消息节点获得描述 * * @param elem 节点 */ public abstract String getNote(N elem); /** * 将节点解析为实体对象 * * @param elem 节点 * @return 实体对象 */ public abstract E analysis(N elem); /** * 获得实体类型 * * @return 类型 */ public abstract Class getEntityClass(); } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/CustomMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMCustomElem; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.entity.CustomMessageEntity; /** * 自定义消息节点 */ public class CustomMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(CustomMessageEntity entity) { return V2TIMManager.getMessageManager().createCustomMessage(entity.getData().getBytes(), entity.getDesc(), entity.getExt() == null ? null : entity.getExt().getBytes()); } @Override public String getNote(V2TIMCustomElem elem) { return "[其它消息]"; } @Override public CustomMessageEntity analysis(V2TIMCustomElem elem) { return new CustomMessageEntity(elem); } @Override public Class getEntityClass() { return CustomMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/FaceMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMFaceElem; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.entity.FaceMessageEntity; /** * 表情消息节点 */ public class FaceMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(FaceMessageEntity entity) { return V2TIMManager.getMessageManager().createFaceMessage(entity.getIndex(), entity.getData().getBytes()); } @Override public String getNote(V2TIMFaceElem elem) { return "[表情]"; } @Override public FaceMessageEntity analysis(V2TIMFaceElem elem) { return new FaceMessageEntity(elem); } @Override public Class getEntityClass() { return FaceMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/FileMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMFileElem; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.entity.FileMessageEntity; /** * 文件消息节点 */ public class FileMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(FileMessageEntity entity) { return V2TIMManager.getMessageManager().createFileMessage(entity.getFilePath(), entity.getFileName()); } @Override public String getNote(V2TIMFileElem elem) { return "[文件]"; } @Override public FileMessageEntity analysis(V2TIMFileElem elem) { return new FileMessageEntity(elem); } @Override public Class getEntityClass() { return FileMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/GroupTipsMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMGroupTipsElem; import top.huic.tencent_im_plugin.message.entity.GroupTipsMessageEntity; /** * 群提示消息节点 */ public class GroupTipsMessageNode extends AbstractMessageNode { @Override public String getNote(V2TIMGroupTipsElem elem) { return "[群提示]"; } @Override public GroupTipsMessageEntity analysis(V2TIMGroupTipsElem elem) { return new GroupTipsMessageEntity(elem); } @Override public Class getEntityClass() { return GroupTipsMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/ImageMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMImageElem; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.entity.ImageMessageEntity; /** * 图片消息节点 */ public class ImageMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(ImageMessageEntity entity) { return V2TIMManager.getMessageManager().createImageMessage(entity.getPath()); } @Override public String getNote(V2TIMImageElem elem) { return "[图片]"; } @Override public ImageMessageEntity analysis(V2TIMImageElem elem) { ImageMessageEntity entity = new ImageMessageEntity(); entity.setPath(elem.getPath()); entity.setImageData(elem.getImageList()); return entity; } @Override public Class getEntityClass() { return ImageMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/LocationMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMLocationElem; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import top.huic.tencent_im_plugin.message.entity.LocationMessageEntity; /** * 位置消息节点 */ public class LocationMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(LocationMessageEntity entity) { return V2TIMManager.getMessageManager().createLocationMessage(entity.getDesc(), entity.getLongitude(), entity.getLatitude()); } @Override public String getNote(V2TIMLocationElem elem) { return "[位置消息]"; } @Override public LocationMessageEntity analysis(V2TIMLocationElem elem) { return new LocationMessageEntity(elem); } @Override public Class getEntityClass() { return LocationMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/SoundMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMSoundElem; import top.huic.tencent_im_plugin.message.entity.SoundMessageEntity; /** * 语音消息节点 */ public class SoundMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(SoundMessageEntity entity) { return V2TIMManager.getMessageManager().createSoundMessage(entity.getPath(), entity.getDuration()); } @Override public String getNote(V2TIMSoundElem elem) { return "[语音]"; } @Override public SoundMessageEntity analysis(V2TIMSoundElem elem) { return new SoundMessageEntity(elem); } @Override public Class getEntityClass() { return SoundMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/TextMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMGroupAtInfo; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMTextElem; import java.util.ArrayList; import java.util.List; import top.huic.tencent_im_plugin.message.entity.TextMessageEntity; /** * 文本消息节点 */ public class TextMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(TextMessageEntity entity) { // 有@用户或者@所有人则进入分支 if ((entity.getAtUserList() != null && entity.getAtUserList().size() >= 1) || (entity.getAtAll() != null && entity.getAtAll())) { List atList = new ArrayList<>(); // @所有人 if (entity.getAtAll() != null && entity.getAtAll()) { atList.add(V2TIMGroupAtInfo.AT_ALL_TAG); } // @目标用户 if (entity.getAtUserList() != null) { atList.addAll(entity.getAtUserList()); } return V2TIMManager.getMessageManager().createTextAtMessage(entity.getContent(), atList); } return V2TIMManager.getMessageManager().createTextMessage(entity.getContent()); } @Override public String getNote(V2TIMTextElem elem) { return elem.getText(); } @Override public TextMessageEntity analysis(V2TIMTextElem elem) { return new TextMessageEntity(elem); } @Override public Class getEntityClass() { return TextMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/VideoMessageNode.java ================================================ package top.huic.tencent_im_plugin.message; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMVideoElem; import top.huic.tencent_im_plugin.message.entity.VideoMessageEntity; /** * 视频消息节点 */ public class VideoMessageNode extends AbstractMessageNode { @Override public V2TIMMessage getV2TIMMessage(VideoMessageEntity entity) { String suffix = null; if (entity.getVideoPath().contains(".")) { String[] ss = entity.getVideoPath().split("\\."); suffix = ss[ss.length - 1]; } return V2TIMManager.getMessageManager().createVideoMessage(entity.getVideoPath(), suffix, entity.getDuration(), entity.getSnapshotPath()); } @Override public String getNote(V2TIMVideoElem elem) { return "[视频]"; } @Override public VideoMessageEntity analysis(V2TIMVideoElem elem) { return new VideoMessageEntity(elem); } @Override public Class getEntityClass() { return VideoMessageEntity.class; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/AbstractMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import java.io.Serializable; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 消息实体 * * @author 蒋具宏 */ public class AbstractMessageEntity implements Serializable { private MessageNodeType nodeType; public AbstractMessageEntity(MessageNodeType nodeType) { this.nodeType = nodeType; } public MessageNodeType getNodeType() { return nodeType; } public void setNodeType(MessageNodeType nodeType) { this.nodeType = nodeType; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/CustomMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMCustomElem; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 自定义消息实体 * * @author 蒋具宏 */ public class CustomMessageEntity extends AbstractMessageEntity { /** * 自定义内容 */ private String data; /** * 描述 */ private String desc; /** * 扩展内容 */ private String ext; public CustomMessageEntity() { super(MessageNodeType.Custom); } public CustomMessageEntity(V2TIMCustomElem elem) { super(MessageNodeType.Custom); if (elem.getData() == null || elem.getData().length == 0) { this.data = null; } else { this.data = new String(elem.getData()); } this.desc = elem.getDescription(); if (elem.getExtension() != null && elem.getExtension().length != 0) { this.ext = new String(elem.getExtension()); } } public String getData() { return data; } public void setData(String data) { this.data = data; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getExt() { return ext; } public void setExt(String ext) { this.ext = ext; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/FaceMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMFaceElem; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 表情消息实体 */ public class FaceMessageEntity extends AbstractMessageEntity { /** * 索引 */ private int index; /** * 数据 */ private String data; public FaceMessageEntity() { super(MessageNodeType.Face); } public FaceMessageEntity(V2TIMFaceElem elem) { super(MessageNodeType.Face); this.setIndex(elem.getIndex()); this.setData(elem.getData() == null ? null : new String(elem.getData())); } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public String getData() { return data; } public void setData(String data) { this.data = data; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/FileMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMFileElem; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 文件消息实体 */ public class FileMessageEntity extends AbstractMessageEntity { /** * 文件路径 */ private String filePath; /** * 文件名 */ private String fileName; /** * 文件UUID */ private String uuid; /** * 文件大小 */ private int size; public FileMessageEntity() { super(MessageNodeType.File); } public FileMessageEntity(V2TIMFileElem elem) { super(MessageNodeType.File); this.setFileName(elem.getFileName()); this.setFilePath(elem.getPath()); this.setSize(elem.getFileSize()); this.setUuid(elem.getUUID()); } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/GroupTipsMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMGroupChangeInfo; import com.tencent.imsdk.v2.V2TIMGroupMemberChangeInfo; import com.tencent.imsdk.v2.V2TIMGroupMemberInfo; import com.tencent.imsdk.v2.V2TIMGroupTipsElem; import java.util.List; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 群提示消息实体 * * @author 蒋具宏 */ public class GroupTipsMessageEntity extends AbstractMessageEntity { /** * 群ID */ private String groupID; /** * 群事件通知类型 */ private int type; /** * 操作用户 */ private V2TIMGroupMemberInfo opMember; /** * 被操作人列表 */ private List memberList; /** * 群资料变更信息列表,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE时有效 */ private List groupChangeInfoList ; /** * 获取群成员变更信息列表,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE时有效 */ private List memberChangeInfoList; /** * 当前群成员数,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_JOIN, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_QUIT, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_KICKED的时候有效 */ private int memberCount; public GroupTipsMessageEntity() { super(MessageNodeType.GroupTips); } public GroupTipsMessageEntity(V2TIMGroupTipsElem elem){ super(MessageNodeType.GroupTips); this.groupID = elem.getGroupID(); this.type = elem.getType(); this.opMember = elem.getOpMember(); this.memberList = elem.getMemberList(); this.groupChangeInfoList = elem.getGroupChangeInfoList(); this.memberChangeInfoList = elem.getMemberChangeInfoList(); this.memberCount = elem.getMemberCount(); } public String getGroupID() { return groupID; } public void setGroupID(String groupID) { this.groupID = groupID; } public int getType() { return type; } public void setType(int type) { this.type = type; } public V2TIMGroupMemberInfo getOpMember() { return opMember; } public void setOpMember(V2TIMGroupMemberInfo opMember) { this.opMember = opMember; } public List getMemberList() { return memberList; } public void setMemberList(List memberList) { this.memberList = memberList; } public List getGroupChangeInfoList() { return groupChangeInfoList; } public void setGroupChangeInfoList(List groupChangeInfoList) { this.groupChangeInfoList = groupChangeInfoList; } public List getMemberChangeInfoList() { return memberChangeInfoList; } public void setMemberChangeInfoList(List memberChangeInfoList) { this.memberChangeInfoList = memberChangeInfoList; } public int getMemberCount() { return memberCount; } public void setMemberCount(int memberCount) { this.memberCount = memberCount; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/ImageMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMImageElem; import java.util.List; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 图片消息实体 * * @author 蒋具宏 */ public class ImageMessageEntity extends AbstractMessageEntity { /** * 原图本地文件路径,发送方有效 */ private String path; /** * 图片列表,根据类型分开 */ private List imageData; public ImageMessageEntity() { super(MessageNodeType.Image); } public ImageMessageEntity(V2TIMImageElem elem) { super(MessageNodeType.Image); this.setPath(elem.getPath()); this.setImageData(elem.getImageList()); } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public List getImageData() { return imageData; } public void setImageData(List imageData) { this.imageData = imageData; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/LocationMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMLocationElem; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 位置消息实体 * * @author 蒋具宏 */ public class LocationMessageEntity extends AbstractMessageEntity { /** * 描述 */ private String desc; /** * 经度 */ private double latitude; /** * 纬度 */ private double longitude; public LocationMessageEntity() { super(MessageNodeType.Location); } public LocationMessageEntity(V2TIMLocationElem elem) { super(MessageNodeType.Location); this.setDesc(elem.getDesc()); this.setLongitude(elem.getLongitude()); this.setLatitude(elem.getLatitude()); } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public double getLatitude() { return latitude; } public void setLatitude(double latitude) { this.latitude = latitude; } public double getLongitude() { return longitude; } public void setLongitude(double longitude) { this.longitude = longitude; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/SoundMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMSoundElem; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 语音消息实体 * * @author 蒋具宏 */ public class SoundMessageEntity extends AbstractMessageEntity { /** * 语音ID */ private String uuid; /** * 路径 */ private String path; /** * 时长 */ private Integer duration; /** * 数据大小 */ private Integer dataSize; public SoundMessageEntity() { super(MessageNodeType.Sound); } public SoundMessageEntity(V2TIMSoundElem elem) { super(MessageNodeType.Sound); this.setPath(elem.getPath()); this.setDuration(elem.getDuration()); this.setDataSize(elem.getDataSize()); this.setUuid(elem.getUUID()); } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Integer getDuration() { return duration; } public void setDuration(Integer duration) { this.duration = duration; } public Integer getDataSize() { return dataSize; } public void setDataSize(Integer dataSize) { this.dataSize = dataSize; } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/TextMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMTextElem; import java.util.List; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 文本消息实体 * * @author 蒋具宏 */ public class TextMessageEntity extends AbstractMessageEntity { /** * 消息内容 */ private String content; /** * \@的用户列表 */ private List atUserList; /** * 是否@所有人 */ private Boolean atAll; public TextMessageEntity() { super(MessageNodeType.Text); } public TextMessageEntity(V2TIMTextElem elem) { super(MessageNodeType.Text); this.content = elem.getText(); } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public List getAtUserList() { return atUserList; } public void setAtUserList(List atUserList) { this.atUserList = atUserList; } public Boolean getAtAll() { return atAll; } public void setAtAll(Boolean atAll) { this.atAll = atAll; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/message/entity/VideoMessageEntity.java ================================================ package top.huic.tencent_im_plugin.message.entity; import com.tencent.imsdk.v2.V2TIMVideoElem; import java.io.Serializable; import top.huic.tencent_im_plugin.enums.MessageNodeType; /** * 视频消息实体 * * @author 蒋具宏 */ public class VideoMessageEntity extends AbstractMessageEntity implements Serializable { /** * 视频路径 */ private String videoPath; /** * 视频UUID */ private String videoUuid; /** * 视频大小 */ private int videoSize; /** * 时长 */ private int duration; /** * 缩略图路径 */ private String snapshotPath; /** * 缩略图UUID */ private String snapshotUuid; /** * 缩略图大小 */ private int snapshotSize; /** * 缩略图宽度 */ private int snapshotWidth; /** * 缩略图高度 */ private int snapshotHeight; public VideoMessageEntity() { super(MessageNodeType.Video); } public VideoMessageEntity(V2TIMVideoElem elem) { super(MessageNodeType.Video); this.setVideoUuid(elem.getVideoUUID()); this.setVideoPath(elem.getVideoPath()); this.setVideoSize(elem.getVideoSize()); this.setDuration(elem.getDuration()); this.setSnapshotUuid(elem.getSnapshotUUID()); this.setSnapshotWidth(elem.getSnapshotWidth()); this.setSnapshotHeight(elem.getSnapshotHeight()); this.setSnapshotPath(elem.getSnapshotPath()); this.setSnapshotSize(elem.getSnapshotSize()); } public String getVideoPath() { return videoPath; } public void setVideoPath(String videoPath) { this.videoPath = videoPath; } public String getVideoUuid() { return videoUuid; } public void setVideoUuid(String videoUuid) { this.videoUuid = videoUuid; } public int getVideoSize() { return videoSize; } public void setVideoSize(int videoSize) { this.videoSize = videoSize; } public int getDuration() { return duration; } public void setDuration(int duration) { this.duration = duration; } public String getSnapshotPath() { return snapshotPath; } public void setSnapshotPath(String snapshotPath) { this.snapshotPath = snapshotPath; } public String getSnapshotUuid() { return snapshotUuid; } public void setSnapshotUuid(String snapshotUuid) { this.snapshotUuid = snapshotUuid; } public int getSnapshotSize() { return snapshotSize; } public void setSnapshotSize(int snapshotSize) { this.snapshotSize = snapshotSize; } public int getSnapshotWidth() { return snapshotWidth; } public void setSnapshotWidth(int snapshotWidth) { this.snapshotWidth = snapshotWidth; } public int getSnapshotHeight() { return snapshotHeight; } public void setSnapshotHeight(int snapshotHeight) { this.snapshotHeight = snapshotHeight; } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/util/BeanUtils.java ================================================ package top.huic.tencent_im_plugin.util; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * Bean工具类 */ public class BeanUtils { /** * 复制属性 * * @param source 源对象 * @param target 目标对象 * @param ignoreProperties 忽略的参数列表 */ public static void copyProperties(Object source, Object target, String... ignoreProperties) { Class sourceClass = source.getClass(); Class targetClass = target.getClass(); // 填充目标方法列表 Map targetMethodMap = new HashMap<>(); for (Method method : targetClass.getDeclaredMethods()) { targetMethodMap.put(method.getName(), method); } try { for (Method method : sourceClass.getDeclaredMethods()) { String name = method.getName(); // 验证是否是属性方法(get / is) if (method.getReturnType() != Void.class || method.getParameterTypes().length >= 1 || !(name.startsWith("get") || name.startsWith("is"))) { // 获得方法后缀名(不包含 get is 前缀的内容) String methodSuffixName = name.replaceFirst(name.startsWith("get") ? "get" : "is", ""); if (methodSuffixName.length() == 0) { continue; } // 获得真实属性名 String fieldName = methodSuffixName.substring(0, 1).toLowerCase() + methodSuffixName.substring(1); // 如果是忽略的属性 if (ignoreProperties != null && Arrays.asList(ignoreProperties).contains(fieldName)) { continue; } // 如果不存在设置方法 String setMethodName = "set" + methodSuffixName; if (!targetMethodMap.containsKey(setMethodName)) { continue; } // 方法校验(非普通set参数(1个参数)) 或 不是公开方法,则不进行赋值确认 Method targetMethod = targetMethodMap.get(setMethodName); if (targetMethod.getParameterTypes().length != 1 || targetMethod.getModifiers() != Modifier.PUBLIC) { continue; } // 获得值,如果为null则忽略 Object resultValue = method.invoke(source); if (resultValue == null) { continue; } // 赋值 targetMethod.invoke(target, resultValue); } } } catch (Exception e) { throw new RuntimeException(e); } } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/util/CommonUtil.java ================================================ package top.huic.tencent_im_plugin.util; import android.os.Handler; import android.os.Looper; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; /** * 工具类 */ public class CommonUtil { /** * 主线程处理器 */ private final static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper()); /** * 通用方法,获得参数值,如未找到参数,则直接中断 * * @param methodCall 方法调用对象 * @param result 返回对象 * @param param 参数名 */ public static T getParam(MethodCall methodCall, MethodChannel.Result result, String param) { T par = methodCall.argument(param); if (par == null) { result.error("Missing parameter", "Cannot find parameter `" + param + "` or `" + param + "` is null!", 5); throw new RuntimeException("Cannot find parameter `" + param + "` or `" + param + "` is null!"); } return par; } /** * 运行主线程返回结果执行 * * @param result 返回结果对象 * @param param 返回参数 */ public static void runMainThreadReturn(final MethodChannel.Result result, final Object param) { MAIN_HANDLER.post(new Runnable() { @Override public void run() { result.success(param); } }); } /** * 运行主线程返回错误结果执行 * * @param result 返回结果对象 * @param errorCode 错误码 * @param errorMessage 错误信息 * @param errorDetails 错误内容 */ public static void runMainThreadReturnError(final MethodChannel.Result result, final String errorCode, final String errorMessage, final Object errorDetails) { MAIN_HANDLER.post(new Runnable() { @Override public void run() { result.error(errorCode, errorMessage, errorDetails); } }); } /** * 运行主线程方法 */ public static void runMainThreadMethod(Runnable runnable){ MAIN_HANDLER.post(runnable); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/util/JsonUtil.java ================================================ package top.huic.tencent_im_plugin.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.ValueFilter; /** * JSON工具类 * * @author 蒋具宏 */ public class JsonUtil { /** * 自定义数据过滤器 */ private static final ValueFilter filter = new ValueFilter() { @Override public Object process(Object object, String name, Object value) { if (value instanceof byte[]) { return new String((byte[]) value); } return value; } }; /** * 将对象序列化为JSON * * @param data 对象 * @return 解析结果 */ public static String toJSONString(Object data) { if (data instanceof String) return data.toString(); return JSON.toJSONString(data, filter); } } ================================================ FILE: android/src/main/java/top/huic/tencent_im_plugin/util/TencentImUtils.java ================================================ package top.huic.tencent_im_plugin.util; import com.alibaba.fastjson.JSON; import com.tencent.imsdk.v2.V2TIMFriendApplication; import com.tencent.imsdk.v2.V2TIMFriendApplicationResult; import com.tencent.imsdk.v2.V2TIMGroupApplication; import com.tencent.imsdk.v2.V2TIMGroupApplicationResult; import com.tencent.imsdk.v2.V2TIMManager; import com.tencent.imsdk.v2.V2TIMMessage; import com.tencent.imsdk.v2.V2TIMValueCallback; import java.util.ArrayList; import java.util.Collections; import java.util.List; import top.huic.tencent_im_plugin.ValueCallBack; import top.huic.tencent_im_plugin.entity.FindFriendApplicationEntity; import top.huic.tencent_im_plugin.entity.FindGroupApplicationEntity; import top.huic.tencent_im_plugin.entity.FindMessageEntity; /** * 腾讯云IM工具类 */ public class TencentImUtils { /** * 获得好友申请对象 * * @param json json 字符串 * @param call 回调对象 */ public static void getFriendApplicationByFindGroupApplicationEntity(String json, ValueCallBack call) { getFriendApplicationByFindGroupApplicationEntity(JSON.parseObject(json, FindFriendApplicationEntity.class), call); } /** * 获得好友申请对象 * * @param data 实体对象 * @param call 回调对象 */ public static void getFriendApplicationByFindGroupApplicationEntity(final FindFriendApplicationEntity data, final ValueCallBack call) { V2TIMManager.getFriendshipManager().getFriendApplicationList(new V2TIMValueCallback() { @Override public void onError(int i, String s) { call.onError(i, s); } @Override public void onSuccess(V2TIMFriendApplicationResult v2TIMFriendApplicationResult) { if (v2TIMFriendApplicationResult.getFriendApplicationList() != null) { for (V2TIMFriendApplication item : v2TIMFriendApplicationResult.getFriendApplicationList()) { if (item.getUserID().equals(data.getUserID()) && item.getType() == data.getType()) { call.onSuccess(item); return; } } } call.onSuccess(null); } }); } /** * 获得群申请对象 * * @param json json 字符串 * @param call 回调对象 */ public static void getGroupApplicationByFindGroupApplicationEntity(String json, ValueCallBack call) { getGroupApplicationByFindGroupApplicationEntity(JSON.parseObject(json, FindGroupApplicationEntity.class), call); } /** * 获得群申请对象 * * @param data 实体对象 * @param call 回调对象 */ public static void getGroupApplicationByFindGroupApplicationEntity(final FindGroupApplicationEntity data, final ValueCallBack call) { V2TIMManager.getGroupManager().getGroupApplicationList(new V2TIMValueCallback() { @Override public void onError(int i, String s) { call.onError(i, s); } @Override public void onSuccess(V2TIMGroupApplicationResult v2TIMGroupApplicationResult) { if (v2TIMGroupApplicationResult.getGroupApplicationList() != null) { for (V2TIMGroupApplication item : v2TIMGroupApplicationResult.getGroupApplicationList()) { if (item.getGroupID().equals(data.getGroupID()) && item.getFromUser().equals(data.getFromUser())) { call.onSuccess(item); return; } } } call.onSuccess(null); } }); } /** * 获得消息对象 * * @param json json字符串 * @param call 回调对象 */ public static void getMessageByFindMessageEntity(String json, ValueCallBack call) { getMessageByFindMessageEntity(JSON.parseObject(json, FindMessageEntity.class), call); } /** * 获得消息对象 * * @param data 查找消息对象实体 * @param call 回调对象 */ public static void getMessageByFindMessageEntity(final FindMessageEntity data, final ValueCallBack call) { getMessageByFindMessageEntity(Collections.singletonList(data), new ValueCallBack>(null) { @Override public void onSuccess(List v2TIMMessages) { if (v2TIMMessages == null || v2TIMMessages.size() == 0) { call.onError(-1, "未找到消息对象!消息ID不存在"); return; } call.onSuccess(v2TIMMessages.get(0)); } @Override public void onError(int code, String desc) { call.onError(code, desc); } }); } /** * 获得消息对象 * * @param data 查找消息对象实体 * @param call 回调对象 */ public static void getMessageByFindMessageEntity(List data, final ValueCallBack> call) { List ids = new ArrayList<>(); for (FindMessageEntity datum : data) { ids.add(datum.getMsgId()); } V2TIMManager.getMessageManager().findMessages(ids, new V2TIMValueCallback>() { @Override public void onError(int i, String s) { call.onError(i, s); } @Override public void onSuccess(List v2TIMMessages) { call.onSuccess(v2TIMMessages); } }); } } ================================================ FILE: example/.gitignore ================================================ # Miscellaneous *.class *.log *.pyc *.swp .DS_Store .atom/ .buildlog/ .history .svn/ # IntelliJ related *.iml *.ipr *.iws .idea/ # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line # is commented out by default. #.vscode/ # Flutter/Dart/Pub related **/doc/api/ .dart_tool/ .flutter-plugins .flutter-plugins-dependencies .packages .pub-cache/ .pub/ /build/ # Web related lib/generated_plugin_registrant.dart # Exceptions to above rules. !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages ================================================ FILE: example/.metadata ================================================ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # # This file should be version controlled and should not be manually edited. version: revision: d345a3b303ce041846ff895eb49a104bef133c4b channel: master project_type: app ================================================ FILE: example/README.md ================================================ # tencent_im_plugin_example Demonstrates how to use the tencent_im_plugin plugin. ## Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this is your first Flutter project: - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) For help getting started with Flutter, view our [online documentation](https://flutter.dev/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. ================================================ FILE: example/android/.gitignore ================================================ gradle-wrapper.jar /.gradle /captures/ /gradlew /gradlew.bat /local.properties GeneratedPluginRegistrant.java ================================================ FILE: example/android/app/agconnect-services.json ================================================ { "agcgw":{ "backurl":"connect-drcn.dbankcloud.cn", "url":"connect-drcn.hispace.hicloud.com" }, "client":{ "cp_id":"890086000102176873", "product_id":"736430079244549109", "client_id":"400572237515588608", "client_secret":"76A8613ED5A461B6AA74396CAF70DBB0B23690F8B4136A0A66AA202FFEEA890D", "app_id":"102514829", "package_name":"top.huic.tencent_im_plugin_example", "api_key":"CgB6e3x9I8KuPeIag8AT0fhvvrEf57HaQCYqoB91348bgNFNEim2y+8s3/ervtmQDygm6EKiBqCBRdNurhYotfYi" }, "service":{ "analytics":{ "collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", "resource_id":"p1", "channel_id":"" }, "cloudstorage":{ "storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn" }, "ml":{ "mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn" } }, "region":"CN", "configuration_version":"1.0" } ================================================ FILE: example/android/app/build.gradle ================================================ def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" //def keystorePropertiesFile = rootProject.file("key.properties") //def keystoreProperties = new Properties() //keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { compileSdkVersion 28 lintOptions { disable 'InvalidPackage' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "top.huic.tencent_im_plugin_example" minSdkVersion 17 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } // 证书参数 signingConfigs { config { storeFile file('key.jks') storePassword '123456' keyAlias 'key' keyPassword '123456' v1SigningEnabled true v2SigningEnabled true } } buildTypes { debug { signingConfig signingConfigs.config } release { signingConfig signingConfigs.config // // 开启混淆 // minifyEnabled true // useProguard true } } compileOptions { sourceCompatibility = 1.8 targetCompatibility = 1.8 } // 减小应用程序大小的配置 aaptOptions { ignoreAssetsPattern "!x86:!*ffprobe" } } flutter { source '../..' } dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' } apply plugin: 'com.huawei.agconnect' ================================================ FILE: example/android/app/src/debug/AndroidManifest.xml ================================================ ================================================ FILE: example/android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: example/android/app/src/main/java/top/huic/tencent_im_plugin_example/MainActivity.java ================================================ package top.huic.tencent_im_plugin_example; import android.app.ActivityManager; import android.content.Context; import android.os.Bundle; import java.util.List; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugins.GeneratedPluginRegistrant; public class MainActivity extends FlutterActivity { /** * Flutter 通知器 */ public static MethodChannel channel; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); channel = new MethodChannel(this.getFlutterEngine().getDartExecutor(), "tencent_im_plugin_example"); } @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine); } } ================================================ FILE: example/android/app/src/main/res/drawable/launch_background.xml ================================================ ================================================ FILE: example/android/app/src/main/res/values/styles.xml ================================================ ================================================ FILE: example/android/app/src/profile/AndroidManifest.xml ================================================ ================================================ FILE: example/android/build.gradle ================================================ buildscript { repositories { google() jcenter() maven {url 'https://developer.huawei.com/repo/'} } dependencies { classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.huawei.agconnect:agcp:1.2.1.301' } } allprojects { repositories { google() jcenter() } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } task clean(type: Delete) { delete rootProject.buildDir } ================================================ FILE: example/android/gradle/wrapper/gradle-wrapper.properties ================================================ #Fri Feb 28 14:11:06 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip ================================================ FILE: example/android/gradle.properties ================================================ org.gradle.jvmargs=-Xmx1536M android.enableR8=true android.useAndroidX=true android.enableJetifier=true ================================================ FILE: example/android/settings.gradle ================================================ include ':app' def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() def plugins = new Properties() def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') if (pluginsFile.exists()) { pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } } plugins.each { name, path -> def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() include ":$name" project(":$name").projectDir = pluginDirectory } ================================================ FILE: example/ios/.gitignore ================================================ *.mode1v3 *.mode2v3 *.moved-aside *.pbxuser *.perspectivev3 **/*sync/ .sconsign.dblite .tags* **/.vagrant/ **/DerivedData/ Icon? **/Pods/ **/.symlinks/ profile xcuserdata **/.generated/ Flutter/App.framework Flutter/Flutter.framework Flutter/Flutter.podspec Flutter/Generated.xcconfig Flutter/app.flx Flutter/app.zip Flutter/flutter_assets/ Flutter/flutter_export_environment.sh ServiceDefinitions.json Runner/GeneratedPluginRegistrant.* # Exceptions to above rules. !default.mode1v3 !default.mode2v3 !default.pbxuser !default.perspectivev3 ================================================ FILE: example/ios/Flutter/AppFrameworkInfo.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable App CFBundleIdentifier io.flutter.flutter.app CFBundleInfoDictionaryVersion 6.0 CFBundleName App CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 MinimumOSVersion 9.0 ================================================ FILE: example/ios/Flutter/Debug.xcconfig ================================================ #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" ================================================ FILE: example/ios/Flutter/Release.xcconfig ================================================ #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" ================================================ FILE: example/ios/Podfile ================================================ # Uncomment this line to define a global platform for your project platform :ios, '8.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' project 'Runner', { 'Debug' => :debug, 'Profile' => :release, 'Release' => :release, } def flutter_root generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) unless File.exist?(generated_xcode_build_settings_path) raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" end File.foreach(generated_xcode_build_settings_path) do |line| matches = line.match(/FLUTTER_ROOT\=(.*)/) return matches[1].strip if matches end raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" end require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) flutter_ios_podfile_setup def install_plugin_pods(application_path = nil, relative_symlink_dir, platform) # defined_in_file is set by CocoaPods and is a Pathname to the Podfile. application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file) raise 'Could not find application path' unless application_path # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock # referring to absolute paths on developers' machines. symlink_dir = File.expand_path(relative_symlink_dir, application_path) system('rm', '-rf', symlink_dir) # Avoid the complication of dependencies like FileUtils. symlink_plugins_dir = File.expand_path('plugins', symlink_dir) system('mkdir', '-p', symlink_plugins_dir) plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies') plugin_pods = flutter_parse_plugins_file(plugins_file, platform) plugin_pods.each do |plugin_hash| plugin_name = plugin_hash['name'] plugin_path = plugin_hash['path'] if (plugin_name && plugin_path) specPath = "#{plugin_path}/#{platform}/#{plugin_name}.podspec" pod plugin_name, :path => specPath end end end target 'Runner' do use_frameworks! use_modular_headers! flutter_install_ios_engine_pod(File.dirname(File.realpath(__FILE__))) install_plugin_pods(File.dirname(File.realpath(__FILE__)), '.symlinks', 'ios') end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) end end ================================================ FILE: example/ios/Runner/AppDelegate.swift ================================================ import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } ================================================ FILE: example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-App-20x20@3x.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@3x.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-App-40x40@3x.png", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-App-60x60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-App-60x60@3x.png", "scale" : "3x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-App-20x20@1x.png", "scale" : "1x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-App-40x40@1x.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-App-76x76@1x.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-App-76x76@2x.png", "scale" : "2x" }, { "size" : "83.5x83.5", "idiom" : "ipad", "filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", "filename" : "Icon-App-1024x1024@1x.png", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "LaunchImage.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "LaunchImage@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "LaunchImage@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md ================================================ # Launch Screen Assets You can customize the launch screen with your own desired assets by replacing the image files in this directory. You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. ================================================ FILE: example/ios/Runner/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: example/ios/Runner/Base.lproj/Main.storyboard ================================================ ================================================ FILE: example/ios/Runner/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName tencent_im_plugin_example CFBundlePackageType APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) CFBundleSignature ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS NSAppTransportSecurity NSAllowsArbitraryLoads NSCameraUsageDescription App需要您的同意,才能访问相册 NSLocationWhenInUseUsageDescription 是否允许需要访问位置? NSMicrophoneUsageDescription App需要您的同意,才能访问麦克风 NSPhotoLibraryUsageDescription 是否允许访问图片库? NSPhotoLibraryAddUsageDescription 是否允许保存图片? Privacy - Calendars Usage Description 是否允许访问日历? Privacy - Location Always Usage Description 是否允许始终访问位置? Privacy - Location When In Use Usage Description 是否允许使用期间访问位置? UIBackgroundModes audio UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance ================================================ FILE: example/ios/Runner/Runner-Bridging-Header.h ================================================ #import "GeneratedPluginRegistrant.h" ================================================ FILE: example/ios/Runner.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 50; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; F421BC9C2F4D92DF91A983A8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5951A49241F164BFC879FD8A /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 453EE5ABF54A138152CF911D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 4B436B647E9F79944B465D68 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 5951A49241F164BFC879FD8A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E27FEED2BBEF82CCFCE08B08 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( F421BC9C2F4D92DF91A983A8 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 38FEDA953939FFB3CD8B4370 /* Pods */ = { isa = PBXGroup; children = ( 453EE5ABF54A138152CF911D /* Pods-Runner.debug.xcconfig */, E27FEED2BBEF82CCFCE08B08 /* Pods-Runner.release.xcconfig */, 4B436B647E9F79944B465D68 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, ); name = Flutter; sourceTree = ""; }; 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 38FEDA953939FFB3CD8B4370 /* Pods */, A3BD4893CCA84354F64352B2 /* Frameworks */, ); sourceTree = ""; }; 97C146EF1CF9000F007C117D /* Products */ = { isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, ); name = Products; sourceTree = ""; }; 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; }; 97C146F11CF9000F007C117D /* Supporting Files */ = { isa = PBXGroup; children = ( ); name = "Supporting Files"; sourceTree = ""; }; A3BD4893CCA84354F64352B2 /* Frameworks */ = { isa = PBXGroup; children = ( 5951A49241F164BFC879FD8A /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( F39B2611AF028A7ADB261525 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 5F1A0E9208832B656E3DB0F2 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = Runner; productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; DevelopmentTeam = ZVZ337XL75; LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 97C146E51CF9000F007C117D; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Thin Binary"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 5F1A0E9208832B656E3DB0F2 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${BUILT_PRODUCTS_DIR}/HandyJSON/HandyJSON.framework", "${PODS_ROOT}/TXIMSDK_Plus_iOS_Bitcode/ImSDK_Plus.framework", "${BUILT_PRODUCTS_DIR}/Toast/Toast.framework", "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", "${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework", "${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework", "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", "${BUILT_PRODUCTS_DIR}/tencent_im_plugin/tencent_im_plugin.framework", "${BUILT_PRODUCTS_DIR}/video_player/video_player.framework", "${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HandyJSON.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ImSDK_Plus.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/tencent_im_plugin.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; F39B2611AF028A7ADB261525 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 97C146FB1CF9000F007C117D /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 97C147001CF9000F007C117D /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Profile; }; 249021D4217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = YYHJZM64K7; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = top.huic.tencentImPluginExample; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 97C147061CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = ZVZ337XL75; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = top.huic.tencentImPluginExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 97C147071CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = YYHJZM64K7; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = top.huic.tencentImPluginExample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( 97C147031CF9000F007C117D /* Debug */, 97C147041CF9000F007C117D /* Release */, 249021D3217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( 97C147061CF9000F007C117D /* Debug */, 97C147071CF9000F007C117D /* Release */, 249021D4217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } ================================================ FILE: example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme ================================================ ================================================ FILE: example/ios/Runner.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: example/lib/main.dart ================================================ import 'package:flutter/material.dart'; import 'package:tencent_im_plugin_example/page/chat.dart'; import 'package:tencent_im_plugin_example/page/home.dart'; import 'package:tencent_im_plugin_example/page/interfaces_test.dart'; import 'package:tencent_im_plugin_example/page/login.dart'; import 'package:tencent_im_plugin_example/page/main/main.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, routes: { "/": (context) => HomePage(), "/interfaces_test": (context) => InterfacesTest(), "/login": (context) => Login(), "/main": (context) => Main(), "/chat": (context) => Chat(), }, ); } } ================================================ FILE: example/lib/page/chat.dart ================================================ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; import 'package:tencent_im_plugin/entity/conversation_entity.dart'; import 'package:tencent_im_plugin/entity/message_entity.dart'; import 'package:tencent_im_plugin/entity/user_entity.dart'; import 'package:tencent_im_plugin/entity/find_message_entity.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart'; import 'package:tencent_im_plugin/message_node/text_message_node.dart'; import 'package:tencent_im_plugin/message_node/custom_message_node.dart'; import 'package:tencent_im_plugin/message_node/image_message_node.dart'; import 'package:tencent_im_plugin/message_node/video_message_node.dart'; import 'package:tencent_im_plugin/message_node/sound_message_node.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/enums/image_type_enum.dart'; import 'package:image_picker/image_picker.dart'; import 'package:video_player/video_player.dart'; import 'package:video_thumbnail/video_thumbnail.dart'; import 'package:tencent_im_plugin/enums/message_status_enum.dart'; /// 聊天页面 class Chat extends StatefulWidget { @override _ChatState createState() => _ChatState(); } class _ChatState extends State { /// 文本组件控制器 TextEditingController _textEditingController = TextEditingController(); /// 会话实体 ConversationEntity _conversation; /// 消息列表 List _messages = []; /// 用户信息 UserEntity _selfUser; /// 临时目录 String _tempPath; @override void initState() { super.initState(); TencentImPlugin.addListener(_imListener); _loadTempPath(); SchedulerBinding.instance.addPostFrameCallback((_) { _conversation = ModalRoute.of(context).settings.arguments; this.setState(() {}); _loadUserInfo(); _onLoadMessages(); _textEditingController.text = _conversation.draftText; }); } @override void dispose() { super.dispose(); TencentImPlugin.removeListener(_imListener); String text = _textEditingController.text.trim(); TencentImPlugin.setConversationDraft( conversationID: _conversation.conversationID, draftText: text.trim() != '' ? text : null); } /// IM监听器 _imListener(type, params) { if (type == TencentImListenerTypeEnum.NewMessage) { this.setState(() { this._messages.insert(0, params); }); } if (type == TencentImListenerTypeEnum.MessageSendProgress) { print("==================="); print("消息发送进度更新:${params.msgId}"); print("==================="); } if (type == TencentImListenerTypeEnum.MessageSendSucc) { print("==================="); print("消息发送成功"); print("==================="); } if (type == TencentImListenerTypeEnum.MessageSendFail) { print("==================="); print("消息发送失败"); print("==================="); } } /// 加载连目录 _loadTempPath() async { _tempPath = (await getTemporaryDirectory()).path; this.setState(() {}); } /// 加载当前登录用户信息 _loadUserInfo() async { this._selfUser = (await TencentImPlugin.getUsersInfo( userIDList: [await TencentImPlugin.getLoginUser()]))[0]; this.setState(() {}); } /// 加载消息 _onLoadMessages() async { if (_conversation == null) { return; } List messages = await (_conversation.groupID != null ? TencentImPlugin.getGroupHistoryMessageList( groupID: _conversation.groupID, count: 100) : TencentImPlugin.getC2CHistoryMessageList( userID: _conversation.userID, count: 100)); this.setState(() { this._messages = messages; }); // 下载语音、视频缩略图 for (var item in messages) { if (item.elemType == MessageElemTypeEnum.Video) { File file = new File( _tempPath + "/" + (item.node as VideoMessageNode).snapshotUuid); if (!file.existsSync()) { TencentImPlugin.downloadVideoThumbnail( message: FindMessageEntity(msgId: item.msgID), path: file.path) .then((value) { this.setState(() {}); }); } } if (item.elemType == MessageElemTypeEnum.Sound) { File file = new File(_tempPath + "/" + (item.node as SoundMessageNode).uuid); if (!file.existsSync()) { TencentImPlugin.downloadSound( message: FindMessageEntity(msgId: item.msgID), path: file.path) .then((value) { this.setState(() {}); }); } } } this.setState(() {}); } /// 发送按钮点击事件 _onSend() async { String text = _textEditingController.text; if (text.trim() == '') { return; } this._sendMessage(TextMessageNode(content: text, atUserList: [])); _textEditingController.text = ""; } /// 图片选择按钮 _onImageSelect() async { int value = await showCupertinoModalPopup( builder: (BuildContext context) => CupertinoActionSheet( actions: [ CupertinoActionSheetAction( child: Text("图片"), onPressed: () => Navigator.pop(this.context, 0), ), CupertinoActionSheetAction( child: Text("视频"), onPressed: () => Navigator.pop(this.context, 1), ), ], cancelButton: CupertinoActionSheetAction( child: Text("取消"), onPressed: () => Navigator.pop(this.context), ), // 取消按钮 ), context: context, ); if (value == null) { return; } // 图片 if (value == 0) { final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery); if (pickedFile == null) return; this._sendMessage(ImageMessageNode(path: pickedFile.path)); } // 视频 if (value == 1) { final pickedFile = await ImagePicker().getVideo(source: ImageSource.gallery); if (pickedFile == null) return; // 获得视频缩略图 String thumb = await VideoThumbnail.thumbnailFile( video: pickedFile.path, thumbnailPath: _tempPath, imageFormat: ImageFormat.JPEG, quality: 25, ); // 获得控制器并获得视频时长 VideoPlayerController playerController = VideoPlayerController.file(File(pickedFile.path)); await playerController.initialize(); int duration = playerController.value.duration.inSeconds; this._sendMessage(VideoMessageNode( duration: duration, snapshotPath: thumb, videoPath: pickedFile.path)); } } /// 根据消息获得组件 _getMessageComponent(MessageEntity message) { // 文本消息 if (message.elemType == MessageElemTypeEnum.Text) { return Text((message.node as TextMessageNode).content); } // 图片消息 if (message.elemType == MessageElemTypeEnum.Image) { ImageMessageNode node = message.node; if ((node.path == null || node.path == '') && node.imageData != null) { return Container( constraints: BoxConstraints( maxHeight: 100, maxWidth: 100, ), child: Image.network(node.imageData[ImageTypeEnum.Thumb]?.url), ); } return Container( constraints: BoxConstraints( maxHeight: 100, maxWidth: 100, ), child: Image.file(File(node.path)), ); } // 视频消息 if (message.elemType == MessageElemTypeEnum.Video) { VideoMessageNode node = message.node; String path = node.snapshotPath == null || node.snapshotPath == '' ? (_tempPath + "/" + node.snapshotUuid) : node.snapshotPath; return Container( constraints: BoxConstraints( maxHeight: 100, maxWidth: 100, ), child: Image.file(File(path)), ); } if (message.elemType == MessageElemTypeEnum.Custom) { CustomMessageNode node = message.node; return Text("[自定义消息]data:${node.data},desc:${node.desc},ext:${node.ext}"); } return Text("暂不支持的数据格式"); } /// 发送消息 _sendMessage(MessageNode node) async { String msgId = await TencentImPlugin.sendMessage( node: node, receiver: _conversation.userID, groupID: _conversation.groupID, ); this._messages.insert( 0, MessageEntity( msgID: msgId, node: node, faceUrl: _selfUser.faceUrl, elemType: node.nodeType, status: MessageStatusEnum.Sending, ), ); this.setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: Text(_conversation?.showName ?? "加载中..."), centerTitle: true, actions: [ _conversation == null ? null : IconButton( icon: Icon(_conversation.groupID != null ? Icons.supervisor_account : Icons.settings), onPressed: () => {}, ), Container(width: 8), ]..removeWhere((element) => element == null), ), body: Column( children: [ Expanded( child: Column( children: [ Flexible( child: ListView( reverse: true, shrinkWrap: true, children: _messages .map( (item) => Padding( padding: const EdgeInsets.all(8.0), child: Container( child: Row( mainAxisAlignment: item.self ? MainAxisAlignment.end : MainAxisAlignment.start, children: [ Offstage( child: Row( children: [ CircleAvatar( backgroundImage: item.faceUrl == null || item.faceUrl == '' ? null : NetworkImage(item.faceUrl), ), Container(width: 10), ], ), offstage: item.self, ), _getMessageComponent(item), Offstage( child: Row( children: [ Container(width: 10), CircleAvatar( backgroundImage: item.faceUrl == null || item.faceUrl == '' ? null : NetworkImage(item.faceUrl), ), ], ), offstage: !item.self, ), ], ), ), ), ) .toList(), ), ), ], ), ), Container( child: Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: _onImageSelect, child: Icon( Icons.image_outlined, size: 30, ), ), Container(width: 8), // GestureDetector( // onTap: () {}, // child: Icon( // Icons.mic, // size: 30, // ), // ), // Container(width: 8), Expanded( child: Container( constraints: BoxConstraints( maxHeight: 40, ), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(30)), color: Color(0xFFEEEEEE), ), child: TextField( controller: _textEditingController, decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.only( left: 15, top: -8, bottom: 0, right: 15, ), ), ), ), ), Container(width: 8), OutlinedButton(onPressed: _onSend, child: Text("发送")) ], ), ), ), ], ), ); } } ================================================ FILE: example/lib/page/home.dart ================================================ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State { @override void initState() { super.initState(); TencentImPlugin.initSDK(appid: '1400294314'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("页面导航")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ OutlinedButton( onPressed: () => Navigator.pushNamed(context, "/interfaces_test"), child: Text("接口测试"), ), OutlinedButton( onPressed: () => Navigator.pushNamed(context, "/login"), child: Text("进入Demo"), ), ], ), ), ); } } ================================================ FILE: example/lib/page/interfaces_test.dart ================================================ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin/utils/enum_util.dart'; import 'package:tencent_im_plugin/entity/group_info_entity.dart'; import 'package:tencent_im_plugin/entity/signaling_info_entity.dart'; import 'package:tencent_im_plugin/entity/user_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/entity/friend_info_entity.dart'; import 'package:tencent_im_plugin/entity/friend_add_application_entity.dart'; import 'package:tencent_im_plugin/message_node/text_message_node.dart'; import 'package:tencent_im_plugin/enums/signaling_action_type_enum.dart'; import 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart'; import 'package:tencent_im_plugin/enums/group_member_role_enum.dart'; import 'package:tencent_im_plugin/enums/friend_type_enum.dart'; import 'package:logger/logger.dart'; typedef TestCallback = Future Function(); /// 接口测试页面 class InterfacesTest extends StatefulWidget { @override _InterfacesTestState createState() => _InterfacesTestState(); } class _InterfacesTestState extends State { /// 日志输出 static Logger _logger = Logger(); /// 群ID static String _groupId = "@TGS#2HAKW7YGC"; /// 直播群ID static String _avGroupId = "@TGS#aRXCQ7YGG"; /// 好友ID static String _friendId = "test"; /// 接口列表 Map _interfaces = { "getLoginStatus": () => TencentImPlugin.getLoginStatus(), "getLoginUser": () => TencentImPlugin.getLoginUser(), "invite": () => TencentImPlugin.invite(data: "邀请你进行视频通话1", invitee: _friendId), "inviteInGroup": () => TencentImPlugin.inviteInGroup(data: "邀请你进行视频通话2", groupID: _groupId, inviteeList: [_friendId]), "cancel": () async => TencentImPlugin.cancel(inviteID: await TencentImPlugin.invite(data: "邀请你进行视频通话3", invitee: _friendId), data: "123"), "accept": () async => TencentImPlugin.accept(inviteID: await TencentImPlugin.invite(data: "邀请你进行视频通话4", invitee: _friendId), data: "123"), "reject": () async => TencentImPlugin.reject(inviteID: await TencentImPlugin.invite(data: "邀请你进行视频通话5", invitee: _friendId), data: "123"), // "getSignalingInfo": () async => TencentImPlugin.getSignalingInfo(inviteID: await TencentImPlugin.invite(data: "邀请你进行视频通话", invitee: _friendId), data: "123"), "addInvitedSignaling": () async => TencentImPlugin.addInvitedSignaling( info: SignalingInfoEntity( inviter: _friendId, data: "test", actionType: SignalingActionTypeEnum.Invite, inviteeList: ["dev"], ), ), "sendMessage": () async => TencentImPlugin.sendMessage(receiver: _friendId, node: TextMessageNode(content: "1433223")), // "revokeMessage": () async => TencentImPlugin.revokeMessage(receiver: "dev", node: TextMessageNode(content: "1433223")), "getC2CHistoryMessageList": () async => TencentImPlugin.getC2CHistoryMessageList(userID: _friendId, count: 100), "getGroupHistoryMessageList": () async => TencentImPlugin.getGroupHistoryMessageList(groupID: _groupId, count: 100), "markC2CMessageAsRead": () async => TencentImPlugin.markC2CMessageAsRead(userID: _friendId), "markGroupMessageAsRead": () async => TencentImPlugin.markGroupMessageAsRead(groupID: _groupId), // "deleteMessageFromLocalStorage": () async => TencentImPlugin.deleteMessageFromLocalStorage(groupID: _groupId), // "deleteMessages": () async => TencentImPlugin.deleteMessages(groupID: _groupId), "insertGroupMessageToLocalStorage": () async => TencentImPlugin.insertGroupMessageToLocalStorage( node: TextMessageNode(content: "1433223"), groupID: _groupId, sender: _friendId, ), // "createGroup": () async => TencentImPlugin.createGroup( // info: GroupInfoEntity( // groupType: GroupTypeEnum.Public, // groupName: "测试群聊", // notification: "这是群公告", // introduction: "这是群简介", // ), // ), // "joinGroup": () async => TencentImPlugin.joinGroup(message: "申请入群", groupID: _groupId), // "quitGroup": () async => TencentImPlugin.quitGroup(groupID: _groupId), // "dismissGroup": () async => TencentImPlugin.dismissGroup(groupID: _groupId), "getJoinedGroupList": () async => TencentImPlugin.getJoinedGroupList(), "getGroupsInfo": () async => TencentImPlugin.getGroupsInfo(groupIDList: [_groupId]), "setGroupInfo": () async => TencentImPlugin.setGroupInfo( info: GroupInfoEntity( groupID: _groupId, groupName: "${DateTime.now()}", ), ), "searchGroups": () async => TencentImPlugin.searchGroups( keywordList: ["1", "2"], isSearchGroupID: true, isSearchGroupName: true, ), "searchGroupMembers": () async => TencentImPlugin.searchGroupMembers( keywordList: ["1", "2"], groupIDList: [_groupId], isSearchMemberNameCard: true, isSearchMemberUserID: true, isSearchMemberRemark: true, isSearchMemberNickName: true, ), "setGroupReceiveMessageOpt": () async => TencentImPlugin.setGroupReceiveMessageOpt( groupID: _groupId, opt: ReceiveMessageOptEnum.ReceiveAndNotify, ), "setC2CReceiveMessageOpt": () async => TencentImPlugin.setC2CReceiveMessageOpt( ids: [_friendId], opt: ReceiveMessageOptEnum.ReceiveAndNotify, ), "getC2CReceiveMessageOpt": () async => await TencentImPlugin.getC2CReceiveMessageOpt(ids: [_friendId]), "initGroupAttributes": () async => TencentImPlugin.initGroupAttributes( groupID: _avGroupId, attributes: { "a": "1", "b": "2", }, ), "setGroupAttributes": () async => TencentImPlugin.setGroupAttributes( groupID: _avGroupId, attributes: { "c": "3", "d": "4", }, ), "deleteGroupAttributes": () async => TencentImPlugin.deleteGroupAttributes(groupID: _avGroupId, keys: ["b"]), "getGroupAttributes": () async => TencentImPlugin.getGroupAttributes(groupID: _avGroupId), "getGroupMemberList": () async => TencentImPlugin.getGroupMemberList(groupID: _groupId), "getGroupMembersInfo": () async => TencentImPlugin.getGroupMembersInfo(groupID: _groupId, memberList: [_friendId]), "setGroupMemberInfo": () async => TencentImPlugin.setGroupMemberInfo( groupID: _groupId, info: GroupMemberEntity( userID: _friendId, nameCard: "测试群名片", ), ), "muteGroupMember": () async => TencentImPlugin.muteGroupMember( groupID: _groupId, seconds: 60, userID: _friendId, ), // "inviteUserToGroup": () async => TencentImPlugin.inviteUserToGroup( // groupID: _groupId, // userList: [_friendId], // ), // "kickGroupMember": () async => TencentImPlugin.kickGroupMember( // groupID: _groupId, // memberList: [_friendId], // ), "setGroupMemberRole": () async => TencentImPlugin.setGroupMemberRole( groupID: _groupId, userID: _friendId, role: GroupMemberRoleEnum.Admin, ), // "transferGroupOwner": () async => TencentImPlugin.transferGroupOwner( // groupID: _groupId, // userID: _friendId, // ), // "getGroupApplicationList": () async => TencentImPlugin.getGroupApplicationList(), // "acceptGroupApplication": () async => TencentImPlugin.acceptGroupApplication(), // "refuseGroupApplication": () async => TencentImPlugin.refuseGroupApplication(), "setGroupApplicationRead": () async => TencentImPlugin.setGroupApplicationRead(), "getConversationList": () async => TencentImPlugin.getConversationList(), "getConversation": () async => TencentImPlugin.getConversation(conversationID: (await TencentImPlugin.getConversationList()).conversationList[0].conversationID), "deleteConversation": () async => TencentImPlugin.deleteConversation(conversationID: (await TencentImPlugin.getConversationList()).conversationList[0].conversationID), "setConversationDraft": () async => TencentImPlugin.setConversationDraft( conversationID: (await TencentImPlugin.getConversationList()).conversationList[0].conversationID, draftText: "测试会话草稿", ), "getUsersInfo": () async => TencentImPlugin.getUsersInfo(userIDList: [_friendId]), "setSelfInfo": () async => TencentImPlugin.setSelfInfo(info: UserEntity(nickName: "${DateTime.now()}")), "addToBlackList": () async => TencentImPlugin.addToBlackList(userIDList: [_friendId]), "getBlackList": () async => TencentImPlugin.getBlackList(), "deleteFromBlackList": () async => TencentImPlugin.deleteFromBlackList(userIDList: [_friendId]), "setOfflinePushConfig": () async => TencentImPlugin.setOfflinePushConfig(bussid: 10301, token: "请输入您的Token"), "setUnreadBadge": () async => TencentImPlugin.setUnreadBadge(number: 10), "getFriendList": () async => TencentImPlugin.getFriendList(), "getFriendsInfo": () async => TencentImPlugin.getFriendsInfo(userIDList: [_friendId]), "setFriendInfo": () async => TencentImPlugin.setFriendInfo( info: FriendInfoEntity( userID: _friendId, friendRemark: "这是测试备注", ), ), "addFriend": () async => TencentImPlugin.addFriend( info: FriendAddApplicationEntity( userID: _friendId, friendRemark: "这是测试备注", addWording: "申请加为好友", addSource: "手动查找", addType: FriendTypeEnum.Both, ), ), "deleteFromFriendList": () async => TencentImPlugin.deleteFromFriendList(deleteType: FriendTypeEnum.Both, userIDList: [_friendId]), "checkFriend": () async => TencentImPlugin.checkFriend(userID: _friendId, checkType: FriendTypeEnum.Both), "getFriendApplicationList": () async => TencentImPlugin.getFriendApplicationList(), // "acceptFriendApplication": () async => TencentImPlugin.acceptFriendApplication(), // "refuseFriendApplication": () async => TencentImPlugin.refuseFriendApplication(), // "deleteFriendApplication": () async => TencentImPlugin.deleteFriendApplication(), "setFriendApplicationRead": () async => TencentImPlugin.setFriendApplicationRead(), "createFriendGroup": () async => TencentImPlugin.createFriendGroup(userIDList: [_friendId], groupName: "测试分组"), "getFriendGroups": () async => TencentImPlugin.getFriendGroups(groupNameList: ["测试分组"]), "renameFriendGroup": () async => TencentImPlugin.renameFriendGroup(oldName: "测试分组", newName: "test"), "addFriendsToFriendGroup": () async => TencentImPlugin.addFriendsToFriendGroup(groupName: "test", userIDList: [_friendId]), "deleteFriendsFromFriendGroup": () async => TencentImPlugin.deleteFriendsFromFriendGroup(groupName: "test", userIDList: [_friendId]), "deleteFriendGroup": () async => TencentImPlugin.deleteFriendGroup(groupNameList: ["test"]), }; /// 当前正在测试的Key String _currentTestKey; /// 已测试数量 int _finishTestCount = 0; /// 未通过接口列表 List _failInterfaces = []; /// 是否开始测试 bool _start = false; /// 测试结果描述 List _result = []; /// 回调描述 List _callResult = []; @override void initState() { super.initState(); TencentImPlugin.addListener(_listener); TencentImPlugin.login( userID: "dev", userSig: "eJwtzEELgjAYxvHvsnPIu7U5EzoEQRDWITWqW7KVr8MaS8Yi*u6Zenx*D-w-pMjyyGtHUsIiILNho9KPDm84sNJ*4pcyV2tRkZRyALbgc8rHRweLTvcuhGAAMGqH7d9iEAKSWMipgve*ulZS1vKoT83uXO6rkAWzaoqtgVAdNpecu9Y-38aXtE6W5PsDr9ExPw__", ); } @override void dispose() { super.dispose(); TencentImPlugin.removeListener(_listener); TencentImPlugin.logout(); } /// 监听器对象 _listener(type, params) { _callResult.add("${_getDateTime()}-[${EnumUtil.getEnumName(type)}]:$params"); if (this.mounted) { this.setState(() {}); } } /// 获得时间字符串 _getDateTime() { DateTime dateTime = DateTime.now(); return "${dateTime.hour <= 9 ? "0${dateTime.hour}" : dateTime.hour}:${dateTime.minute <= 9 ? "0${dateTime.minute}" : dateTime.minute}:${dateTime.second <= 9 ? "0${dateTime.second}" : dateTime.second}"; } /// 开始测试 startTest() async { this.setState(() => _start = true); for (var key in _interfaces.keys) { this.setState(() => _currentTestKey = key); try { var resultData = await _interfaces[key](); _result.add("${_getDateTime()}-[$key]:测试通过;结果:$resultData"); } catch (err) { _failInterfaces.add("$key : $err"); _result.add("${_getDateTime()}-[$key]:$err"); _logger.e(err, "[测试结果出错] $key"); } this.setState(() => _finishTestCount += 1); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("接口测试列表")), body: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ RichText( text: TextSpan( text: "接口数量:${_interfaces.length}", style: TextStyle(color: Colors.black), children: [ TextSpan(text: ",已通过:"), TextSpan(text: "${_finishTestCount - _failInterfaces.length}", style: TextStyle(color: Colors.green)), TextSpan(text: ",未通过:"), TextSpan(text: "${_failInterfaces.length}", style: TextStyle(color: Colors.red)), ], ), ), _start ? Text((_finishTestCount == _interfaces.length) ? "测试完成" : "正在测试:$_currentTestKey") : OutlinedButton( onPressed: startTest, child: Text("开始测试"), ), Divider(), Text("日志信息"), Expanded( child: ListView( children: _result .map( (e) => RichText( text: TextSpan( text: e, style: TextStyle(color: e.contains("测试通过") ? Colors.green : Colors.red), ), ), ) .toList(), )), Divider(), Text("回调信息"), Expanded( child: ListView( children: _callResult .map( (e) => Text(e), ) .toList(), )), ], ), ), ); } } ================================================ FILE: example/lib/page/login.dart ================================================ import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin_example/utils/GenerateTestUserSig.dart'; /// 登录页面 class Login extends StatefulWidget { @override _LoginState createState() => _LoginState(); } class _LoginState extends State { TextEditingController _controller = TextEditingController(); /// 用户名 String _userName = "dev"; @override void initState() { super.initState(); _controller.text = _userName; } /// 登录按钮点击事件 _onLogin() async { String sign = GenerateTestUserSig( sdkappid: 1400294314, key: "706da51f9280812611bcc80b5182b1c5554db8d053bc00b8a37ae8cba887f6a7", ).genSig(identifier: _userName, expire: 1 * 60 * 1000); await TencentImPlugin.login( userID: _userName, userSig: sign, ); Navigator.pushNamedAndRemoveUntil( context, "/main", (Route route) => false); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("登录页面"), ), body: Padding( padding: const EdgeInsets.all(8.0), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( decoration: InputDecoration(hintText: "请输入用户名"), textAlign: TextAlign.center, onChanged: (value) => this.setState(() => _userName = value), controller: _controller, ), Container(height: 20), OutlinedButton( onPressed: _userName.trim() == '' ? null : _onLogin, child: Text("立即登录"), ), ], ), ), ), ); } } ================================================ FILE: example/lib/page/main/components/conversation.dart ================================================ import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:tencent_im_plugin/entity/conversation_result_entity.dart'; import 'package:tencent_im_plugin/entity/conversation_entity.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart'; /// 会话页面 class Conversation extends StatefulWidget { @override _ConversationState createState() => _ConversationState(); } class _ConversationState extends State { /// 刷新指示器Key GlobalKey _refreshIndicatorKey = GlobalKey(); /// 会话结果对象 ConversationResultEntity _data; @override void initState() { super.initState(); TencentImPlugin.addListener(_imListener); SchedulerBinding.instance.addPostFrameCallback((_) { _refreshIndicatorKey.currentState.show(); }); } @override void dispose() { super.dispose(); TencentImPlugin.removeListener(_imListener); } /// IM监听器 _imListener(type, params) { if (type == TencentImListenerTypeEnum.ConversationChanged) { _onRefresh(); } } /// 刷新事件 Future _onRefresh() { return TencentImPlugin.getConversationList().then((value) { this.setState(() => _data = value); }); } /// 会话点击事件 _onConversationClick(ConversationEntity data) { Navigator.pushNamed(context, "/chat", arguments: data); } @override Widget build(BuildContext context) { return RefreshIndicator( key: _refreshIndicatorKey, onRefresh: _onRefresh, child: ListView( children: ListTile.divideTiles( context: context, tiles: _data?.conversationList == null ? [] : _data.conversationList .map( (item) => ListTile( onTap: () => _onConversationClick(item), leading: CircleAvatar( backgroundImage: item.faceUrl == null || item.faceUrl == '' ? null : NetworkImage(item.faceUrl)), title: RichText( text: TextSpan( children: [ TextSpan( text: "[${item.groupID == null ? "私聊" : "群聊"}] ", style: TextStyle(color: Colors.grey)), TextSpan(text: item.showName), ], style: TextStyle(color: Colors.black), ), ), subtitle: RichText( text: TextSpan( children: [ TextSpan( text: item.draftText == null ? "" : "[草稿]", style: TextStyle(color: Colors.red)), TextSpan( text: item.draftText ?? item.lastMessage?.note ?? "", ), ], style: TextStyle(color: Colors.black), ), ), ), ) .toList(), ).toList(), ), ); } } ================================================ FILE: example/lib/page/main/components/friend.dart ================================================ import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin/entity/friend_info_entity.dart'; import 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart'; import 'package:tencent_im_plugin/enums/friend_application_agree_type_enum.dart'; import 'package:tencent_im_plugin/entity/friend_application_result_entity.dart'; import 'package:tencent_im_plugin/entity/find_friend_application_entity.dart'; /// 好友页面 class Friend extends StatefulWidget { @override _FriendState createState() => _FriendState(); } class _FriendState extends State { /// 刷新指示器Key GlobalKey _refreshIndicatorKey = GlobalKey(); /// 数据结果对象 List _data = []; @override void initState() { super.initState(); TencentImPlugin.addListener(_imListener); SchedulerBinding.instance.addPostFrameCallback((_) { _refreshIndicatorKey.currentState.show(); }); } @override void dispose() { super.dispose(); TencentImPlugin.removeListener(_imListener); } /// IM监听器 _imListener(type, params) { if (type == TencentImListenerTypeEnum.FriendListAdded) { this.setState(() {}); } } /// 刷新事件 Future _onRefresh() { return TencentImPlugin.getFriendList().then((value) => this.setState(() => _data = value)); } @override Widget build(BuildContext context) { return RefreshIndicator( key: _refreshIndicatorKey, onRefresh: _onRefresh, child: Column( children: [ Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text("好友申请列表"))), SingleChildScrollView( child: FutureBuilder( future: TencentImPlugin.getFriendApplicationList(), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState != ConnectionState.done) return Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text("正在拉取好友申请列表"))); if (snapshot.data.friendApplicationList.length == 0) return Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text("暂无待处理好友申请"))); return Column( children: ListTile.divideTiles( context: context, tiles: snapshot.data.friendApplicationList .map( (item) => ListTile( title: Row( children: [ Expanded( child: RichText( text: TextSpan( children: [ TextSpan(text: item.nickname == null || item.nickname == '' ? item.userID : item.nickname), ], style: TextStyle(color: Colors.black), ), ), ), Row( children: [ RaisedButton( onPressed: () async { Future result = TencentImPlugin.acceptFriendApplication(application: FindFriendApplicationEntity.fromFriendApplicationEntity(item), responseType: FriendApplicationAgreeTypeEnum.AgreeAndAdd); await result.then((value) => Fluttertoast.showToast(msg: "处理成功!")).catchError((e) => Fluttertoast.showToast(msg: "处理失败!")); if (this.mounted) this.setState(() {}); }, child: Text("同意"), ), RaisedButton( onPressed: () async { Future result = TencentImPlugin.refuseFriendApplication(application: FindFriendApplicationEntity.fromFriendApplicationEntity(item)); await result.then((value) => Fluttertoast.showToast(msg: "处理成功!")).catchError((e) => Fluttertoast.showToast(msg: "处理失败!")); if (this.mounted) this.setState(() {}); }, child: Text("拒绝"), ), ], ), ], ), ), ) .toList(), ).toList(), ); }, ), ), Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text("好友列表"))), Expanded( child: ListView( children: ListTile.divideTiles( context: context, tiles: _data .map( (item) => ListTile( leading: CircleAvatar(backgroundImage: item.userProfile?.faceUrl == null || item.userProfile.faceUrl == '' ? null : NetworkImage(item.userProfile.faceUrl)), title: RichText( text: TextSpan( children: [ TextSpan(text: item.userProfile.nickName == null || item.userProfile.nickName == '' ? item.userID : item.userProfile.nickName), ], style: TextStyle(color: Colors.black), ), ), ), ) .toList(), ).toList(), ), ), ], ), ); } } ================================================ FILE: example/lib/page/main/components/group.dart ================================================ import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin/entity/group_info_entity.dart'; /// 群组列表 class Group extends StatefulWidget { @override _GroupState createState() => _GroupState(); } class _GroupState extends State { /// 刷新指示器Key GlobalKey _refreshIndicatorKey = GlobalKey(); /// 数据结果对象 List _data = []; @override void initState() { super.initState(); TencentImPlugin.addListener(_imListener); SchedulerBinding.instance.addPostFrameCallback((_) { _refreshIndicatorKey.currentState.show(); }); } @override void dispose() { super.dispose(); TencentImPlugin.removeListener(_imListener); } /// IM监听器 _imListener(type, params) {} /// 刷新事件 Future _onRefresh() { return TencentImPlugin.getJoinedGroupList() .then((value) => this.setState(() => _data = value)); } @override Widget build(BuildContext context) { return RefreshIndicator( key: _refreshIndicatorKey, onRefresh: _onRefresh, child: ListView( children: ListTile.divideTiles( context: context, tiles: _data .map( (item) => ListTile( leading: CircleAvatar( backgroundImage: item.faceUrl == null || item.faceUrl == '' ? null : NetworkImage(item.faceUrl)), title: RichText( text: TextSpan( children: [ TextSpan(text: "${item.groupName}"), ], style: TextStyle(color: Colors.black), ), ), subtitle: Text(item.introduction ?? ""), ), ) .toList(), ).toList(), ), ); } } ================================================ FILE: example/lib/page/main/main.dart ================================================ import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:tencent_im_plugin_example/page/main/components/conversation.dart'; import 'package:tencent_im_plugin_example/page/main/components/friend.dart'; import 'package:tencent_im_plugin_example/page/main/components/group.dart'; import 'package:tencent_im_plugin/tencent_im_plugin.dart'; import 'package:tencent_im_plugin/entity/group_info_entity.dart'; import 'package:tencent_im_plugin/entity/friend_add_application_entity.dart'; import 'package:tencent_im_plugin/enums/group_type_enum.dart'; import 'package:tencent_im_plugin/enums/friend_type_enum.dart'; import 'package:tencent_im_plugin/message_node/text_message_node.dart'; /// 用户主页 class Main extends StatefulWidget { @override _MainState createState() => _MainState(); } class _MainState extends State

{ /// 当前页面下标 int _index = 0; /// 页面控制器 PageController _pageController = PageController(); @override void initState() { super.initState(); } /// 页面改变事件 _onPageChange(index) { _pageController.jumpToPage(index); this.setState(() { _index = index; }); } /// 菜单点击事件 _onMenuClick(int value) async { if (value == 0) { this._startConversation(); } else if (value == 1) { this._startGroupChat(); } else if (value == 2) { this._startAddFriend(); } } /// 发起会话 void _startConversation() async { String text = ""; var result = await this._showDialog( "发起会话", TextField( onChanged: (_text) => text = _text, decoration: InputDecoration(hintText: "请输入用户ID"), ), ); // 执行操作 if (result && text.trim() != '') { TencentImPlugin.sendMessage(node: TextMessageNode(content: "发起对话"), receiver: text); } } /// 开启群聊 void _startGroupChat() async { String text = ""; GroupTypeEnum type; var result = await this._showDialog( "创建群聊", Column( children: [ TextField( onChanged: (_text) => text = _text, decoration: InputDecoration(hintText: "请输入群名称"), ), GroupSelect(title: "群类型", values: GroupTypeEnum.values, onChanged: (newType) => type = newType), ], ), ); if (result && text != '' && type != null) { String id = await TencentImPlugin.createGroup(info: GroupInfoEntity.create(groupName: text, groupType: type)); Fluttertoast.showToast(msg: "群聊创建成功,群ID:$id"); } } /// 添加好友 void _startAddFriend() async { String text = ""; var result = await this._showDialog( "添加好友", TextField( onChanged: (_text) => text = _text, decoration: InputDecoration(hintText: "请输入用户ID"), ), ); // 执行操作 if (result && text.trim() != '') { TencentImPlugin.addFriend(info: FriendAddApplicationEntity(userID: text, addType: FriendTypeEnum.Both)).then((res) { Fluttertoast.showToast(msg: "好友申请发送成功!"); }).catchError((e) { Fluttertoast.showToast(msg: "好友申请发送失败!"); }); } } /// 显示对话框 /// [title] 标题 /// [child] 内容 Future _showDialog(String title, Widget child) { return showDialog( context: context, builder: (BuildContext context) => AlertDialog( title: Text(title), content: child, actions: [ OutlinedButton( child: Text("取消"), onPressed: () => Navigator.pop(context, false), ), OutlinedButton( child: Text("确定"), onPressed: () => Navigator.pop(context, true), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("主页"), actions: [ PopupMenuButton( onSelected: _onMenuClick, itemBuilder: (BuildContext context) => >[ PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [Text('发起对话')], ), value: 0, ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [Text('创建群聊')], ), value: 1, ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [Text('添加好友')], ), value: 2, ), ], ), ], ), body: Column( children: [ Expanded( child: PageView( onPageChanged: _onPageChange, controller: _pageController, children: [ Conversation(), Group(), Friend(), ], ), ), BottomNavigationBar( currentIndex: _index, items: [ BottomNavigationBarItem(icon: Icon(Icons.message), label: "会话"), BottomNavigationBarItem(icon: Icon(Icons.supervisor_account), label: "群组"), BottomNavigationBarItem(icon: Icon(Icons.account_box), label: "好友"), ], onTap: _onPageChange, ), ], ), ); } } /// 组选择 class GroupSelect extends StatefulWidget { /// 标签 final String title; /// 值列表 final List values; /// 改变事件 final ValueChanged onChanged; const GroupSelect({ Key key, @required this.title, @required this.values, @required this.onChanged, }) : super(key: key); @override _GroupSelectState createState() => _GroupSelectState(); } class _GroupSelectState extends State { /// 当前选择值 T _value; @override Widget build(BuildContext context) { return DropdownButton( hint: Text(widget.title), items: List.generate( widget.values.length, (index) { T item = widget.values[index]; return DropdownMenuItem( value: item, child: Text("${item.toString()}"), ); }, ), value: _value, elevation: 1, onChanged: (newType) { if (widget.onChanged != null) widget.onChanged(newType); this._value = newType; if (this.mounted) this.setState(() {}); }, ); } } ================================================ FILE: example/lib/utils/GenerateTestUserSig.dart ================================================ library generate_test_im_usersig; import 'dart:convert'; import 'dart:io'; import 'package:crypto/crypto.dart'; import 'package:flutter/material.dart'; ///生成腾讯云即时通信测试用userSig /// class GenerateTestUserSig { GenerateTestUserSig({@required this.sdkappid, @required this.key}); int sdkappid; String key; ///生成UserSig String genSig({ @required String identifier, @required int expire, List userBuf, }) { int currTime = _getCurrentTime(); String sig = ''; Map sigDoc = new Map(); sigDoc.addAll({ "TLS.ver": "2.0", "TLS.identifier": identifier, "TLS.sdkappid": this.sdkappid, "TLS.expire": expire, "TLS.time": currTime, }); sig = _hmacsha256( identifier: identifier, currTime: currTime, expire: expire, ); sigDoc['TLS.sig'] = sig; String jsonStr = json.encode(sigDoc); List compress = zlib.encode(utf8.encode(jsonStr)); return _escape(content: base64.encode(compress)); } int _getCurrentTime() { return (new DateTime.now().millisecondsSinceEpoch / 1000).floor(); } String _hmacsha256({ @required String identifier, @required int currTime, @required int expire, }) { int sdkappid = this.sdkappid; String contentToBeSigned = "TLS.identifier:$identifier\nTLS.sdkappid:$sdkappid\nTLS.time:$currTime\nTLS.expire:$expire\n"; Hmac hmacSha256 = new Hmac(sha256, utf8.encode(this.key)); Digest hmacSha256Digest = hmacSha256.convert(utf8.encode(contentToBeSigned)); return base64.encode(hmacSha256Digest.bytes); } String _escape({ @required String content, }) { return content .replaceAll('\+', '*') .replaceAll('\/', '-') .replaceAll('=', '_'); } } ================================================ FILE: example/pubspec.yaml ================================================ name: tencent_im_plugin_example description: Demonstrates how to use the tencent_im_plugin plugin. publish_to: 'none' environment: sdk: ">=2.1.0 <3.0.0" dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 # 图片选择(https://pub.dev/packages/image_picker) image_picker: ^0.7.4 # 视频缩略图获取(https://pub.dev/packages/video_thumbnail) video_thumbnail: ^0.3.3 # 路径管理(https://pub.dev/packages/path_provider) path_provider: ^2.0.1 # 视频播放器和信息获取(https://pub.flutter-io.cn/packages/video_player) video_player: ^2.1.1 # 群提示 fluttertoast: ^8.0.7 dev_dependencies: platform: ^3.1.0 flutter_test: sdk: flutter tencent_im_plugin: path: ../ # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter. flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. # For details regarding adding assets from package dependencies, see # https://flutter.dev/assets-and-images/#from-packages # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: # fonts: # - family: Schyler # fonts: # - asset: fonts/Schyler-Regular.ttf # - asset: fonts/Schyler-Italic.ttf # style: italic # - family: Trajan Pro # fonts: # - asset: fonts/TrajanPro.ttf # - asset: fonts/TrajanPro_Bold.ttf # weight: 700 # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages ================================================ FILE: example/test/widget_test.dart ================================================ // This is a basic Flutter widget test. // // To perform an interaction with a widget in your test, use the WidgetTester // utility that Flutter provides. For example, you can send tap and scroll // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tencent_im_plugin_example/main.dart'; void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(MyApp()); // Verify that platform version is retrieved. expect( find.byWidgetPredicate( (Widget widget) => widget is Text && widget.data.startsWith('Running on:'), ), findsOneWidget, ); }); } ================================================ FILE: ios/.gitignore ================================================ .idea/ .vagrant/ .sconsign.dblite .svn/ .DS_Store *.swp profile DerivedData/ build/ GeneratedPluginRegistrant.h GeneratedPluginRegistrant.m .generated/ *.pbxuser *.mode1v3 *.mode2v3 *.perspectivev3 !default.pbxuser !default.mode1v3 !default.mode2v3 !default.perspectivev3 xcuserdata *.moved-aside *.pyc *sync/ Icon? .tags* /Flutter/Generated.xcconfig /Flutter/flutter_export_environment.sh ================================================ FILE: ios/Assets/.gitkeep ================================================ ================================================ FILE: ios/Classes/SwiftTencentImPlugin.swift ================================================ import Flutter import UIKit import HandyJSON import ImSDK_Plus public class SwiftTencentImPlugin: NSObject, FlutterPlugin { public static var channel: FlutterMethodChannel?; /* 下面是监听器列表,由于局部变量的监听器对象不会触发,所以提取为全局对象 */ /// SDK 监听器 private var customSdkListener = CustomSDKListener(); /// 消息监听器 private var customAdvancedMsgListener = CustomAdvancedMsgListener(); /// 会话监听器 private var customConversationListener = CustomConversationListener(); /// 群组监听器 private var customGroupListener = CustomGroupListener(); /// 关系链相关监听器 private var customFriendshipListener = CustomFriendshipListener(); /// 信令监听器 private var customSignalingListener = CustomSignalingListener(); /// Apns离线推送监听器 private var customAPNSListener = CustomAPNSListener(); public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "tencent_im_plugin", binaryMessenger: registrar.messenger()) let instance = SwiftTencentImPlugin() SwiftTencentImPlugin.channel = channel; registrar.addMethodCallDelegate(instance, channel: channel) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "initSDK": self.`initSDK`(call: call, result: result) break case "unInitSDK": self.unInitSDK(call: call, result: result) break case "getVersion": self.getVersion(call: call, result: result) break case "getServerTime": self.getServerTime(call: call, result: result) break case "login": self.login(call: call, result: result) break case "logout": self.logout(call: call, result: result) break case "getLoginStatus": self.getLoginStatus(call: call, result: result) break case "getLoginUser": self.getLoginUser(call: call, result: result) break case "invite": self.invite(call: call, result: result) break case "inviteInGroup": self.inviteInGroup(call: call, result: result) break case "cancel": self.cancel(call: call, result: result) break case "accept": self.accept(call: call, result: result) break case "reject": self.reject(call: call, result: result) break case "getSignalingInfo": self.getSignalingInfo(call: call, result: result) break case "addInvitedSignaling": self.addInvitedSignaling(call: call, result: result) break case "sendMessage": self.sendMessage(call: call, result: result); break; case "resendMessage": self.resendMessage(call: call, result: result); break; case "revokeMessage": self.revokeMessage(call: call, result: result); break; case "getC2CHistoryMessageList": self.getC2CHistoryMessageList(call: call, result: result); break; case "getGroupHistoryMessageList": self.getGroupHistoryMessageList(call: call, result: result); break; case "getHistoryMessageList": self.getHistoryMessageList(call: call, result: result); break; case "markC2CMessageAsRead": self.markC2CMessageAsRead(call: call, result: result); break; case "markGroupMessageAsRead": self.markGroupMessageAsRead(call: call, result: result); break; case "deleteMessageFromLocalStorage": self.deleteMessageFromLocalStorage(call: call, result: result); break; case "deleteMessages": self.deleteMessages(call: call, result: result); break; case "insertGroupMessageToLocalStorage": self.insertGroupMessageToLocalStorage(call: call, result: result); break; case "insertC2CMessageToLocalStorage": self.insertC2CMessageToLocalStorage(call: call, result: result); break; case "downloadVideo": self.downloadVideo(call: call, result: result); break; case "downloadVideoThumbnail": self.downloadVideoThumbnail(call: call, result: result); break; case "downloadSound": self.downloadSound(call: call, result: result); break; case "downloadFile": self.downloadFile(call: call, result: result); break; case "setMessageLocalCustomStr": self.setMessageLocalCustomStr(call: call, result: result); break; case "setMessageLocalCustomInt": self.setMessageLocalCustomInt(call: call, result: result); break; case "findMessages": self.findMessages(call: call, result: result); break; case "createGroup": self.createGroup(call: call, result: result); break; case "joinGroup": self.joinGroup(call: call, result: result); break; case "quitGroup": self.quitGroup(call: call, result: result); break; case "dismissGroup": self.dismissGroup(call: call, result: result); break; case "getJoinedGroupList": self.getJoinedGroupList(call: call, result: result); break; case "getGroupsInfo": self.getGroupsInfo(call: call, result: result); break; case "setGroupInfo": self.setGroupInfo(call: call, result: result); break; case "searchGroups": self.searchGroups(call: call, result: result); break; case "searchGroupMembers": self.searchGroupMembers(call: call, result: result); break; case "setGroupReceiveMessageOpt": self.setGroupReceiveMessageOpt(call: call, result: result); break; case "setC2CReceiveMessageOpt": self.setC2CReceiveMessageOpt(call: call, result: result); break; case "getC2CReceiveMessageOpt": self.getC2CReceiveMessageOpt(call: call, result: result); break; case "initGroupAttributes": self.initGroupAttributes(call: call, result: result); break; case "setGroupAttributes": self.setGroupAttributes(call: call, result: result); break; case "deleteGroupAttributes": self.deleteGroupAttributes(call: call, result: result); break; case "getGroupAttributes": self.getGroupAttributes(call: call, result: result); break; case "getGroupOnlineMemberCount": self.getGroupOnlineMemberCount(call: call, result: result); break; case "getGroupMemberList": self.getGroupMemberList(call: call, result: result); break; case "getGroupMembersInfo": self.getGroupMembersInfo(call: call, result: result); break; case "setGroupMemberInfo": self.setGroupMemberInfo(call: call, result: result); break; case "muteGroupMember": self.muteGroupMember(call: call, result: result); break; case "inviteUserToGroup": self.inviteUserToGroup(call: call, result: result); break; case "kickGroupMember": self.kickGroupMember(call: call, result: result); break; case "setGroupMemberRole": self.setGroupMemberRole(call: call, result: result); break; case "transferGroupOwner": self.transferGroupOwner(call: call, result: result); break; case "getGroupApplicationList": self.getGroupApplicationList(call: call, result: result); break; case "acceptGroupApplication": self.acceptGroupApplication(call: call, result: result); break; case "refuseGroupApplication": self.refuseGroupApplication(call: call, result: result); break; case "setGroupApplicationRead": self.setGroupApplicationRead(call: call, result: result); break; case "getConversationList": self.getConversationList(call: call, result: result); break; case "getConversation": self.getConversation(call: call, result: result); break; case "deleteConversation": self.deleteConversation(call: call, result: result); break; case "setConversationDraft": self.setConversationDraft(call: call, result: result); break; case "pinConversation": self.pinConversation(call: call, result: result); break; case "getTotalUnreadMessageCount": self.getTotalUnreadMessageCount(call: call, result: result); break; case "getUsersInfo": self.getUsersInfo(call: call, result: result); break; case "setSelfInfo": self.setSelfInfo(call: call, result: result); break; case "addToBlackList": self.addToBlackList(call: call, result: result); break; case "deleteFromBlackList": self.deleteFromBlackList(call: call, result: result); break; case "getBlackList": self.getBlackList(call: call, result: result); break; case "setOfflinePushConfig": self.setOfflinePushConfig(call: call, result: result); break; case "setUnreadBadge": self.setUnreadBadge(call: call, result: result); break; case "getFriendList": self.getFriendList(call: call, result: result); break; case "getFriendsInfo": self.getFriendsInfo(call: call, result: result); break; case "setFriendInfo": self.setFriendInfo(call: call, result: result); break; case "addFriend": self.addFriend(call: call, result: result); break; case "deleteFromFriendList": self.deleteFromFriendList(call: call, result: result); break; case "checkFriend": self.checkFriend(call: call, result: result); break; case "getFriendApplicationList": self.getFriendApplicationList(call: call, result: result); break; case "acceptFriendApplication": self.acceptFriendApplication(call: call, result: result); break; case "refuseFriendApplication": self.refuseFriendApplication(call: call, result: result); break; case "deleteFriendApplication": self.deleteFriendApplication(call: call, result: result); break; case "setFriendApplicationRead": self.setFriendApplicationRead(call: call, result: result); break; case "createFriendGroup": self.createFriendGroup(call: call, result: result); break; case "getFriendGroups": self.getFriendGroups(call: call, result: result); break; case "deleteFriendGroup": self.deleteFriendGroup(call: call, result: result); break; case "renameFriendGroup": self.renameFriendGroup(call: call, result: result); break; case "addFriendsToFriendGroup": self.addFriendsToFriendGroup(call: call, result: result); break; case "deleteFriendsFromFriendGroup": self.deleteFriendsFromFriendGroup(call: call, result: result); break; default: result(FlutterMethodNotImplemented); } } /** * 初始化腾讯云IM */ public func `initSDK`(call: FlutterMethodCall, result: @escaping FlutterResult) { let logPrintLevel = ((call.arguments as! [String: Any])["logPrintLevel"]) as? Int; if let appid = CommonUtils.getParam(call: call, result: result, param: "appid") as? String { // 初始化SDK配置 let sdkConfig = V2TIMSDKConfig(); if logPrintLevel != nil { sdkConfig.logLevel = V2TIMLogLevel.init(rawValue: logPrintLevel!)!; } V2TIMManager.sharedInstance().initSDK((appid as NSString).intValue, config: sdkConfig, listener: customSdkListener) // 绑定消息监听 V2TIMManager.sharedInstance()?.addAdvancedMsgListener(listener: customAdvancedMsgListener) // 绑定会话监听 V2TIMManager.sharedInstance().setConversationListener(customConversationListener) // 绑定群监听 V2TIMManager.sharedInstance().setGroupListener(customGroupListener) // 绑定关系链监听 V2TIMManager.sharedInstance().setFriendListener(customFriendshipListener) // 绑定信令监听 V2TIMManager.sharedInstance().addSignalingListener(listener: customSignalingListener) // 绑定APNS监听 V2TIMManager.sharedInstance().setAPNSListener(customAPNSListener) result(nil); } } /// 反初始化 public func unInitSDK(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().unInitSDK(); V2TIMManager.sharedInstance()?.removeAdvancedMsgListener(listener: customAdvancedMsgListener) V2TIMManager.sharedInstance()?.removeSignalingListener(listener: customSignalingListener) result(nil); } /// 获得SDK版本 public func getVersion(call: FlutterMethodCall, result: @escaping FlutterResult) { result(V2TIMManager.sharedInstance()?.getVersion()!); } /// 获取服务器当前时间 public func getServerTime(call: FlutterMethodCall, result: @escaping FlutterResult) { result(V2TIMManager.sharedInstance()?.getServerTime()); } /// 登录 func login(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String, let userSig = CommonUtils.getParam(call: call, result: result, param: "userSig") as? String { V2TIMManager.sharedInstance().login(userID, userSig: userSig, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 登出 public func logout(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance()?.logout({ result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } /// 获得登录状态 public func getLoginStatus(call: FlutterMethodCall, result: @escaping FlutterResult) { result(V2TIMManager.sharedInstance().getLoginStatus().rawValue); } /// 获得当前登录用户 public func getLoginUser(call: FlutterMethodCall, result: @escaping FlutterResult) { result(V2TIMManager.sharedInstance()?.getLoginUser()); } /// 邀请某个人 public func invite(call: FlutterMethodCall, result: @escaping FlutterResult) { if let invitee = CommonUtils.getParam(call: call, result: result, param: "invitee") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? String, let onlineUserOnly = CommonUtils.getParam(call: call, result: result, param: "onlineUserOnly") as? Bool, let offlinePushInfo = CommonUtils.getParam(call: call, result: result, param: "offlinePushInfo") as? String, let timeout = CommonUtils.getParam(call: call, result: result, param: "timeout") as? Int32 { result(V2TIMManager.sharedInstance().invite(invitee, data: data, onlineUserOnly: onlineUserOnly, offlinePushInfo: CustomOfflinePushInfoEntity.init(jsonStr: offlinePushInfo), timeout: timeout, succ: { () -> Void in }, fail: { (code: Int32, desc: Optional) -> Void in })) } } /// 邀请群内的某些人 public func inviteInGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? String, let inviteeList = CommonUtils.getParam(call: call, result: result, param: "inviteeList") as? String, let onlineUserOnly = CommonUtils.getParam(call: call, result: result, param: "onlineUserOnly") as? Bool, let timeout = CommonUtils.getParam(call: call, result: result, param: "timeout") as? Int32 { // 邀请 result(V2TIMManager.sharedInstance().invite(inGroup: groupID, inviteeList: inviteeList.split(separator: ","), data: data, onlineUserOnly: onlineUserOnly, timeout: timeout, succ: { () -> Void in }, fail: { (code: Int32, desc: Optional) -> Void in })) } } /// 邀请方取消邀请 public func cancel(call: FlutterMethodCall, result: @escaping FlutterResult) { if let inviteID = CommonUtils.getParam(call: call, result: result, param: "inviteID") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? String { V2TIMManager.sharedInstance().cancel(inviteID, data: data, succ: { () -> Void in result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 接收方接收邀请 public func accept(call: FlutterMethodCall, result: @escaping FlutterResult) { if let inviteID = CommonUtils.getParam(call: call, result: result, param: "inviteID") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? String { V2TIMManager.sharedInstance().accept(inviteID, data: data, succ: { () -> Void in result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 接收方拒绝邀请 public func reject(call: FlutterMethodCall, result: @escaping FlutterResult) { if let inviteID = CommonUtils.getParam(call: call, result: result, param: "inviteID") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? String { V2TIMManager.sharedInstance().reject(inviteID, data: data, succ: { () -> Void in result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 获得信令信息 public func getSignalingInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let messageStr = CommonUtils.getParam(call: call, result: result, param: "message") as? String { TencentImUtils.getMessageByFindMessageEntity(json: messageStr, succ: { (messages: V2TIMMessage?) in result(JsonUtil.toJson(CustomSignalingInfoEntity.getDict(info: V2TIMManager.sharedInstance().getSignallingInfo(messages!)))); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 添加邀请信令(可以用于群离线推送消息触发的邀请信令) public func addInvitedSignaling(call: FlutterMethodCall, result: @escaping FlutterResult) { if let info = CommonUtils.getParam(call: call, result: result, param: "info") as? String { V2TIMManager.sharedInstance().addInvitedSignaling(CustomSignalingInfoEntity.init(jsonStr: info), succ: { () -> Void in result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 发送消息 private func sendMessage(call: FlutterMethodCall, result: @escaping FlutterResult) { if let nodeStr = CommonUtils.getParam(call: call, result: result, param: "node") as? String { // 将节点信息解析 let node = JsonUtil.getDictionaryFromJSONString(jsonString: nodeStr); // 获得发送消息体 let message: V2TIMMessage = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: node["nodeType"] as! Int).messageNodeInterface().getV2TIMMessage(params: node); self._sendMessage(message: message, call: call, result: result); } } /// 重发消息 public func resendMessage(call: FlutterMethodCall, result: @escaping FlutterResult) { if let messageStr = CommonUtils.getParam(call: call, result: result, param: "message") as? String { TencentImUtils.getMessageByFindMessageEntity(json: messageStr, succ: { (message: V2TIMMessage?) in self._sendMessage(message: message!, call: call, result: result); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 发送消息 /// - Parameters: /// - message: 消息对象 /// - call: Flutter 方法调用对象 /// - result: Flutter 返回结果对象 private func _sendMessage(message: V2TIMMessage, call: FlutterMethodCall, result: @escaping FlutterResult) { let receiver = ((call.arguments as! [String: Any])["receiver"]) as? String; let groupID = ((call.arguments as! [String: Any])["groupID"]) as? String; let localCustomInt = ((call.arguments as! [String: Any])["localCustomInt"]) as? Int32; let localCustomStr = ((call.arguments as! [String: Any])["localCustomStr"]) as? String; let offlinePushInfo = ((call.arguments as! [String: Any])["offlinePushInfo"]) as? String; if let ol = CommonUtils.getParam(call: call, result: result, param: "ol") as? Bool, let priority = CommonUtils.getParam(call: call, result: result, param: "priority") as? Int { if localCustomInt != nil { message.localCustomInt = localCustomInt!; } if localCustomStr != nil { message.localCustomData = localCustomStr!.data(using: .utf8); } var msgId: [String?] = [nil]; // 成功回调 let _sendSuccess = { TencentImUtils.getMessageByFindMessageEntity(dict: ["msgId": msgId[0]], succ: { (message: V2TIMMessage?) -> () in SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageSendSucc, params: MessageEntity.init(message: message!)) }, fail: { (int32: Int32, s: String?) -> () in }) }; // 进度回调 let _progress = { (p: UInt32) in SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageSendProgress, params: [ "msgId": msgId[0]!, "progress": p, ]) }; // 失败回调 let _fail = { (code: Int32, desc: Optional) -> Void in SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageSendFail, params: [ "msgId": msgId[0]!, "code": code, "desc": desc, ]) }; // 发送消息 msgId[0] = V2TIMManager.sharedInstance().send(message, receiver: receiver, groupID: groupID, priority: V2TIMMessagePriority.init(rawValue: priority)!, onlineUserOnly: ol, offlinePushInfo: CustomOfflinePushInfoEntity.init(jsonStr: offlinePushInfo), progress: _progress, succ: _sendSuccess, fail: _fail) result(msgId[0]); } } /// 撤回消息 public func revokeMessage(call: FlutterMethodCall, result: @escaping FlutterResult) { if let messageStr = CommonUtils.getParam(call: call, result: result, param: "message") as? String { TencentImUtils.getMessageByFindMessageEntity(json: messageStr, succ: { (messages: V2TIMMessage?) in V2TIMManager.sharedInstance().revokeMessage(messages!, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 获得单聊历史记录 public func getC2CHistoryMessageList(call: FlutterMethodCall, result: @escaping FlutterResult) { let lastMsg = ((call.arguments as! [String: Any])["lastMsg"]) as? String; if let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String, let count = CommonUtils.getParam(call: call, result: result, param: "count") as? Int32 { // 返回结果对象 let resultCallBack = { (messages: [V2TIMMessage]?) in var resultData: [MessageEntity] = []; for item in messages! { resultData.append(MessageEntity.init(message: item)); } result(JsonUtil.toJson(resultData)); }; // 根据消息对象是否为null进行不同的操作 if lastMsg == nil { V2TIMManager.sharedInstance().getC2CHistoryMessageList(userID, count: count, lastMsg: nil, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result)) } else { TencentImUtils.getMessageByFindMessageEntity(json: lastMsg!, succ: { (messages: V2TIMMessage?) in V2TIMManager.sharedInstance().getC2CHistoryMessageList(userID, count: count, lastMsg: messages!, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } } /// 获得群聊历史记录 public func getGroupHistoryMessageList(call: FlutterMethodCall, result: @escaping FlutterResult) { let lastMsg = ((call.arguments as! [String: Any])["lastMsg"]) as? String; if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let count = CommonUtils.getParam(call: call, result: result, param: "count") as? Int32 { // 返回结果对象 let resultCallBack = { (messages: [V2TIMMessage]?) in var resultData: [MessageEntity] = []; for item in messages! { resultData.append(MessageEntity.init(message: item)); } result(JsonUtil.toJson(resultData)); }; // 根据消息对象是否为null进行不同的操作 if lastMsg == nil { V2TIMManager.sharedInstance().getGroupHistoryMessageList(groupID, count: count, lastMsg: nil, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result)) } else { TencentImUtils.getMessageByFindMessageEntity(json: lastMsg!, succ: { (messages: V2TIMMessage?) in V2TIMManager.sharedInstance().getGroupHistoryMessageList(groupID, count: count, lastMsg: messages!, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } } /// 获得历史记录 public func getHistoryMessageList(call: FlutterMethodCall, result: @escaping FlutterResult) { let lastMsg = ((call.arguments as! [String: Any])["lastMsg"]) as? String; let groupID = ((call.arguments as! [String: Any])["groupID"]) as? String; let userID = ((call.arguments as! [String: Any])["userID"]) as? String; if let type = CommonUtils.getParam(call: call, result: result, param: "type") as? Int, let count = CommonUtils.getParam(call: call, result: result, param: "count") as? Int32 { // 返回结果对象 let resultCallBack = { (messages: [V2TIMMessage]?) in var resultData: [MessageEntity] = []; for item in messages! { resultData.append(MessageEntity.init(message: item)); } result(JsonUtil.toJson(resultData)); }; // 根据消息对象是否为null进行不同的操作 let opt = V2TIMMessageListGetOption(); if let v = userID { opt.userID = v; } if let v = groupID { opt.groupID = v; } opt.count = UInt(count); opt.getType = V2TIMMessageGetType.init(rawValue: type)!; if lastMsg == nil { V2TIMManager.sharedInstance()?.getHistoryMessageList(opt, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result)) } else { TencentImUtils.getMessageByFindMessageEntity(json: lastMsg!, succ: { (messages: V2TIMMessage?) in if messages != nil { opt.lastMsg = messages!; } V2TIMManager.sharedInstance()?.getHistoryMessageList(opt, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } } /// 设置单聊已读 public func markC2CMessageAsRead(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String { V2TIMManager.sharedInstance().markC2CMessage(asRead: userID, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 设置群聊已读 public func markGroupMessageAsRead(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String { V2TIMManager.sharedInstance().markGroupMessage(asRead: groupID, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 删除本地消息 public func deleteMessageFromLocalStorage(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (messages: V2TIMMessage?) in V2TIMManager.sharedInstance().deleteMessage(fromLocalStorage: messages!, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 删除本地及漫游消息 public func deleteMessages(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String { let arr = JsonUtil.getArrayFromJSONString(jsonString: message); TencentImUtils.getMessageByFindMessageEntity(dict: arr as! [[String: Any]], succ: { (messages: [V2TIMMessage]?) in V2TIMManager.sharedInstance().delete(messages!, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 向群组消息列表中添加一条消息 public func insertGroupMessageToLocalStorage(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let sender = CommonUtils.getParam(call: call, result: result, param: "sender") as? String, let nodeStr = CommonUtils.getParam(call: call, result: result, param: "node") as? String { // 将节点信息解析 let node = JsonUtil.getDictionaryFromJSONString(jsonString: nodeStr); // 获得消息体 let message: V2TIMMessage = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: node["nodeType"] as! Int).messageNodeInterface().getV2TIMMessage(params: node); // 添加到列表 V2TIMManager.sharedInstance().insertGroupMessage(toLocalStorage: message, to: groupID, sender: sender, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 向群组消息列表中添加一条消息 public func insertC2CMessageToLocalStorage(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String, let sender = CommonUtils.getParam(call: call, result: result, param: "sender") as? String, let nodeStr = CommonUtils.getParam(call: call, result: result, param: "node") as? String { // 将节点信息解析 let node = JsonUtil.getDictionaryFromJSONString(jsonString: nodeStr); // 获得消息体 let message: V2TIMMessage = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: node["nodeType"] as! Int).messageNodeInterface().getV2TIMMessage(params: node); // 添加到列表 V2TIMManager.sharedInstance().insertC2CMessage(toLocalStorage: message, to: userID, sender: sender, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 下载视频 public func downloadVideo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String, let path = CommonUtils.getParam(call: call, result: result, param: "path") as? String { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (msg: V2TIMMessage?) in msg?.videoElem?.downloadVideo(path, progress: { curSize, totalSize in SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [ "msgId": msg!.msgID!, "currentSize": curSize, "totalSize": totalSize, "type": DownloadType.Video.rawValue, ]) }, succ: { result(path); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 下载视频缩略图 public func downloadVideoThumbnail(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String, let path = CommonUtils.getParam(call: call, result: result, param: "path") as? String { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (msg: V2TIMMessage?) in msg?.videoElem?.downloadSnapshot(path, progress: { curSize, totalSize in SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [ "msgId": msg!.msgID!, "currentSize": curSize, "totalSize": totalSize, "type": DownloadType.VideoThumbnail.rawValue, ]) }, succ: { result(path); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 下载语音 public func downloadSound(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String, let path = CommonUtils.getParam(call: call, result: result, param: "path") as? String { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (msg: V2TIMMessage?) in msg?.soundElem?.downloadSound(path, progress: { curSize, totalSize in SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [ "msgId": msg!.msgID!, "currentSize": curSize, "totalSize": totalSize, "type": DownloadType.Sound.rawValue, ]) }, succ: { result(path); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 下载文件 public func downloadFile(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String, let path = CommonUtils.getParam(call: call, result: result, param: "path") as? String { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (msg: V2TIMMessage?) in msg?.fileElem?.downloadFile(path, progress: { curSize, totalSize in SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [ "msgId": msg!.msgID!, "currentSize": curSize, "totalSize": totalSize, "type": DownloadType.File.rawValue, ]) }, succ: { result(path); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 设置消息本地Str public func setMessageLocalCustomStr(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? String { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (msg: V2TIMMessage?) in msg!.localCustomData = data.data(using: .utf8)!; result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 设置消息本地Int public func setMessageLocalCustomInt(call: FlutterMethodCall, result: @escaping FlutterResult) { if let message = CommonUtils.getParam(call: call, result: result, param: "message") as? String, let data = CommonUtils.getParam(call: call, result: result, param: "data") as? Int32 { TencentImUtils.getMessageByFindMessageEntity(json: message, succ: { (msg: V2TIMMessage?) in msg!.localCustomInt = data; result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 查找消息列表 public func findMessages(call: FlutterMethodCall, result: @escaping FlutterResult) { if let messages = CommonUtils.getParam(call: call, result: result, param: "messages") as? String { TencentImUtils.getMessageByFindMessageEntity(dict: JsonUtil.getArrayFromJSONString(jsonString: messages) as! [[String: Any]], succ: { (ms: [V2TIMMessage]!) in var res: [MessageEntity] = []; for item in ms! { res.append(MessageEntity.init(message: item)); } result(JsonUtil.toJson(res)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 创建群 public func createGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { let memberList = ((call.arguments as! [String: Any])["memberList"]) as? String; if let info = CommonUtils.getParam(call: call, result: result, param: "info") as? String { // 初始化群创建群成员列表 var ms: [CustomCreateGroupMemberEntity]? = nil; if memberList != nil { ms = []; let array = JsonUtil.getArrayFromJSONString(jsonString: memberList!); for index in 0.. = [:] for item in array! { res[item.userID] = item.receiveOpt.rawValue } result(res); }, fail: TencentImUtils.returnErrorClosures(result: result)) } /// 初始化群属性,会清空原有的群属性列表 public func initGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let attributes = CommonUtils.getParam(call: call, result: result, param: "attributes") as? String { V2TIMManager.sharedInstance().initGroupAttributes(groupID, attributes: (JsonUtil.getDictionaryFromJSONString(jsonString: attributes) as! [String: String]), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 设置群属性 public func setGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let attributes = CommonUtils.getParam(call: call, result: result, param: "attributes") as? String { V2TIMManager.sharedInstance().setGroupAttributes(groupID, attributes: (JsonUtil.getDictionaryFromJSONString(jsonString: attributes) as! [String: String]), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 删除群属性 public func deleteGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) { let keys = ((call.arguments as! [String: Any])["keys"]) as? String; if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String { V2TIMManager.sharedInstance().deleteGroupAttributes(groupID, keys: keys?.components(separatedBy: ","), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获得群属性 public func getGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) { let keys = ((call.arguments as! [String: Any])["keys"]) as? String; if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String { V2TIMManager.sharedInstance().getGroupAttributes(groupID, keys: keys?.components(separatedBy: ","), succ: { dictionary in result(JsonUtil.toJson(dictionary!)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获得群在线人数 public func getGroupOnlineMemberCount(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String { V2TIMManager.sharedInstance().getGroupOnlineMemberCount(groupID, succ: { num in result(num); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获得群成员列表 public func getGroupMemberList(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let filter = CommonUtils.getParam(call: call, result: result, param: "filter") as? UInt32, let nextSeq = CommonUtils.getParam(call: call, result: result, param: "nextSeq") as? UInt64 { V2TIMManager.sharedInstance().getGroupMemberList(groupID, filter: filter, nextSeq: nextSeq, succ: { nextSeq, infos in result(JsonUtil.toJson(CustomGroupMemberInfoResultEntity.init(nextSeq: nextSeq, infos: infos!))); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获取指定的群成员资料 public func getGroupMembersInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let memberList = CommonUtils.getParam(call: call, result: result, param: "memberList") as? String { V2TIMManager.sharedInstance().getGroupMembersInfo(groupID, memberList: memberList.components(separatedBy: ","), succ: { infos in var resultData: [[String: Any]] = []; for item in infos! { resultData.append(CustomGroupMemberFullInfoEntity.getDict(info: item)) } result(JsonUtil.toJson(resultData)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获取指定的群成员资料 public func setGroupMemberInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let info = CommonUtils.getParam(call: call, result: result, param: "info") as? String { V2TIMManager.sharedInstance().setGroupMemberInfo(groupID, info: CustomGroupMemberFullInfoEntity.init(json: info), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 禁言 public func muteGroupMember(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String, let seconds = CommonUtils.getParam(call: call, result: result, param: "seconds") as? UInt32 { V2TIMManager.sharedInstance().muteGroupMember(groupID, member: userID, muteTime: seconds, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 邀请他人进群 public func inviteUserToGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let userList = CommonUtils.getParam(call: call, result: result, param: "userList") as? String { V2TIMManager.sharedInstance().inviteUser(toGroup: groupID, userList: userList.components(separatedBy: ","), succ: { infos in var resultData: [[String: Any]] = []; for item in infos! { resultData.append(CustomGroupMemberOperationResultEntity.getDict(info: item)) } result(JsonUtil.toJson(resultData)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 踢人 public func kickGroupMember(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let memberList = CommonUtils.getParam(call: call, result: result, param: "memberList") as? String, let reason = CommonUtils.getParam(call: call, result: result, param: "reason") as? String { V2TIMManager.sharedInstance().kickGroupMember(groupID, memberList: memberList.components(separatedBy: ","), reason: reason, succ: { infos in var resultData: [[String: Any]] = []; for item in infos! { resultData.append(CustomGroupMemberOperationResultEntity.getDict(info: item)) } result(JsonUtil.toJson(resultData)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 切换群成员角色 public func setGroupMemberRole(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String, let role = CommonUtils.getParam(call: call, result: result, param: "role") as? UInt32 { V2TIMManager.sharedInstance().setGroupMemberRole(groupID, member: userID, newRole: role, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 转让群主 public func transferGroupOwner(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupID = CommonUtils.getParam(call: call, result: result, param: "groupID") as? String, let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String { V2TIMManager.sharedInstance().transferGroupOwner(groupID, member: userID, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获取加群的申请列表 public func getGroupApplicationList(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().getGroupApplicationList({ info in result(JsonUtil.toJson(CustomGroupApplicationResultEntity.getDict(info: info!))); }, fail: TencentImUtils.returnErrorClosures(result: result)) } /// 同意某一条加群申请 public func acceptGroupApplication(call: FlutterMethodCall, result: @escaping FlutterResult) { if let application = CommonUtils.getParam(call: call, result: result, param: "application") as? String, let reason = CommonUtils.getParam(call: call, result: result, param: "reason") as? String { TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(json: application, succ: { (application: V2TIMGroupApplication?) -> () in V2TIMManager.sharedInstance().accept(application!, reason: reason, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 拒绝某一条加群申请 public func refuseGroupApplication(call: FlutterMethodCall, result: @escaping FlutterResult) { if let application = CommonUtils.getParam(call: call, result: result, param: "application") as? String, let reason = CommonUtils.getParam(call: call, result: result, param: "reason") as? String { TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(json: application, succ: { (application: V2TIMGroupApplication?) -> () in V2TIMManager.sharedInstance().refuse(application!, reason: reason, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 标记申请列表为已读 public func setGroupApplicationRead(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().setGroupApplicationRead({ result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } /// 获得会话列表 public func getConversationList(call: FlutterMethodCall, result: @escaping FlutterResult) { if let nextSeq = CommonUtils.getParam(call: call, result: result, param: "nextSeq") as? UInt64, let count = CommonUtils.getParam(call: call, result: result, param: "count") as? Int32 { V2TIMManager.sharedInstance().getConversationList(nextSeq, count: count, succ: { conversations, nextSeq, finished in result(JsonUtil.toJson(CustomConversationResultEntity.init(conversations: conversations!, nextSeq: nextSeq, finished: finished))); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获得会话 public func getConversation(call: FlutterMethodCall, result: @escaping FlutterResult) { if let conversationID = CommonUtils.getParam(call: call, result: result, param: "conversationID") as? String { V2TIMManager.sharedInstance().getConversation(conversationID, succ: { conversation in result(JsonUtil.toJson(CustomConversationEntity.getDict(info: conversation!))); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 删除会话 public func deleteConversation(call: FlutterMethodCall, result: @escaping FlutterResult) { if let conversationID = CommonUtils.getParam(call: call, result: result, param: "conversationID") as? String { V2TIMManager.sharedInstance().deleteConversation(conversationID, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 设置会话草稿 public func setConversationDraft(call: FlutterMethodCall, result: @escaping FlutterResult) { let draftText = ((call.arguments as! [String: Any])["draftText"]) as? String; if let conversationID = CommonUtils.getParam(call: call, result: result, param: "conversationID") as? String { V2TIMManager.sharedInstance().setConversationDraft(conversationID, draftText: draftText, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 会话置顶 public func pinConversation(call: FlutterMethodCall, result: @escaping FlutterResult) { if let conversationID = CommonUtils.getParam(call: call, result: result, param: "conversationID") as? String, let isPinned = CommonUtils.getParam(call: call, result: result, param: "isPinned") as? Bool { V2TIMManager.sharedInstance().pinConversation(conversationID, isPinned: isPinned, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获得会话总未读数 public func getTotalUnreadMessageCount(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().getTotalUnreadMessageCount({ number in result(number); }, fail: TencentImUtils.returnErrorClosures(result: result)) } /// 获得用户资料 public func getUsersInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().getUsersInfo(userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomUserEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 修改自己的资料 public func setSelfInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let info = CommonUtils.getParam(call: call, result: result, param: "info") as? String { V2TIMManager.sharedInstance().setSelfInfo(CustomUserEntity.init(json: info), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 添加用户到黑名单 public func addToBlackList(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().add(toBlackList: userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendOperationResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 从黑名单中删除 public func deleteFromBlackList(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().delete(fromBlackList: userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendOperationResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 获得黑名单列表 public func getBlackList(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().getBlackList({ infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendInfoEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)) } /// 设置离线推送 public func setOfflinePushConfig(call: FlutterMethodCall, result: @escaping FlutterResult) { if let token = CommonUtils.getParam(call: call, result: result, param: "token") as? String, let bussid = CommonUtils.getParam(call: call, result: result, param: "bussid") as? Int32, let tpns = CommonUtils.getParam(call: call, result: result, param: "tpns") as? Bool { let config = V2TIMAPNSConfig(); config.token = token.data(using: .utf8); config.businessID = bussid; config.isTPNSToken = tpns; V2TIMManager.sharedInstance().setAPNS(config, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)) } } /// 设置未读桌标 public func setUnreadBadge(call: FlutterMethodCall, result: @escaping FlutterResult) { if let number = CommonUtils.getParam(call: call, result: result, param: "number") as? UInt32 { CustomAPNSListener.number = number; result(nil); } } /// 获得好友列表 public func getFriendList(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().getFriendList({ infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendInfoEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } /// 获得指定好友信息 public func getFriendsInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().getFriendsInfo(userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendInfoResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 设置好友资料 public func setFriendInfo(call: FlutterMethodCall, result: @escaping FlutterResult) { if let info = CommonUtils.getParam(call: call, result: result, param: "info") as? String { V2TIMManager.sharedInstance().setFriendInfo(CustomFriendInfoEntity.init(json: info), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 添加好友 public func addFriend(call: FlutterMethodCall, result: @escaping FlutterResult) { if let info = CommonUtils.getParam(call: call, result: result, param: "info") as? String { V2TIMManager.sharedInstance().addFriend(CustomFriendAddApplicationEntity.init(json: info), succ: { info in result(JsonUtil.toJson(CustomFriendOperationResultEntity.getDict(info: info!))); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 删除好友 public func deleteFromFriendList(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String, let deleteType = CommonUtils.getParam(call: call, result: result, param: "deleteType") as? Int { V2TIMManager.sharedInstance().delete(fromFriendList: userIDList.components(separatedBy: ","), delete: V2TIMFriendType.init(rawValue: deleteType)!, succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendOperationResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 检查好友关系 public func checkFriend(call: FlutterMethodCall, result: @escaping FlutterResult) { if let userID = CommonUtils.getParam(call: call, result: result, param: "userID") as? String, let checkType = CommonUtils.getParam(call: call, result: result, param: "checkType") as? Int { V2TIMManager.sharedInstance().checkFriend([userID], check: V2TIMFriendType.init(rawValue: checkType)!, succ: { info in if info == nil || info?.count == 0 { result(nil) return; } result(JsonUtil.toJson(CustomFriendCheckResultEntity.getDict(info: info!.first!))); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 获得好友申请列表 public func getFriendApplicationList(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().getFriendApplicationList({ info in result(JsonUtil.toJson(CustomFriendApplicationResultEntity.getDict(info: info!))); }, fail: TencentImUtils.returnErrorClosures(result: result)); } /// 同意建立好友申请关系 public func acceptFriendApplication(call: FlutterMethodCall, result: @escaping FlutterResult) { if let application = CommonUtils.getParam(call: call, result: result, param: "application") as? String, let responseType = CommonUtils.getParam(call: call, result: result, param: "responseType") as? Int { TencentImUtils.getFriendApplicationByFindFriendApplicationEntity(json: application, succ: { (v2TIMFriendApplication: V2TIMFriendApplication?) -> () in V2TIMManager.sharedInstance().accept(v2TIMFriendApplication!, type: V2TIMFriendAcceptType.init(rawValue: responseType)!, succ: { info in result(JsonUtil.toJson(CustomFriendOperationResultEntity.getDict(info: info!))); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 拒绝建立好友申请关系 public func refuseFriendApplication(call: FlutterMethodCall, result: @escaping FlutterResult) { if let application = CommonUtils.getParam(call: call, result: result, param: "application") as? String { TencentImUtils.getFriendApplicationByFindFriendApplicationEntity(json: application, succ: { (v2TIMFriendApplication: V2TIMFriendApplication?) -> () in V2TIMManager.sharedInstance().refuse(v2TIMFriendApplication!, succ: { info in result(JsonUtil.toJson(CustomFriendOperationResultEntity.getDict(info: info!))); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 删除好友申请 public func deleteFriendApplication(call: FlutterMethodCall, result: @escaping FlutterResult) { if let application = CommonUtils.getParam(call: call, result: result, param: "application") as? String { TencentImUtils.getFriendApplicationByFindFriendApplicationEntity(json: application, succ: { (v2TIMFriendApplication: V2TIMFriendApplication?) -> () in V2TIMManager.sharedInstance().delete(v2TIMFriendApplication!, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 设置好友申请为已读 public func setFriendApplicationRead(call: FlutterMethodCall, result: @escaping FlutterResult) { V2TIMManager.sharedInstance().setFriendApplicationRead({ result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } /// 新建好友分组 public func createFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupName = CommonUtils.getParam(call: call, result: result, param: "groupName") as? String, let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().createFriendGroup(groupName, userIDList: userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendOperationResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 获得分组信息 public func getFriendGroups(call: FlutterMethodCall, result: @escaping FlutterResult) { let groupNameList = ((call.arguments as! [String: Any])["groupNameList"]) as? String; V2TIMManager.sharedInstance().getFriendGroupList(groupNameList?.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendGroupEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } /// 删除分组 public func deleteFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupNameList = CommonUtils.getParam(call: call, result: result, param: "groupNameList") as? String { V2TIMManager.sharedInstance().deleteFriendGroup(groupNameList.components(separatedBy: ","), succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 修改分组名称 public func renameFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let oldName = CommonUtils.getParam(call: call, result: result, param: "oldName") as? String, let newName = CommonUtils.getParam(call: call, result: result, param: "newName") as? String { V2TIMManager.sharedInstance().renameFriendGroup(oldName, newName: newName, succ: { result(nil); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 添加好友到分组 public func addFriendsToFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupName = CommonUtils.getParam(call: call, result: result, param: "groupName") as? String, let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().addFriends(toFriendGroup: groupName, userIDList: userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendOperationResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /// 从分组中删除好友 public func deleteFriendsFromFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) { if let groupName = CommonUtils.getParam(call: call, result: result, param: "groupName") as? String, let userIDList = CommonUtils.getParam(call: call, result: result, param: "userIDList") as? String { V2TIMManager.sharedInstance().deleteFriends(fromFriendGroup: groupName, userIDList: userIDList.components(separatedBy: ","), succ: { infos in var data: [[String: Any]] = []; for item in infos! { data.append(CustomFriendOperationResultEntity.getDict(info: item)); } result(JsonUtil.toJson(data)); }, fail: TencentImUtils.returnErrorClosures(result: result)); } } /** * 调用监听器 * * @param type 类型 * @param params 参数 */ public static func invokeListener(type: ListenerType, params: Any?) { var resultParams: [String: Any] = [:]; resultParams["type"] = type; if let p = params { resultParams["params"] = p; } SwiftTencentImPlugin.channel!.invokeMethod("onListener", arguments: JsonUtil.toJson(resultParams)); } } ================================================ FILE: ios/Classes/TencentImPlugin.h ================================================ #import @interface TencentImPlugin : NSObject @end ================================================ FILE: ios/Classes/TencentImPlugin.m ================================================ #import "TencentImPlugin.h" #if __has_include() #import #else // Support project import fallback if the generated compatibility header // is not copied when this plugin is created as a library. // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 #import "tencent_im_plugin-Swift.h" #endif @implementation TencentImPlugin + (void)registerWithRegistrar:(NSObject*)registrar { [SwiftTencentImPlugin registerWithRegistrar:registrar]; } @end ================================================ FILE: ios/Classes/entity/CustomConversationEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义会话实体 class CustomConversationEntity: V2TIMConversation { /// 根据对象获得字典对象 public static func getDict(info: V2TIMConversation) -> [String: Any] { var result: [String: Any] = [:]; result["conversationID"] = info.conversationID; result["type"] = info.type.rawValue; result["userID"] = info.userID; result["groupID"] = info.groupID; result["showName"] = info.showName; result["faceUrl"] = info.faceUrl; result["recvOpt"] = info.recvOpt.rawValue; result["groupType"] = info.groupType; result["unreadCount"] = info.unreadCount; result["lastMessage"] = info.lastMessage == nil ? nil : MessageEntity.init(message: info.lastMessage); result["draftText"] = info.draftText; result["draftText"] = info.draftText; result["draftTimestamp"] = info.draftTimestamp; result["pinned"] = info.isPinned; result["test"] = nil; if info.groupAtInfolist != nil { var groupAtInfoList: [[String: Any]] = []; for item in info.groupAtInfolist { groupAtInfoList.append(CustomGroupAtInfoEntity.getDict(info: item)); } result["groupAtInfoList"] = groupAtInfoList; } return result; } } ================================================ FILE: ios/Classes/entity/CustomConversationResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义会话结果实体 class CustomConversationResultEntity: NSObject { /// 下一次分页拉取的游标 var nextSeq: UInt64?; /// 是否拉取完毕 var finished: Bool?; /// 会话列表 var conversationList: [[String: Any]]?; required public override init() { } init(conversations: [V2TIMConversation], nextSeq: UInt64, finished: Bool) { super.init(); self.nextSeq = nextSeq; self.finished = finished; conversationList = []; for item in conversations { conversationList!.append(CustomConversationEntity.getDict(info: item)); } } } ================================================ FILE: ios/Classes/entity/CustomCreateGroupMemberEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群创建群成员实体 class CustomCreateGroupMemberEntity: V2TIMCreateGroupMemberInfo { required public override init() { } convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.userID = (dict["userID"] as? String); if dict["role"] != nil { self.role = (dict["role"] as! UInt32); } } } ================================================ FILE: ios/Classes/entity/CustomFriendAddApplicationEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus /// 好友申请实体 class CustomFriendAddApplicationEntity: V2TIMFriendAddApplication { convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.userID = (dict["userID"] as? String); self.friendRemark = (dict["friendRemark"] as? String); self.addWording = (dict["addWording"] as? String); self.addSource = (dict["addSource"] as? String); if dict["addType"] != nil { self.addType = V2TIMFriendType.init(rawValue: (dict["addType"] as! Int))! } } } ================================================ FILE: ios/Classes/entity/CustomFriendApplicationEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus /// 好友申请实体 class CustomFriendApplicationEntity: V2TIMFriendApplication { /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendApplication) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["nickname"] = info.nickName; result["faceUrl"] = info.faceUrl; result["addTime"] = info.addTime; result["addSource"] = info.addSource; result["addWording"] = info.addWording; result["type"] = info.type.rawValue; return result; } } ================================================ FILE: ios/Classes/entity/CustomFriendApplicationResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus /// 好友申请结果实体 class CustomFriendApplicationResultEntity: V2TIMFriendApplicationResult { /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendApplicationResult) -> [String: Any] { var result: [String: Any] = [:]; result["unreadCount"] = info.unreadCount; var friendApplicationList: [[String: Any]] = []; for item in info.applicationList { friendApplicationList.append(CustomFriendApplicationEntity.getDict(info: item as! V2TIMFriendApplication)) } result["friendApplicationList"] = friendApplicationList; return result; } } ================================================ FILE: ios/Classes/entity/CustomFriendCheckResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus /// 自定义好友检查结果实体 class CustomFriendCheckResultEntity : V2TIMFriendCheckResult{ /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendCheckResult) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["resultCode"] = info.resultCode; result["resultInfo"] = info.resultInfo; result["resultType"] = info.relationType.rawValue; return result; } } ================================================ FILE: ios/Classes/entity/CustomFriendGroupEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus /// 自定义好友分组实体 class CustomFriendGroupEntity: V2TIMFriendGroup { /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendGroup) -> [String: Any] { var result: [String: Any] = [:]; result["name"] = info.groupName; result["friendCount"] = info.userCount; result["friendIDList"] = info.friendList; return result; } } ================================================ FILE: ios/Classes/entity/CustomFriendInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义好友信息实体 class CustomFriendInfoEntity: V2TIMFriendInfo { convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.userID = (dict["userID"] as? String); self.friendRemark = (dict["friendRemark"] as? String); if dict["friendCustomInfo"] != nil { self.friendCustomInfo = [:]; for (k, v) in (dict["friendCustomInfo"] as! [String: String]) { self.friendCustomInfo[k] = v.data(using: .utf8) } } } /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendInfo) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["friendRemark"] = info.friendRemark; result["friendGroups"] = info.friendGroups; result["friendCustomInfo"] = info.friendCustomInfo; result["userProfile"] = CustomUserEntity.getDict(info: info.userFullInfo); return result; } } ================================================ FILE: ios/Classes/entity/CustomFriendInfoResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus class CustomFriendInfoResultEntity: V2TIMFriendInfoResult { /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendInfoResult) -> [String: Any] { var result: [String: Any] = [:]; result["resultCode"] = info.resultCode; result["resultInfo"] = info.resultInfo; result["relation"] = info.relation.rawValue; result["friendInfo"] = CustomFriendInfoEntity.getDict(info: info.friendInfo); return result; } } ================================================ FILE: ios/Classes/entity/CustomFriendOperationResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 好友操作结果实体 class CustomFriendOperationResultEntity: V2TIMFriendOperationResult { /// 根据对象获得字典对象 public static func getDict(info: V2TIMFriendOperationResult) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["resultCode"] = info.resultCode; result["resultInfo"] = info.resultInfo; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupApplicationEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群申请实体 class CustomGroupApplicationEntity: V2TIMGroupApplication { /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupApplication) -> [String: Any] { var result: [String: Any] = [:]; result["groupID"] = info.groupID; result["fromUser"] = info.fromUser; result["fromUserNickName"] = info.fromUserNickName; result["fromUserFaceUrl"] = info.fromUserFaceUrl; result["toUser"] = info.toUser; result["addTime"] = info.addTime; result["requestMsg"] = info.requestMsg; result["handledMsg"] = info.handledMsg; result["type"] = info.getType.rawValue; result["handleStatus"] = info.handleStatus.rawValue; result["handleResult"] = info.handleResult.rawValue; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupApplicationResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 群申请结果实体 class CustomGroupApplicationResultEntity: V2TIMGroupApplicationResult { /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupApplicationResult) -> [String: Any] { var result: [String: Any] = [:]; result["unreadCount"] = info.unreadCount; var groupApplicationList: [[String: Any]] = []; for item in info.applicationList! { groupApplicationList.append(CustomGroupApplicationEntity.getDict(info: item as! V2TIMGroupApplication)) } result["groupApplicationList"] = groupApplicationList; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupAtInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群@信息实体 class CustomGroupAtInfoEntity: V2TIMGroupAtInfo { /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupAtInfo) -> [String: Any] { var result: [String: Any] = [:]; result["seq"] = info.seq; result["atType"] = info.atType.rawValue; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupChangeInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/4. // import Foundation import ImSDK_Plus /// 自定义群改变信息 class CustomGroupChangeInfoEntity: V2TIMGroupChangeInfo { /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupChangeInfo) -> [String: Any] { var result: [String: Any] = [:]; result["type"] = info.type.rawValue; result["key"] = info.key; result["value"] = info.value; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群信息实体 class CustomGroupInfoEntity: V2TIMGroupInfo { required public override init() { } convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); if dict["groupID"] != nil { self.groupID = (dict["groupID"] as? String); } if dict["groupType"] != nil { self.groupType = (dict["groupType"] as? String); } if dict["groupName"] != nil { self.groupName = (dict["groupName"] as? String); } if dict["notification"] != nil { self.notification = (dict["notification"] as? String); } if dict["introduction"] != nil { self.introduction = (dict["introduction"] as? String); } if dict["faceURL"] != nil { self.faceURL = (dict["faceURL"] as? String); } if dict["allMuted"] != nil { self.allMuted = (dict["allMuted"] as! Bool); } if dict["groupAddOpt"] != nil { self.groupAddOpt = V2TIMGroupAddOpt.init(rawValue: (dict["groupAddOpt"] as! Int))!; } if dict["customInfo"] != nil { self.customInfo = [:]; for (k, v) in (dict["customInfo"] as! [String: String]) { self.customInfo[k] = v.data(using: .utf8) } } } /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupInfo) -> [String: Any] { var result: [String: Any] = [:]; result["groupID"] = info.groupID; result["groupType"] = info.groupType; result["groupName"] = info.groupName; result["notification"] = info.notification; result["introduction"] = info.introduction; result["faceUrl"] = info.faceURL; result["allMuted"] = info.allMuted; result["owner"] = info.owner; result["createTime"] = info.createTime; result["groupAddOpt"] = info.groupAddOpt.rawValue; result["lastInfoTime"] = info.lastInfoTime; result["lastMessageTime"] = info.lastMessageTime; result["memberCount"] = info.memberCount; result["onlineCount"] = info.onlineCount; result["role"] = info.role; result["recvOpt"] = info.recvOpt.rawValue; result["joinTime"] = info.joinTime; result["customInfo"] = info.customInfo; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupInfoResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群信息结果实体 class CustomGroupInfoResultEntity: V2TIMGroupInfoResult { required public override init() { } /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupInfoResult) -> [String: Any] { var result: [String: Any] = [:]; result["resultCode"] = info.resultCode; result["resultMessage"] = info.resultMsg; result["groupInfo"] = CustomGroupInfoEntity.getDict(info: info.info); return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupMemberChangeInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/4. // import Foundation import ImSDK_Plus /// 自定义群信息实体 class CustomGroupMemberChangeInfoEntity: V2TIMGroupMemberChangeInfo { /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupMemberChangeInfo) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["muteTime"] = info.muteTime; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupMemberFullInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群成员信息实体 class CustomGroupMemberFullInfoEntity: V2TIMGroupMemberFullInfo { convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.userID = (dict["userID"] as? String); if dict["customInfo"] != nil { self.customInfo = [:]; for (k, v) in (dict["customInfo"] as! [String: String]) { self.customInfo[k] = v.data(using: .utf8) } } self.nameCard = (dict["nameCard"] as? String); } /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupMemberFullInfo) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["nickName"] = info.nickName; result["friendRemark"] = info.friendRemark; result["faceUrl"] = info.faceURL; result["role"] = info.role; result["muteUntil"] = info.muteUntil; result["joinTime"] = info.joinTime; result["customInfo"] = info.customInfo; result["nameCard"] = info.nameCard; return result; } /// 根据对象获得字典对象 public static func getDict(simpleInfo: V2TIMGroupMemberInfo) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = simpleInfo.userID; result["nickName"] = simpleInfo.nickName; result["friendRemark"] = simpleInfo.friendRemark; result["faceUrl"] = simpleInfo.faceURL; result["nameCard"] = simpleInfo.nameCard; return result; } } ================================================ FILE: ios/Classes/entity/CustomGroupMemberInfoResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus class CustomGroupMemberInfoResultEntity: NSObject { /// 获取分页拉取的 seq。如果为 0 表示拉取结束。 var nextSeq: UInt64?; /// 群成员信息 var memberInfoList: [[String: Any]]?; override init() { } init(nextSeq: UInt64, infos: [V2TIMGroupMemberFullInfo]) { super.init(); self.nextSeq = nextSeq; self.memberInfoList = []; for info in infos { self.memberInfoList!.append(CustomGroupMemberFullInfoEntity.getDict(info: info)) } } } ================================================ FILE: ios/Classes/entity/CustomGroupMemberOperationResultEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义群成员操作结果 class CustomGroupMemberOperationResultEntity: V2TIMGroupMemberOperationResult { /// 根据对象获得字典对象 public static func getDict(info: V2TIMGroupMemberOperationResult) -> [String: Any] { var result: [String: Any] = [:]; result["result"] = info.result.rawValue; result["memberID"] = info.userID; return result; } } ================================================ FILE: ios/Classes/entity/CustomMessageReceiptEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation import ImSDK_Plus /// 自定义消息响应实体 class CustomMessageReceiptEntity: V2TIMMessageReceipt { /// 根据对象获得字典对象 public static func getDict(info: V2TIMMessageReceipt) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["timestamp"] = info.timestamp; return result; } } ================================================ FILE: ios/Classes/entity/CustomOfflinePushInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 自定义离线推送数据实体 class CustomOfflinePushInfoEntity: V2TIMOfflinePushInfo { required public override init() { } init(jsonStr: String?) { super.init(); if jsonStr == nil { return; } let dict = JsonUtil.getDictionaryFromJSONString(jsonString: jsonStr!); self.title = (dict["title"] as? String); self.desc = (dict["desc"] as? String); self.ext = (dict["ext"] as? String); self.iOSSound = (dict["iOSSound"] as? String); if dict["ignoreIOSBadge"] != nil { self.ignoreIOSBadge = (dict["ignoreIOSBadge"] as! Bool); } self.androidOPPOChannelID = (dict["androidOPPOChannelID"] as? String); if dict["disablePush"] != nil { self.disablePush = (dict["disablePush"] as! Bool); } } } ================================================ FILE: ios/Classes/entity/CustomSignalingInfoEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/6. // import Foundation import ImSDK_Plus /// 自定义信令信息实体 class CustomSignalingInfoEntity: V2TIMSignalingInfo { required public override init() { } init(jsonStr: String?) { super.init(); if jsonStr == nil { return; } let dict = JsonUtil.getDictionaryFromJSONString(jsonString: jsonStr!); self.inviteID = (dict["inviteID"] as? String); self.groupID = (dict["groupID"] as? String); self.inviter = (dict["inviter"] as? String); self.inviteeList = (dict["inviteeList"] as? NSMutableArray); self.data = (dict["data"] as? String); if dict["timeout"] != nil { self.timeout = (dict["timeout"] as! UInt32); } if dict["actionType"] != nil { self.actionType = SignalingActionType.init(rawValue: (dict["actionType"] as! Int))!; } } /// 根据对象获得字典对象 public static func getDict(info: V2TIMSignalingInfo) -> [String: Any] { var result: [String: Any] = [:]; result["inviteID"] = info.inviteID; result["groupID"] = info.groupID; result["inviter"] = info.inviter; result["inviteeList"] = info.inviteeList; result["data"] = info.data; result["timeout"] = info.timeout; result["actionType"] = info.actionType.rawValue; return result; } } ================================================ FILE: ios/Classes/entity/CustomUserEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义用户实体 class CustomUserEntity: V2TIMUserFullInfo { convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); if dict["nickName"] != nil{ self.nickName = (dict["nickName"] as? String); } if dict["faceURL"] != nil{ self.faceURL = (dict["faceURL"] as? String); } if dict["selfSignature"] != nil{ self.selfSignature = (dict["selfSignature"] as? String); } if dict["gender"] != nil { self.gender = V2TIMGender.init(rawValue: (dict["gender"] as! Int))!; } if dict["role"] != nil { self.role = (dict["role"] as! UInt32); } if dict["level"] != nil { self.level = (dict["level"] as! UInt32); } if dict["birthday"] != nil { self.birthday = (dict["birthday"] as! UInt32); } if dict["allowType"] != nil { self.allowType = V2TIMFriendAllowType.init(rawValue: (dict["allowType"] as! Int))!; } if dict["customInfo"] != nil { self.customInfo = [:]; for (k, v) in (dict["customInfo"] as! [String: String]) { self.customInfo[k] = v.data(using: .utf8) } } } /// 根据对象获得字典对象 public static func getDict(info: V2TIMUserFullInfo) -> [String: Any] { var result: [String: Any] = [:]; result["userID"] = info.userID; result["nickName"] = info.nickName; result["faceUrl"] = info.faceURL; result["selfSignature"] = info.selfSignature; result["gender"] = info.gender.rawValue; result["role"] = info.role; result["level"] = info.level; result["birthday"] = info.birthday; result["allowType"] = info.allowType.rawValue; result["customInfo"] = info.customInfo; return result; } } ================================================ FILE: ios/Classes/entity/FindFriendApplicationEntity.swift ================================================ // // Created by 蒋具宏 on 2020/11/3. // import Foundation /// 查找好友申请实体 class FindFriendApplicationEntity: NSObject { /// 用户ID var userID: String?; /// 类型 var type: Int?; required public override init() { } convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.userID = dict["userID"] as! String; self.type = dict["type"] as! Int; } } ================================================ FILE: ios/Classes/entity/FindGroupApplicationEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/28. // import Foundation /// 查找群申请信息实体 class FindGroupApplicationEntity: NSObject { /// 来自用户 var fromUser: String?; /// 群ID var groupID: String?; required public override init() { } convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.fromUser = (dict["fromUser"] as! String); self.groupID = (dict["groupID"] as! String); } } ================================================ FILE: ios/Classes/entity/FindMessageEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 查找消息实体 class FindMessageEntity: NSObject { /// 消息ID var msgId: String?; required public override init() { } convenience init(json: String) { self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json)) } init(dict: [String: Any]) { super.init(); self.msgId = dict["msgId"] as! String; } } ================================================ FILE: ios/Classes/entity/MessageEntity.swift ================================================ import ImSDK_Plus // // MessageEntity.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/2/10. // public class MessageEntity: NSObject { /** * 消息 ID */ var msgID: String?; /** * 消息时间戳 */ var timestamp: Date?; /** * 消息发送者 userID */ var sender: String?; /** * 消息发送者昵称 */ var nickName: String?; /** * 好友备注。如果没有拉取过好友信息或者不是好友,返回 null */ var friendRemark: String?; /** * 发送者头像 url */ var faceUrl: String?; /** * 群组消息,nameCard 为发送者的群名片 */ var nameCard: String?; /** * 群组消息,groupID 为接收消息的群组 ID,否则为 null */ var groupID: String?; /** * 单聊消息,userID 为会话用户 ID,否则为 null。 假设自己和 userA 聊天,无论是自己发给 userA 的消息还是 userA 发给自己的消息,这里的 userID 均为 userA */ var userID: String?; /** * 消息发送状态 */ var status: Int?; /** * 消息类型 */ var elemType: Int?; /** * 消息自定义数据(本地保存,不会发送到对端,程序卸载重装后失效) */ var localCustomData: Data?; /** * 消息自定义数据(本地保存,不会发送到对端,程序卸载重装后失效) */ var localCustomInt: Int32?; /** * 消息发送者是否是自己 */ var `self`: Bool?; /** * 消息自己是否已读 */ var read: Bool?; /** * 消息对方是否已读(只有 C2C 消息有效) */ var peerRead: Bool?; /** * 消息优先级 */ var priority: Int?; /** * 消息的离线推送信息 */ var offlinePushInfo: V2TIMOfflinePushInfo?; /** * 群@用户列表 */ var groupAtUserList: [String]?; /** * 消息的序列号 * 群聊中的消息序列号云端生成,在群里是严格递增且唯一的。 单聊中的序列号是本地生成,不能保证严格递增且唯一。 */ var seq: UInt64?; /** * 描述信息 */ var note: String?; /** * 节点信息 */ var node: AbstractMessageEntity?; /// 消息随机码 var random: UInt64?; override init() { } init(message: V2TIMMessage) { super.init(); // 设置基本信息 self.msgID = message.msgID; self.timestamp = message.timestamp; self.sender = message.sender; self.nickName = message.nickName; self.friendRemark = message.friendRemark; self.faceUrl = message.faceURL; self.nameCard = message.nameCard; self.groupID = message.groupID; self.userID = message.userID; self.status = message.status.rawValue; self.elemType = message.elemType.rawValue; self.localCustomData = message.localCustomData; self.localCustomInt = message.localCustomInt; self.`self` = message.isSelf; self.read = message.isRead; self.peerRead = message.isPeerRead; // self.priority // self.offlinePushInfo self.groupAtUserList = (message.groupAtUserList as? [String]); self.seq = message.seq; self.random = message.random; // 解析接口 let nodeType = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: self.elemType!); if nodeType != MessageNodeType.None { let messageNodeInterface = nodeType.messageNodeInterface(); let elem = MessageNodeType.getElemByMessage(message: message)!; self.note = messageNodeInterface.getNote(elem: elem); self.node = messageNodeInterface.analysis(elem: elem); } } } ================================================ FILE: ios/Classes/enums/DownloadType.swift ================================================ // // Created by 蒋具宏 on 2021/1/5. // import Foundation /// 下载类型 enum DownloadType: Int { /// 语音 case Sound = 0 /// 视频 case Video = 1 /// 视频缩略图 case VideoThumbnail = 2 /// 文件 case File = 3 } ================================================ FILE: ios/Classes/enums/ListenerType.swift ================================================ // Created by 蒋具宏 on 2020/2/15. // 监听器类型 public enum ListenerType { /// 新消息通知 case NewMessage /// C2C已读回执 case C2CReadReceipt /// 消息撤回 case MessageRevoked /// 同步服务开始 case SyncServerStart /// 同步服务完成 case SyncServerFinish /// 同步服务失败 case SyncServerFailed /// 新会话 case NewConversation /// 会话刷新 case ConversationChanged /// 好友申请新增通知 case FriendApplicationListAdded /// 好友申请删除通知 case FriendApplicationListDeleted /// 好友申请已读通知 case FriendApplicationListRead /// 好友新增通知 case FriendListAdded /// 好友删除通知 case FriendListDeleted /// 黑名单新增通知 case BlackListAdd /// 黑名单删除通知 case BlackListDeleted /// 好友资料更新通知 case FriendInfoChanged /// 有用户加入群 case MemberEnter /// 有用户离开群 case MemberLeave /// 有用户被拉入群 case MemberInvited /// 有用户被踢出群 case MemberKicked /// 群成员信息被修改 case MemberInfoChanged /// 创建群 case GroupCreated /// 群被解散 case GroupDismissed /// 群被回收 case GroupRecycled /// 群信息被修改 case GroupInfoChanged /// 有新的加群申请 case ReceiveJoinApplication /// 加群信息已被管理员处理 case ApplicationProcessed /// 指定管理员身份 case GrantAdministrator /// 取消管理员身份 case RevokeAdministrator /// 主动退出群组 case QuitFromGroup /// 收到 RESTAPI 下发的自定义系统消息 case ReceiveRESTCustomData /// 收到群属性更新的回调 case GroupAttributeChanged /// 正在连接到腾讯云服务器 case Connecting /// 网络连接成功 case ConnectSuccess /// 网络连接失败 case ConnectFailed /// 踢下线 case KickedOffline /// 当前用户的资料发生了更新 case SelfInfoUpdated /// 用户登录的 userSig 过期(用户需要重新获取 userSig 后登录) case UserSigExpired /// 收到信令邀请 case ReceiveNewInvitation /// 信令被邀请者接受邀请 case InviteeAccepted /// 信令被邀请者拒绝邀请 case InviteeRejected /// 信令邀请被取消 case InvitationCancelled /// 信令邀请超时 case InvitationTimeout /// 下载进度 case DownloadProgress /// 消息发送成功 case MessageSendSucc /// 消息发送失败 case MessageSendFail /// 消息发送进度更新 case MessageSendProgress } ================================================ FILE: ios/Classes/enums/MessageNodeType.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/3/13. // 消息节点类型 enum MessageNodeType: Int { // 没有元素 case None // 文本 case Text // 自定义 case Custom // 图片 case Image // 语音 case Sound // 视频 case Video // 文件 case File // 位置 case Location // 表情 case Face // 群提示 case GroupTips /// 获得消息节点接口 func messageNodeInterface() -> AbstractMessageNode { switch self { case .None: return AbstractMessageNode(); case .Text: return TextMessageNode() case .Custom: return CustomMessageNode(); case .Image: return ImageMessageNode(); case .Sound: return SoundMessageNode(); case .Video: return VideoMessageNode(); case .File: return FileMessageNode(); case .Location: return LocationMessageNode(); case .Face: return FaceMessageNode(); case .GroupTips: return GroupTipsMessageNode(); } } /// 根据腾讯云节点获得枚举对象 public static func getMessageNodeTypeByV2TIMConstant(constant: Int) -> MessageNodeType { MessageNodeType.init(rawValue: constant)! } /// 根据Message获得节点信息 public static func getElemByMessage(message: V2TIMMessage) -> V2TIMElem? { let messageType = getMessageNodeTypeByV2TIMConstant(constant: message.elemType.rawValue); switch messageType { case .None: return nil; case .Text: return message.textElem; case .Custom: return message.customElem; case .Image: return message.imageElem; case .Sound: return message.soundElem; case .Video: return message.videoElem; case .File: return message.fileElem; case .Location: return message.locationElem; case .Face: return message.faceElem; case .GroupTips: return message.groupTipsElem; } } } ================================================ FILE: ios/Classes/listener/CustomAPNSListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/29. // import Foundation import ImSDK_Plus /// 自定义APNS监听器 class CustomAPNSListener: NSObject, V2TIMAPNSListener { public static var number: UInt32 = 0; /// 程序进后台后,自定义 APP 的未读数,如果不处理,APP 未读数默认为所有会话未读数之和 func onSetAPPUnreadCount() -> UInt32 { return CustomAPNSListener.number; } } ================================================ FILE: ios/Classes/listener/CustomAdvancedMsgListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 消息相关监听器 class CustomAdvancedMsgListener: NSObject, V2TIMAdvancedMsgListener { /// 新消息通知 func onRecvNewMessage(_ msg: V2TIMMessage!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.NewMessage, params: MessageEntity.init(message: msg!)) } /// C2C已读回执 func onRecvC2CReadReceipt(_ receiptList: [V2TIMMessageReceipt]!) { var data: [[String: Any]] = []; for item in receiptList! { data.append(CustomMessageReceiptEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.C2CReadReceipt, params: data) } /// 消息撤回 func onRecvMessageRevoked(_ msgID: String!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageRevoked, params: msgID!) } } ================================================ FILE: ios/Classes/listener/CustomConversationListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 自定义会话监听 class CustomConversationListener: NSObject, V2TIMConversationListener { /// 同步服务开始 func onSyncServerStart() { SwiftTencentImPlugin.invokeListener(type: ListenerType.SyncServerStart, params: nil) } /// 同步服务完成 func onSyncServerFinish() { SwiftTencentImPlugin.invokeListener(type: ListenerType.SyncServerFinish, params: nil) } /// 同步服务失败 func onSyncServerFailed() { SwiftTencentImPlugin.invokeListener(type: ListenerType.SyncServerFailed, params: nil) } /// 新会话 func onNewConversation(_ conversationList: [V2TIMConversation]!) { var cs: [[String: Any]] = []; for item in conversationList! { cs.append(CustomConversationEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.NewConversation, params: cs) } /// 会话刷新 func onConversationChanged(_ conversationList: [V2TIMConversation]!) { var cs: [[String: Any]] = []; for item in conversationList! { cs.append(CustomConversationEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.ConversationChanged, params: cs) } } ================================================ FILE: ios/Classes/listener/CustomFriendshipListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 关系链相关监听器 class CustomFriendshipListener: NSObject, V2TIMFriendshipListener { /** * 好友申请新增通知,两种情况会收到这个回调: *

* 自己申请加别人好友 * 别人申请加自己好友 */ func onFriendApplicationListAdded(_ applicationList: [V2TIMFriendApplication]!) { var data: [[String: Any]] = []; for item in applicationList! { data.append(CustomFriendApplicationEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendApplicationListAdded, params: data) } /** * 好友申请删除通知,四种情况会收到这个回调 *

* 调用 deleteFriendApplication 主动删除好友申请 * 调用 refuseFriendApplication 拒绝好友申请 * 调用 acceptFriendApplication 同意好友申请且同意类型为 V2TIM_FRIEND_ACCEPT_AGREE 时 * 申请加别人好友被拒绝 */ func onFriendApplicationListDeleted(_ userIDList: [Any]!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendApplicationListDeleted, params: userIDList!) } /** * 好友申请已读通知,如果调用 setFriendApplicationRead 设置好友申请列表已读,会收到这个回调(主要用于多端同步) */ func onFriendApplicationListRead() { SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendApplicationListRead, params: nil) } /** * 好友新增通知 */ func onFriendListAdded(_ infoList: [V2TIMFriendInfo]!) { var data: [[String: Any]] = []; for item in infoList! { data.append(CustomFriendInfoEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendListAdded, params: data) } /** * 好友删除通知,,两种情况会收到这个回调: *

* 自己删除好友(单向和双向删除都会收到回调) * 好友把自己删除(双向删除会收到) */ func onFriendListDeleted(_ userIDList: [Any]!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendListDeleted, params: userIDList!) } /** * 黑名单新增通知 */ func onBlackListAdded(_ infoList: [V2TIMFriendInfo]!) { var data: [[String: Any]] = []; for item in infoList! { data.append(CustomFriendInfoEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.BlackListAdd, params: data) } /** * 黑名单删除通知 */ func onBlackListDeleted(_ userIDList: [Any]!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.BlackListDeleted, params: userIDList!) } /** * 好友资料更新通知 */ func onFriendProfileChanged(_ infoList: [V2TIMFriendInfo]!) { var data: [[String: Any]] = []; for item in infoList! { data.append(CustomFriendInfoEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendInfoChanged, params: data) } } ================================================ FILE: ios/Classes/listener/CustomGroupListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 群监听器 class CustomGroupListener: NSObject, V2TIMGroupListener { /// 有用户加入群(全员能够收到) func onMemberEnter(_ groupID: String!, memberList: [V2TIMGroupMemberInfo]!) { var data: [[String: Any]] = []; for item in memberList! { data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberEnter, params: [ "groupID": groupID!, "memberList": data, ]) } /// 有用户离开群(全员能够收到) func onMemberLeave(_ groupID: String!, member: V2TIMGroupMemberInfo!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberLeave, params: [ "groupID": groupID!, "member": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: member!), ]) } /// 某些人被拉入某群(全员能够收到) func onMemberInvited(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) { var data: [[String: Any]] = []; for item in memberList! { data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberInvited, params: [ "groupID": groupID!, "memberList": data, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), ]) } /// 某些人被踢出某群(全员能够收到) func onMemberKicked(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) { var data: [[String: Any]] = []; for item in memberList! { data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberKicked, params: [ "groupID": groupID!, "memberList": data, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), ]) } /// 群成员信息被修改(全员能收到) func onMemberInfoChanged(_ groupID: String!, changeInfoList: [V2TIMGroupMemberChangeInfo]!) { var data: [[String: Any]] = []; for item in changeInfoList! { data.append(CustomGroupMemberChangeInfoEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberInfoChanged, params: [ "groupID": groupID!, "changInfo": data, ]) } /// 创建群(主要用于多端同步) func onGroupCreated(_ groupID: String!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupCreated, params: groupID!) } /// 群被解散了(全员能收到) func onGroupDismissed(_ groupID: String!, opUser: V2TIMGroupMemberInfo!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupDismissed, params: [ "groupID": groupID!, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), ]) } /// 群被回收(全员能收到) func onGroupRecycled(_ groupID: String!, opUser: V2TIMGroupMemberInfo!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupRecycled, params: [ "groupID": groupID!, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), ]) } /// 群信息被修改(全员能收到) func onGroupInfoChanged(_ groupID: String!, changeInfoList: [V2TIMGroupChangeInfo]!) { var data: [[String: Any]] = []; for item in changeInfoList! { data.append(CustomGroupChangeInfoEntity.getDict(info: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupInfoChanged, params: [ "groupID": groupID!, "changInfo": data, ]) } /// 有新的加群请求(只有群主或管理员会收到) func onReceiveJoinApplication(_ groupID: String!, member: V2TIMGroupMemberInfo!, opReason: String!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.ReceiveJoinApplication, params: [ "groupID": groupID!, "member": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: member!), "opReason": opReason!, ]) } /// 加群请求已经被群主或管理员处理了(只有申请人能够收到) func onApplicationProcessed(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, opResult isAgreeJoin: Bool, opReason: String!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.ApplicationProcessed, params: [ "groupID": groupID!, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), "isAgreeJoin": isAgreeJoin, "opReason": opReason, ]) } /// 指定管理员身份 func onGrantAdministrator(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) { var data: [[String: Any]] = []; for item in memberList! { data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.GrantAdministrator, params: [ "groupID": groupID!, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), "memberList": data, ]) } /// 取消管理员身份 func onRevokeAdministrator(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) { var data: [[String: Any]] = []; for item in memberList! { data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item)); } SwiftTencentImPlugin.invokeListener(type: ListenerType.RevokeAdministrator, params: [ "groupID": groupID!, "opUser": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!), "memberList": data, ]) } /// 主动退出群组(主要用于多端同步,直播群(AVChatRoom)不支持) func onQuit(fromGroup groupID: String!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.QuitFromGroup, params: groupID!) } /// 收到 RESTAPI 下发的自定义系统消息 func onReceiveRESTCustomData(_ groupID: String!, data: Data!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.ReceiveRESTCustomData, params: [ "groupID": groupID!, "customData": data!, ]) } /// 收到群属性更新的回调 func onGroupAttributeChanged(_ groupID: String!, attributes: NSMutableDictionary!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupAttributeChanged, params: [ "groupID": groupID!, "attributes": attributes!, ]) } } ================================================ FILE: ios/Classes/listener/CustomSDKListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 自定义SDK监听器 class CustomSDKListener: NSObject, V2TIMSDKListener { /// 连接中 public func onConnecting() { SwiftTencentImPlugin.invokeListener(type: ListenerType.Connecting, params: nil) } /// 网络连接成功 public func onConnectSuccess() { SwiftTencentImPlugin.invokeListener(type: ListenerType.ConnectSuccess, params: nil) } /// 网络连接失败 public func onConnectFailed(_ code: Int32, err: String!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.ConnectFailed, params: [ "code": code, "err": err!, ]) } /// 踢下线通知 public func onKickedOffline() { SwiftTencentImPlugin.invokeListener(type: ListenerType.KickedOffline, params: nil) } /// 用户登录的 userSig 过期(用户需要重新获取 userSig 后登录) public func onUserSigExpired() { SwiftTencentImPlugin.invokeListener(type: ListenerType.UserSigExpired, params: nil) } /// 当前用户的资料发生了更新 public func onSelfInfoUpdated(_ Info: V2TIMUserFullInfo!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.SelfInfoUpdated, params: CustomUserEntity.getDict(info: Info!)) } } ================================================ FILE: ios/Classes/listener/CustomSignalingListener.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 自定义信令监听 class CustomSignalingListener: NSObject, V2TIMSignalingListener { ///收到新邀请时 func onReceiveNewInvitation(_ inviteID: String!, inviter: String!, groupID: String!, inviteeList: [String]!, data: String?) { var params: [String: Any] = ["inviteID": inviteID!]; if let temp = inviter { params["inviter"] = temp; } if let temp = groupID { params["groupID"] = temp; } if let temp = inviteeList { params["inviteeList"] = temp; } if let temp = data { params["data"] = temp; } SwiftTencentImPlugin.invokeListener(type: ListenerType.ReceiveNewInvitation, params: params) } /// 被邀请者接受邀请 func onInviteeAccepted(_ inviteID: String!, invitee: String!, data: String?) { var params: [String: Any] = ["inviteID": inviteID!,"invitee": invitee!]; if let temp = data { params["data"] = temp; } SwiftTencentImPlugin.invokeListener(type: ListenerType.InviteeAccepted, params: params) } /// 被邀请者拒绝邀请 func onInviteeRejected(_ inviteID: String!, invitee: String!, data: String?) { var params: [String: Any] = ["inviteID": inviteID!,"invitee": invitee!]; if let temp = data { params["data"] = temp; } SwiftTencentImPlugin.invokeListener(type: ListenerType.InviteeRejected, params: params) } /// 邀请被取消 func onInvitationCancelled(_ inviteID: String!, inviter: String!, data: String?) { var params: [String: Any] = ["inviteID": inviteID!,"inviter": inviter!]; if let temp = data { params["data"] = temp; } SwiftTencentImPlugin.invokeListener(type: ListenerType.InvitationCancelled, params: params) } /// 邀请超时 func onInvitationTimeout(_ inviteID: String!, inviteeList: [String]!) { SwiftTencentImPlugin.invokeListener(type: ListenerType.InvitationTimeout, params: [ "inviteID": inviteID!, "inviteeList": inviteeList!, ]) } } ================================================ FILE: ios/Classes/message/AbstractMessageNode.swift ================================================ import ImSDK_Plus // // AbstractMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 消息节点抽象 public class AbstractMessageNode { /** * 获得发送的消息体 * @param params 参数 */ func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { return V2TIMMessage(); } /** * 根据消息节点获得描述 * * @param elem 节点 */ func getNote(elem: V2TIMElem) -> String? { return nil; } /// 根据节点解析为实体对象 func analysis(elem: V2TIMElem) -> AbstractMessageEntity? { return nil; } /// 获得参数 func getParam(params: [AnyHashable: Any], paramKey: AnyHashable) -> T? { if let value = params[paramKey] { return (value as? T); } return nil; } } ================================================ FILE: ios/Classes/message/CustomMessageNode.swift ================================================ import ImSDK_Plus // // TextMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 自定义消息节点 public class CustomMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let data: String = getParam(params: params, paramKey: "data")!; let desc: String? = getParam(params: params, paramKey: "desc"); let ext: String? = getParam(params: params, paramKey: "ext"); return V2TIMManager.sharedInstance().createCustomMessage(data.data(using: String.Encoding.utf8), desc: desc, extension: ext) } override func getNote(elem: V2TIMElem) -> String { "[其它消息]" } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { CustomMessageEntity(elem: elem as! V2TIMCustomElem) } } ================================================ FILE: ios/Classes/message/FaceMessageNode.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 表情消息实体 class FaceMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let index: Int32 = getParam(params: params, paramKey: "index")!; let data: String = getParam(params: params, paramKey: "data")!; return V2TIMManager.sharedInstance().createFaceMessage(index, data: data.data(using: String.Encoding.utf8)) } override func getNote(elem: V2TIMElem) -> String { "[表情]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { FaceMessageEntity(elem: elem as! V2TIMFaceElem) } } ================================================ FILE: ios/Classes/message/FileMessageNode.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus class FileMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let filePath: String = getParam(params: params, paramKey: "filePath")!; let fileName: String = getParam(params: params, paramKey: "fileName")!; return V2TIMManager.sharedInstance().createFileMessage(filePath, fileName: fileName) } override func getNote(elem: V2TIMElem) -> String { "[文件]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { FileMessageEntity(elem: elem as! V2TIMFileElem) } } ================================================ FILE: ios/Classes/message/GroupTipsMessageNode.swift ================================================ import ImSDK_Plus // // GroupTipsMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/21. // 群提示消息节点 public class GroupTipsMessageNode: AbstractMessageNode { override func getNote(elem: V2TIMElem) -> String { "[群提示]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { GroupTipsMessageEntity(elem: elem as! V2TIMGroupTipsElem); } } ================================================ FILE: ios/Classes/message/ImageMessageNode.swift ================================================ import ImSDK_Plus // // TextMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 图片消息节点 public class ImageMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let path: String = getParam(params: params, paramKey: "path")!; return V2TIMManager.sharedInstance().createImageMessage(path) } override func getNote(elem: V2TIMElem) -> String { "[图片]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { ImageMessageEntity(elem: elem as! V2TIMImageElem) } } ================================================ FILE: ios/Classes/message/LocationMessageNode.swift ================================================ import ImSDK_Plus // // TextMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 位置消息节点 public class LocationMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let desc: String = getParam(params: params, paramKey: "desc")!; let longitude: Double = getParam(params: params, paramKey: "longitude")!; let latitude: Double = getParam(params: params, paramKey: "latitude")!; return V2TIMManager.sharedInstance().createLocationMessage(desc, longitude: longitude, latitude: latitude) } override func getNote(elem: V2TIMElem) -> String { "[位置消息]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { LocationMessageEntity(elem: elem as! V2TIMLocationElem); } } ================================================ FILE: ios/Classes/message/SoundMessageNode.swift ================================================ import ImSDK_Plus // // TextMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 语音消息节点 public class SoundMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let path: String = getParam(params: params, paramKey: "path")!; let duration: Int32 = getParam(params: params, paramKey: "duration")!; return V2TIMManager.sharedInstance().createSoundMessage(path, duration: duration) } override func getNote(elem: V2TIMElem) -> String { "[语音]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { SoundMessageEntity(elem: elem as! V2TIMSoundElem); } } ================================================ FILE: ios/Classes/message/TextMessageNode.swift ================================================ import ImSDK_Plus // // TextMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 文本消息节点 public class TextMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let text: String = getParam(params: params, paramKey: "content")!; let atUserList: Any? = getParam(params: params, paramKey: "atUserList"); let atAll: Any? = getParam(params: params, paramKey: "atAll"); // 有@用户或者@所有人则进入分支 if (atUserList != nil && !(atUserList is NSNull)) || (atAll != nil && atAll is NSNull && atAll as! Bool) { var atList: [String] = []; // 追加@的目标 if atUserList != nil && !(atUserList is NSNull) { for item in atUserList as! [String] { atList.append(item); } } // @所有人 if atAll != nil && !(atAll is NSNull) && (atAll as! Bool) { atList.append(kImSDK_MesssageAtALL); } // @有内容则直接返回 if atList.count >= 1 { return V2TIMManager.sharedInstance().createText(atMessage: text, atUserList: (atList as AnyObject as! NSArray).mutableCopy() as! NSMutableArray) } } return V2TIMManager.sharedInstance().createTextMessage(text); } override func getNote(elem: V2TIMElem) -> String { (elem as! V2TIMTextElem).text ?? ""; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { TextMessageEntity(elem: elem as! V2TIMTextElem) } } ================================================ FILE: ios/Classes/message/VideoMessageNode.swift ================================================ import ImSDK_Plus // // TextMessageNode.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/13. // 视频消息节点 public class VideoMessageNode: AbstractMessageNode { override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage { let videoPath: String = getParam(params: params, paramKey: "videoPath")!; let duration: Int32 = getParam(params: params, paramKey: "duration")!; let snapshotPath: String = getParam(params: params, paramKey: "snapshotPath")!; var suffix: String = ""; if videoPath.contains(".") { let ss = videoPath.split(separator: "."); suffix = String(ss[ss.count - 1]); } return V2TIMManager.sharedInstance().createVideoMessage(videoPath, type: suffix, duration: duration, snapshotPath: snapshotPath) } override func getNote(elem: V2TIMElem) -> String { "[视频]"; } override func analysis(elem: V2TIMElem) -> AbstractMessageEntity { VideoMessageEntity(elem: elem as! V2TIMVideoElem); } } ================================================ FILE: ios/Classes/message/entity/AbstractMessageEntity.swift ================================================ // // AbstractMessageEntity.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/15. // 抽象消息实体 public class AbstractMessageEntity : NSObject{ var nodeType : MessageNodeType?; override init() { } init(_ type : MessageNodeType) { nodeType = type; } } ================================================ FILE: ios/Classes/message/entity/CustomMessageEntity.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/3/15. // 自定义消息实体 public class CustomMessageEntity: AbstractMessageEntity { /// 自定义内容 var data: String?; /// 描述 var desc: String?; /// 扩展 var ext: String?; override init() { super.init(MessageNodeType.Custom); } init(elem: V2TIMCustomElem) { super.init(MessageNodeType.Custom); self.data = String(data: elem.data, encoding: String.Encoding.utf8)!; if let v = elem.desc { self.desc = v; } if let v = elem.`extension` { self.ext = v; } } } ================================================ FILE: ios/Classes/message/entity/FaceMessageEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 表情消息实体 class FaceMessageEntity: AbstractMessageEntity { /** * 下标 */ var index: Int32?; /** * 文件名 */ var data: Data?; override init() { super.init(MessageNodeType.Face); } init(elem: V2TIMFaceElem) { super.init(MessageNodeType.Face); self.index = elem.index; self.data = elem.data; } } ================================================ FILE: ios/Classes/message/entity/FileMessageEntity.swift ================================================ // // Created by 蒋具宏 on 2020/10/27. // import Foundation import ImSDK_Plus /// 文件消息实体 class FileMessageEntity: AbstractMessageEntity { /** * 文件路径 */ var filePath: String?; /** * 文件名 */ var fileName: String?; /** * 文件UUID */ var uuid: String?; /** * 文件大小 */ var size: Int32?; override init() { super.init(MessageNodeType.File); } init(elem: V2TIMFileElem) { super.init(MessageNodeType.File); self.uuid = elem.uuid; self.fileName = elem.filename; self.filePath = elem.path; self.size = elem.fileSize; } } ================================================ FILE: ios/Classes/message/entity/LocationMessageEntity.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/3/15. // 位置消息实体 public class LocationMessageEntity: AbstractMessageEntity { /// 描述 var desc: String?; /// 经度 var latitude: Double?; /// 纬度 var longitude: Double?; override init() { super.init(MessageNodeType.Location) } init(elem: V2TIMLocationElem) { super.init(MessageNodeType.Location) self.desc = elem.desc; self.longitude = elem.longitude; self.latitude = elem.latitude; } } ================================================ FILE: ios/Classes/message/entity/SoundMessageEntity.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/3/15. // 语音消息实体 public class SoundMessageEntity: AbstractMessageEntity { /// 语音ID var uuid: String?; /// 路径 var path: String?; /// 时长 var duration: Int32?; /// 数据大小 var dataSize: Int32?; override init() { super.init(MessageNodeType.Sound); } init(elem: V2TIMSoundElem) { super.init(MessageNodeType.Sound); self.path = elem.path; self.dataSize = elem.dataSize; self.duration = elem.duration; self.uuid = elem.uuid; } } ================================================ FILE: ios/Classes/message/entity/TextMessageEntity.swift ================================================ import ImSDK_Plus // // TextMessageEntity.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/15. // 文本消息实体 public class TextMessageEntity: AbstractMessageEntity { /// 消息内容 var content: String?; override init() { super.init(MessageNodeType.Text); } init(elem: V2TIMTextElem) { super.init(MessageNodeType.Text); self.content = elem.text; } } ================================================ FILE: ios/Classes/message/entity/VideoMessageEntity.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/3/15. // 视频消息实体 public class VideoMessageEntity: AbstractMessageEntity { /** * 视频路径 */ var videoPath: String?; /** * 视频UUID */ var videoUuid: String?; /** * 视频大小 */ var videoSize: Int32?; /** * 时长 */ var duration: Int32?; /** * 缩略图路径 */ var snapshotPath: String?; /** * 缩略图UUID */ var snapshotUuid: String?; /** * 缩略图大小 */ var snapshotSize: Int32?; /** * 缩略图宽度 */ var snapshotWidth: Int32?; /** * 缩略图高度 */ var snapshotHeight: Int32?; override init() { super.init(MessageNodeType.Video); } init(elem: V2TIMVideoElem) { super.init(MessageNodeType.Video); self.videoUuid = elem.videoUUID; self.videoPath = elem.videoPath; self.videoSize = elem.videoSize; self.duration = elem.duration; self.snapshotUuid = elem.snapshotUUID; self.snapshotWidth = elem.snapshotWidth; self.snapshotHeight = elem.snapshotHeight; self.snapshotPath = elem.snapshotPath; self.snapshotSize = elem.snapshotSize; } } ================================================ FILE: ios/Classes/message/entity/group_tips/GroupTipsMessageEntity.swift ================================================ import ImSDK_Plus // // GroupTipsMessageself.swift // tencent_im_plugin // // Created by 蒋具宏 on 2020/3/21. // 群体是消息实体 public class GroupTipsMessageEntity: AbstractMessageEntity { /// 群ID var groupID: String?; /// 操作类型 var type: Int?; /// 操作者 var opMember: [String: Any]?; /// 被操作人列表 var memberList: [[String: Any]]?; /// 群资料变更信息列表,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE时有效 var groupChangeInfoList: [[String: Any]]?; /// 群成员变更信息列表,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE时有效 var memberChangeInfoList: [[String: Any]]?; /// 当前群成员数,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_JOIN, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_QUIT, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_KICKED的时候有效 var memberCount : UInt32?; override init() { super.init(MessageNodeType.GroupTips); } init(elem: V2TIMGroupTipsElem) { super.init(MessageNodeType.GroupTips); self.groupID = elem.groupID; self.type = elem.type.rawValue; self.opMember = CustomGroupMemberFullInfoEntity.getDict(simpleInfo: elem.opMember); var memberList : [[String: Any]] = []; for var item in elem.memberList{ memberList.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item)); } self.memberList = memberList; var groupChangeInfoList : [[String: Any]] = []; for var item in elem.groupChangeInfoList{ groupChangeInfoList.append(CustomGroupChangeInfoEntity.getDict(info: item)); } self.groupChangeInfoList = groupChangeInfoList; var memberChangeInfoList : [[String: Any]] = []; for var item in elem.memberChangeInfoList{ memberChangeInfoList.append(CustomGroupMemberChangeInfoEntity.getDict(info: item)); } self.memberChangeInfoList = groupChangeInfoList; self.memberCount = elem.memberCount; } } ================================================ FILE: ios/Classes/message/entity/image/ImageEntity.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/2/10. // 图片实体 public class ImageEntity: NSObject { /** * 大小 */ var size: Int32?; /** * 宽度 */ var width: Int32?; /** * 类型 */ var type: Int?; /** * url */ var url: String?; /** * 高度 */ var height: Int32?; /// ID var uUID: String?; override init() { } init(image: V2TIMImage) { super.init(); self.size = image.size; self.width = image.width; self.type = image.type.rawValue; self.url = image.url; self.height = image.height; self.uUID = image.uuid; } } ================================================ FILE: ios/Classes/message/entity/image/ImageMessageEntity.swift ================================================ import ImSDK_Plus // Created by 蒋具宏 on 2020/3/15. // 图片消息实体 public class ImageMessageEntity: AbstractMessageEntity { /// 路径 var path: String?; /// 图片数据 var imageData: [ImageEntity]?; override init() { super.init(MessageNodeType.Image); } init(elem: V2TIMImageElem) { super.init(MessageNodeType.Image); self.path = elem.path; self.imageData = []; for item in elem.imageList { self.imageData!.append(ImageEntity(image: item)); } } } ================================================ FILE: ios/Classes/utils/CommonUtils.swift ================================================ import Flutter // 通用工具类 // Created by 蒋具宏 on 2020/2/10. public class CommonUtils { /** * 通用方法,获得参数值,如未找到参数,则直接中断 * * @param methodCall 方法调用对象 * @param result 返回对象 * @param param 参数名 */ public static func getParam(call: FlutterMethodCall, result: @escaping FlutterResult, param: String) -> Any? { let value = (call.arguments as! [String: Any])[param]; if value == nil { result( FlutterError(code: "5", message: "Missing parameter", details: "Cannot find parameter `\(param)` or `\(param)` is null!") ); } return value } /// 将hex string 转为Data public static func dataWithHexString(hex: String) -> Data { var hex = hex var data = Data() while (hex.count > 0) { let index1 = hex.index(hex.startIndex, offsetBy: 2) let index2 = hex.index(hex.endIndex, offsetBy: 0) let c: String = String(hex[hex.startIndex..(_ type: T.Type, value: Any?) -> T? where T: Decodable { guard let value = value else { return nil } return toModel(type, value: value) } /** * 字典转模型 */ public static func toModel(_ type: T.Type, value: Any) -> T? where T: Decodable { guard let data = try? JSONSerialization.data(withJSONObject: value) else { return nil } let decoder = JSONDecoder() decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: "+Infinity", negativeInfinity: "-Infinity", nan: "NaN") return try? decoder.decode(type, from: data) } /** * 将json字符串转换为字典 */ public static func getDictionaryFromJSONString(jsonString: String) -> [String: Any] { let jsonData: Data = jsonString.data(using: .utf8)! let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) if dict != nil { return (dict as! NSDictionary) as! [String: Any] } return NSDictionary() as! [String: Any] } /// 将json字符串转换为数组 public static func getArrayFromJSONString(jsonString: String) -> NSArray { let jsonData: Data = jsonString.data(using: .utf8)! let array = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) if array != nil { return array as! NSArray } return array as! NSArray } /** * 将对象转换为JSON字符串(数组/对象) */ public static func toJson(_ object: Any) -> Any { // 解析数组 if let array = object as? [Any] { let isStringArray = object is [String]; var result = "["; for item in array { let data = isStringArray ? "\"\(toJsonByObj(item))\"" : toJsonByObj(item); result += "\(data),"; } // 删除末尾逗号 if result.hasSuffix(",") { result = String(result.dropLast()); } return result + "]"; } // 解析单个对象 return toJsonByObj(object); } /** * 将对象转换为JSON字符串(单个对象) */ private static func toJsonByObj(_ object: Any) -> Any { if object is String { return "\(object)"; } if object is Int32 || object is Int || object is UInt32 || object is UInt64 || object is Bool || object is Double || object is time_t || object is Date || object is Data || object is Dictionary { return vHandler(object); } var result = "{"; // 反射当前类及父类反射对象 let morror = Mirror.init(reflecting: object) let superMorror = morror.superclassMirror // 键值对字典 var dict: Dictionary = [:]; // 遍历父类和子类属性集合,添加到键值对字典 if superMorror != nil { for (name, value) in (superMorror?.children)! { dict[name!] = value; } } for (name, value) in morror.children { dict[name!] = value; } // 组装json对象 for (name, value) in dict { // 解码值,根据不同类型设置不同封装,nil不进行封装 if let n = name { let v = unwrap(value); // 未解码成功的值,则是nil if !("\(type(of: v))".hasPrefix("Optional")) { result += kv(n, v); result += ","; } } } // 删除末尾逗号 if result.hasSuffix(",") { result = String(result.dropLast()); } return result + "}"; } /** * 解码值,optional 将会被自动解码 */ private static func unwrap(_ any: T) -> Any { let mirror = Mirror(reflecting: any) guard mirror.displayStyle == .optional, let first = mirror.children.first else { return any } return first.value } /** * 根据K和V拼装键值对 */ private static func kv(_ k: Any, _ v: Any) -> String { return "\"\(k)\":\(vHandler(v))"; } /** * 值处理,根据不同类型的值,返回不同的结果 */ private static func vHandler(_ v: Any) -> Any { // 根据类型赋值不同的值 // 如果是字符串,将会进行转移 " to \" // 如果是Data,将会解析为字符串并且进行转移 if v is String { return "\"\(stringReplace(source: "\(v)"))\""; } else if v is Int32 || v is Int || v is UInt32 || v is UInt64 || v is Bool || v is Double || v is time_t { return v; } else if v is Date { return Int((v as! Date).timeIntervalSince1970); } else if v is Data { return "\"\(stringReplace(source: String(data: v as! Data, encoding: String.Encoding.utf8)!))\""; } else if v is Dictionary { var result = "{"; // 解析键值对 for (key, value) in v as! Dictionary { result += "\(kv(key, value)),"; } // 删除末尾逗号 if result.hasSuffix(",") { result = String(result.dropLast()); } return result + "}"; } else if v is NSObject { return toJson(v); } else { return "\"\(v)\""; } } /** * 字符串替换 */ private static func stringReplace(source: String) -> String { var result = source; // 内容替换 result = result.replacingOccurrences(of: "\\", with: "\\\\"); result = result.replacingOccurrences(of: "\"", with: "\\\""); result = result.replacingOccurrences(of: "/", with: "\\/"); result = result.replacingOccurrences(of: "\\\\b", with: "\\b"); result = result.replacingOccurrences(of: "\\\\f", with: "\\f"); result = result.replacingOccurrences(of: "\n", with: "\\n"); result = result.replacingOccurrences(of: "\r", with: "\\r"); result = result.replacingOccurrences(of: "\t", with: "\\t"); result = result.replacingOccurrences(of: "\0", with: ""); return result; } } ================================================ FILE: ios/Classes/utils/TencentImUtil.swift ================================================ import ImSDK_Plus // 腾讯云工具类 // Created by 蒋具宏 on 2020/2/10. public class TencentImUtils { /** * 返回[错误返回闭包],腾讯云IM通用格式 */ public static func returnErrorClosures(result: @escaping FlutterResult) -> V2TIMFail { return { (code: Int32, desc: Optional) -> Void in result( FlutterError(code: "\(code)", message: desc ?? "", details: desc ?? "") ); }; } /// 获得消息对象 public static func getMessageByFindMessageEntity(json: String, succ: @escaping GetInfoSuc, fail: @escaping V2TIMFail) { getMessageByFindMessageEntity(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json), succ: succ, fail: fail); } /// 获得消息对象 public static func getMessageByFindMessageEntity(dict: [String: Any], succ: @escaping GetInfoSuc, fail: @escaping V2TIMFail) { getMessageByFindMessageEntity(dict: [dict], succ: { (messages: [V2TIMMessage]?) in // 消息不存在 if messages == nil || messages!.count == 0{ fail(-1,"未找到消息对象!消息ID不存在"); return; } succ(messages![0]); }, fail: fail); } /// 获得消息对象 public static func getMessageByFindMessageEntity(dict: [[String: Any]], succ: @escaping GetInfoSuc<[V2TIMMessage]?>, fail: @escaping V2TIMFail) { var ids: [String] = []; for item in dict { let obj = FindMessageEntity.init(dict: item); ids.append(obj.msgId!); } V2TIMManager.sharedInstance()?.findMessages(ids, succ: { (messages: [V2TIMMessage]?) in succ(messages); }, fail: fail) } /// 获得群申请对象 public static func getGroupApplicationByFindGroupApplicationEntity(json: String, succ: @escaping GetInfoSuc, fail: @escaping V2TIMFail) { getGroupApplicationByFindGroupApplicationEntity(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json), succ: succ, fail: fail); } /// 获得群申请对象 public static func getGroupApplicationByFindGroupApplicationEntity(dict: [String: Any], succ: @escaping GetInfoSuc, fail: @escaping V2TIMFail) { let data = FindGroupApplicationEntity.init(dict: dict); V2TIMManager.sharedInstance().getGroupApplicationList({ result in if result?.applicationList != nil { for item in result!.applicationList! { let itemEntity = item as! V2TIMGroupApplication; if itemEntity.groupID == data.groupID && itemEntity.fromUser == data.fromUser { succ(itemEntity); return; } } } succ(nil); }, fail: fail) } /// 获得好友申请对象 public static func getFriendApplicationByFindFriendApplicationEntity(json: String, succ: @escaping GetInfoSuc, fail: @escaping V2TIMFail) { getFriendApplicationByFindFriendApplicationEntity(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json), succ: succ, fail: fail); } /// 获得好友申请对象 public static func getFriendApplicationByFindFriendApplicationEntity(dict: [String: Any], succ: @escaping GetInfoSuc, fail: @escaping V2TIMFail) { let data = FindFriendApplicationEntity.init(dict: dict); V2TIMManager.sharedInstance().getFriendApplicationList({ result in if result?.applicationList != nil { for item in result!.applicationList! { let itemEntity = item as! V2TIMFriendApplication; if itemEntity.userID == data.userID && itemEntity.type.rawValue == data.type { succ(itemEntity); return; } } } succ(nil); }, fail: fail) } } /** * 获取信息成功回调 */ public typealias GetInfoSuc = (_ array: T) -> Void; ================================================ FILE: ios/tencent_im_plugin.podspec ================================================ # # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. # Run `pod lib lint tencent_im_plugin.podspec' to validate before publishing. # Pod::Spec.new do |s| s.name = 'tencent_im_plugin' s.version = '0.0.1' s.summary = '腾讯云IM插件' s.description = <<-DESC 腾讯云IM插件 DESC s.homepage = 'https://github.com/JiangJuHong/FlutterTencentImPlugin' s.license = { :file => '../LICENSE' } s.author = { 'JiangJuHong' => '690717394@qq.com' } s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' s.platform = :ios, '8.0' # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. # s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } s.swift_version = '5.0' # 解决 for architecture arm64 问题 s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } # 资源导入 s.vendored_frameworks = '**/*.framework' # SDK 依赖 s.dependency 'TXIMSDK_Plus_iOS_Bitcode', '6.1.2155' # alibaba json 序列化库(https://github.com/alibaba/HandyJSON) s.dependency 'HandyJSON' end ================================================ FILE: lib/entity/conversation_entity.dart ================================================ import 'package:tencent_im_plugin/entity/group_at_info_entity.dart'; import 'package:tencent_im_plugin/entity/message_entity.dart'; import 'package:tencent_im_plugin/enums/conversation_type_enum.dart'; import 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart'; import 'package:tencent_im_plugin/enums/group_type_enum.dart'; import 'package:tencent_im_plugin/list_util.dart'; import 'dart:convert'; /// 会话实体 class ConversationEntity { /// 会话ID late String conversationID; /// 会话类型 late ConversationTypeEnum type; /// 用户ID String? userID; /// 群ID String? groupID; /// 显示名称 String? showName; /// 头像 String? faceUrl; /// 接收消息选项(群会话有效) ReceiveMessageOptEnum? recvOpt; /// 群类型 GroupTypeEnum? groupType; /// 未读数量 int? unreadCount; /// 最后一条消息 MessageEntity? lastMessage; /// 草稿文本 String? draftText; /// 草稿时间 int? draftTimestamp; /// 是否置顶 bool? pinned; /// @信息列表 List? groupAtInfoList; ConversationEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['conversationID'] != null) conversationID = json['conversationID']; if (json['type'] != null) type = ConversationTypeTool.getByInt(json['type']); if (json['userID'] != null) userID = json['userID']; if (json['groupID'] != null) groupID = json['groupID']; if (json['showName'] != null) showName = json['showName']; if (json['faceUrl'] != null) faceUrl = json['faceUrl']; if (json['recvOpt'] != null) recvOpt = ReceiveMessageOptTool.getByInt(json['recvOpt']); if (json['groupType'] != null) groupType = GroupTypeTool.getByString(json['groupType']); if (json['unreadCount'] != null) unreadCount = json['unreadCount']; if (json['lastMessage'] != null) lastMessage = MessageEntity.fromJson(json["lastMessage"]); if (json['draftText'] != null) draftText = json['draftText']; if (json['draftTimestamp'] != null) draftTimestamp = json['draftTimestamp']; if (json['pinned'] != null) pinned = json['pinned']; if (json['groupAtInfoList'] != null) groupAtInfoList = ListUtil.generateOBJList(json["groupAtInfoList"]); } @override bool operator ==(Object other) => identical(this, other) || other is ConversationEntity && runtimeType == other.runtimeType && conversationID == other.conversationID; @override int get hashCode => conversationID.hashCode; } ================================================ FILE: lib/entity/conversation_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/conversation_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 会话结果实体 class ConversationResultEntity { /// 下一次分页拉取的游标 late int nextSeq; /// 会话列表是否已经拉取完毕 late bool finished; /// 会话列表 late List conversationList; ConversationResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['nextSeq'] != null) nextSeq = json['nextSeq']; if (json['finished'] != null) finished = json['finished']; if (json['conversationList'] != null) conversationList = ListUtil.generateOBJList( json["conversationList"]); } } ================================================ FILE: lib/entity/download_progress_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/download_type_enum.dart'; /// 下载进度实体 class DownloadProgressEntity { /// 消息ID late String msgId; /// 当前下载大小 late int currentSize; /// 总大小 late int totalSize; /// 下载类型 late DownloadTypeEnum type; DownloadProgressEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['msgId'] != null) msgId = json["msgId"]; if (json['currentSize'] != null) currentSize = json["currentSize"]; if (json['totalSize'] != null) totalSize = json["totalSize"]; if (json['type'] != null) type = DownloadTypeTool.getByInt(json["type"]); } } ================================================ FILE: lib/entity/error_entity.dart ================================================ import 'dart:convert'; /// 错误实体 class ErrorEntity { /// 错误码 late int code; /// 错误描述 String? error; ErrorEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['code'] != null) code = json['code']; if (json['error'] != null) error = json['error']; } } ================================================ FILE: lib/entity/find_friend_application_entity.dart ================================================ import 'package:tencent_im_plugin/entity/friend_application_entity.dart'; import 'package:tencent_im_plugin/enums/friend_application_type_enum.dart'; /// 查找好友申请实体 class FindFriendApplicationEntity { /// 用户ID String userID; /// 类型 FriendApplicationTypeEnum type; FindFriendApplicationEntity({ required this.userID, required this.type, }); /// 根据[data]对象快速转换为查找好友申请实体 factory FindFriendApplicationEntity.fromFriendApplicationEntity(FriendApplicationEntity data) { return FindFriendApplicationEntity(userID: data.userID, type: data.type); } Map toJson() { final Map data = new Map(); data["userID"] = userID; data["type"] = FriendApplicationTypeTool.toInt(type); return data; } } ================================================ FILE: lib/entity/find_group_application_entity.dart ================================================ /// 查找群申请实体 class FindGroupApplicationEntity { /// 来自用户 String fromUser; /// 群ID String groupID; FindGroupApplicationEntity({ required this.fromUser, required this.groupID, }); Map toJson() { final Map data = new Map(); data["fromUser"] = fromUser; data["groupID"] = groupID; return data; } } ================================================ FILE: lib/entity/find_message_entity.dart ================================================ /// 查找消息实体 class FindMessageEntity { /// 消息ID String msgId; FindMessageEntity({ required this.msgId, }); Map toJson() { final Map data = new Map(); data["msgId"] = this.msgId; return data; } } ================================================ FILE: lib/entity/friend_add_application_entity.dart ================================================ import 'package:tencent_im_plugin/enums/friend_type_enum.dart'; /// 好友添加申请实体 class FriendAddApplicationEntity { /// 用户ID String userID; /// 好友备注 String? friendRemark; /// 申请描述 String? addWording; /// 添加来源 String? addSource; /// 添加类型 FriendTypeEnum addType; FriendAddApplicationEntity({ required this.userID, this.friendRemark, this.addWording, this.addSource, required this.addType, }); Map toJson() { final Map data = new Map(); data['userID'] = this.userID; if (this.friendRemark != null) data['friendRemark'] = this.friendRemark; if (this.addWording != null) data['addWording'] = this.addWording; if (this.addSource != null) data['addSource'] = this.addSource; data['addType'] = FriendTypeTool.toInt(this.addType); return data; } } ================================================ FILE: lib/entity/friend_application_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/friend_application_type_enum.dart'; /// 好友申请实体 class FriendApplicationEntity { /// 用户ID late String userID; /// 用户昵称 String? nickname; /// 用户头像 String? faceUrl; /// 申请时间 late int addTime; /// 申请来源 String? addSource; /// 申请描述 String? addWording; /// 类型 late FriendApplicationTypeEnum type; FriendApplicationEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['nickname'] != null) nickname = json['nickname']; if (json['faceUrl'] != null) faceUrl = json['faceUrl']; if (json['addTime'] != null) addTime = json['addTime']; if (json['addSource'] != null) addSource = json['addSource']; if (json['addWording'] != null) addWording = json['addWording']; if (json['type'] != null) type = FriendApplicationTypeTool.getByInt(json['type']); } } ================================================ FILE: lib/entity/friend_application_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/friend_application_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 好友申请结果实体 class FriendApplicationResultEntity { /// 未读数量 late int unreadCount; /// 好友申请列表 late List friendApplicationList; FriendApplicationResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['unreadCount'] != null) unreadCount = json['unreadCount']; if (json['friendApplicationList'] != null) friendApplicationList = ListUtil.generateOBJList( json['friendApplicationList']); } } ================================================ FILE: lib/entity/friend_check_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/friend_relation_type_enum.dart'; /// 好友检测结果实体 class FriendCheckResultEntity { /// 好友 id late String userID; /// 返回结果码 late int resultCode; /// 返回结果描述 String? resultInfo; /// 好友结果类型 FriendRelationTypeEnum? resultType; FriendCheckResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['resultCode'] != null) resultCode = json['resultCode']; if (json['resultInfo'] != null) resultInfo = json['resultInfo']; if (json['resultType'] != null) resultType = FriendRelationTypeTool.getByInt(json['resultType']); } } ================================================ FILE: lib/entity/friend_group_entity.dart ================================================ import 'dart:convert'; /// 好友分组实体 class FriendGroupEntity { /// 组名 late String name; /// 好友数量 late int friendCount; /// 好友ID列表 late List friendIDList; FriendGroupEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['name'] != null) name = json['name']; if (json['friendCount'] != null) friendCount = json['friendCount']; if (json['friendIDList'] != null) friendIDList = json['friendIDList']?.cast(); } } ================================================ FILE: lib/entity/friend_info_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/user_entity.dart'; /// 好友信息实体 class FriendInfoEntity { /// 用户ID late String userID; /// 好友备注 String? friendRemark; /// 好友分组列表 List? friendGroups; /// 好友自定义信息 Map? friendCustomInfo; /// 用户信息 UserEntity? userProfile; FriendInfoEntity({ required this.userID, this.friendRemark, this.friendCustomInfo, }); FriendInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['friendRemark'] != null) friendRemark = json['friendRemark']; if (json['friendGroups'] != null) friendGroups = json['friendGroups']?.cast(); if (json['friendCustomInfo'] != null) friendCustomInfo = json['friendCustomInfo']?.cast(); if (json['userProfile'] != null) userProfile = UserEntity.fromJson(json['userProfile']); } Map toJson() { final Map data = new Map(); data['userID'] = this.userID; if (this.friendRemark != null) data['friendRemark'] = this.friendRemark; if (this.friendCustomInfo != null) data['friendCustomInfo'] = this.friendCustomInfo; return data; } @override bool operator ==(Object other) => identical(this, other) || other is FriendInfoEntity && runtimeType == other.runtimeType && userID == other.userID; @override int get hashCode => userID.hashCode; } ================================================ FILE: lib/entity/friend_info_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/friend_info_entity.dart'; import 'package:tencent_im_plugin/enums/friend_relation_type_enum.dart'; /// 好友信息结果实体 class FriendInfoResultEntity { /// 结果码 late int resultCode; /// 结果信息` String? resultInfo; /// 好友类型 FriendRelationTypeEnum? relation; /// 好友信息 FriendInfoEntity? friendInfo; FriendInfoResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['resultCode'] != null) resultCode = json['resultCode']; if (json['resultInfo'] != null) resultInfo = json['resultInfo']; if (json['relation'] != null) relation = FriendRelationTypeTool.getByInt(json['relation']); if (json['friendInfo'] != null) friendInfo = FriendInfoEntity.fromJson(json['friendInfo']); } } ================================================ FILE: lib/entity/friend_operation_result_entity.dart ================================================ import 'dart:convert'; /// 好友操作结果实体 class FriendOperationResultEntity { /// 用户ID late String userID; /// 返回码 late int resultCode; /// 返回信息 String? resultInfo; FriendOperationResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['resultCode'] != null) resultCode = json['resultCode']; if (json['resultInfo'] != null) resultInfo = json['resultInfo']; } } ================================================ FILE: lib/entity/group_administrator_op_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 群管理员操作通知实体 class GroupAdministratorOpEntity { /// 群ID late String groupID; /// 群成员列表 List? changInfo; /// 操作用户 GroupMemberEntity? opUser; GroupAdministratorOpEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["changInfo"] != null) changInfo = ListUtil.generateOBJList(json['changInfo']); if (json["opUser"] != null) opUser = GroupMemberEntity.fromJson(json["opUser"]); } } ================================================ FILE: lib/entity/group_application_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/group_application_handler_result_enum.dart'; import 'package:tencent_im_plugin/enums/group_application_handler_status_enum.dart'; import 'package:tencent_im_plugin/enums/group_application_type_enum.dart'; /// 群申请实体 class GroupApplicationEntity { /// 群ID late String groupID; /// 获取请求者 ID,请求加群:请求者,邀请加群:邀请人 late String fromUser; /// 用户昵称 String? fromUserNickName; /// 用户头像 String? fromUserFaceUrl; /// 获取处理者 ID, 请求加群:0,邀请加群:被邀请人 String? toUser; /// 获取群未决添加的时间,单位:秒 late int addTime; /// 获取请求者添加的附加信息 String? requestMsg; /// 获取处理者添加的附加信息,只有处理状态不为V2TIMGroupApplication#V2TIM_GROUP_APPLICATION_HANDLE_STATUS_UNHANDLED的时候有效 String? handledMsg; /// 获取群未决请求类型 late GroupApplicationTypeEnum type; /// 获取群未决处理状态 GroupApplicationHandlerStatusEnum? handleStatus; /// 获取群未决处理操作类型,只有处理状态不为V2TIMGroupApplication#V2TIM_GROUP_APPLICATION_HANDLE_STATUS_UNHANDLED的时候有效 GroupApplicationHandlerResultEnum? handleResult; GroupApplicationEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json['fromUser'] != null) fromUser = json['fromUser']; if (json['fromUserNickName'] != null) fromUserNickName = json['fromUserNickName']; if (json['fromUserFaceUrl'] != null) fromUserFaceUrl = json['fromUserFaceUrl']; if (json['toUser'] != null) toUser = json['toUser']; if (json['addTime'] != null) addTime = json['addTime']; if (json['requestMsg'] != null) requestMsg = json['requestMsg']; if (json['handledMsg'] != null) handledMsg = json['handledMsg']; if (json['type'] != null) type = GroupApplicationTypeTool.getByInt(json['type']); if (json['handleStatus'] != null) handleStatus = GroupApplicationHandlerStatusTool.getByInt(json['handleStatus']); if (json['handleResult'] != null) handleResult = GroupApplicationHandlerResultTool.getByInt(json['handleResult']); } } ================================================ FILE: lib/entity/group_application_processed_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; /// 群申请处理 class GroupApplicationProcessedEntity { /// 群ID late String groupID; /// 操作用户 GroupMemberEntity? opUser; /// 操作原因 String? opReason; /// 是否同意加入 bool? isAgreeJoin; GroupApplicationProcessedEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json['opReason'] != null) opReason = json['opReason']; if (json['isAgreeJoin'] != null) isAgreeJoin = json['isAgreeJoin']; if (json["opUser"] != null) opUser = GroupMemberEntity.fromJson(json['opUser']); } } ================================================ FILE: lib/entity/group_application_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_application_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 群申请列表结果实体 class GroupApplicationResultEntity { /// 未读申请数量 late int unreadCount; /// 加群的申请列表 late List groupApplicationList; GroupApplicationResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['unreadCount'] != null) unreadCount = json['unreadCount']; if (json['groupApplicationList'] != null) groupApplicationList = ListUtil.generateOBJList( json['groupApplicationList']); } } ================================================ FILE: lib/entity/group_at_info_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/group_at_type_enum.dart'; /// 群@信息实体 class GroupAtInfoEntity { /// Seq序列号 int? seq; /// @类型 GroupAtTypeEnum? atType; GroupAtInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['seq'] != null) seq = json["seq"]; if (json['atType'] != null) atType = GroupAtTypeTool.getByInt(json["atType"]); } } ================================================ FILE: lib/entity/group_attribute_changed_entity.dart ================================================ import 'dart:convert'; /// 群属性更新实体 class GroupAttributeChangedEntity { /// 群ID late String groupID; /// 属性对象 late Map attributes; GroupAttributeChangedEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json['attributes'] != null) attributes = (json["attributes"] as Map).cast(); } } ================================================ FILE: lib/entity/group_changed_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/group_info_changed_type_enum.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 群改变通知实体 class GroupChangedEntity { /// 群ID late String groupID; /// 群改变信息实体 late List changInfo; GroupChangedEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["changInfo"] != null) changInfo = ListUtil.generateOBJList(json['changInfo']); } } /// 群改变实体 class GroupChangedInfoEntity { /// 类型 late GroupInfoChangedTypeEnum type; /// Key String? key; /// Value String? value; GroupChangedInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['type'] != null) type = GroupInfoChangedTypeTool.getByInt(json['type']); if (json['key'] != null) key = json['key']; if (json['value'] != null) value = json['value']; } } ================================================ FILE: lib/entity/group_create_member_entity.dart ================================================ import 'package:tencent_im_plugin/enums/group_member_role_enum.dart'; /// 群创建时需要传递的群成员实体 class GroupCreateMemberEntity { /// 用户ID late String userID; /// 角色 GroupMemberRoleEnum? role; GroupCreateMemberEntity({ required this.userID, this.role, }); Map toJson() { final Map data = new Map(); data['userID'] = this.userID; if (this.role != null) data['role'] = GroupMemberRoleTool.toInt(this.role!); return data; } } ================================================ FILE: lib/entity/group_dismissed_or_recycled_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; /// 群解散或被回收通知实体 class GroupDismissedOrRecycledEntity { /// 群ID late String groupID; /// 操作用户 GroupMemberEntity? opUser; GroupDismissedOrRecycledEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["opUser"] != null) opUser = GroupMemberEntity.fromJson(json["opUser"]); } } ================================================ FILE: lib/entity/group_info_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/group_add_opt_enum.dart'; import 'package:tencent_im_plugin/enums/group_member_role_enum.dart'; import 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart'; import 'package:tencent_im_plugin/enums/group_type_enum.dart'; /// 群实体 class GroupInfoEntity { /// 群ID String? groupID; /// 群类型 GroupTypeEnum? groupType; /// 群名称 String? groupName; /// 群公告 String? notification; /// 群简介 String? introduction; /// 群头像 String? faceUrl; /// 是否设置了全员禁言 bool? allMuted; /// 群主ID String? owner; /// 创建时间 int? createTime; /// 加群审批类型。 GroupAddOptEnum? groupAddOpt; /// 群最近一次群资料修改时间 int? lastInfoTime; /// 群最近一次发消息时间 int? lastMessageTime; /// 群成员总数量 int? memberCount; /// 在线成员数量 int? onlineCount; /// 群成员角色 GroupMemberRoleEnum? role; /// 当前用户在此群组中的消息接收选项 ReceiveMessageOptEnum? recvOpt; /// 当前用户在此群中的加入时间 int? joinTime; /// 自定义字段 Map? customInfo; GroupInfoEntity({ this.groupID, this.groupType, this.groupName, this.notification, this.introduction, this.faceUrl, this.allMuted, this.groupAddOpt, this.customInfo, }); /// 创建群聊快速方法 GroupInfoEntity.create({ this.groupID, required this.groupName, required this.groupType, this.introduction, }); /// 更新群聊信息快速方法 GroupInfoEntity.update({ required this.groupID, this.groupName, this.notification, this.introduction, this.faceUrl, this.allMuted, this.groupAddOpt, this.customInfo, }); GroupInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json['groupType'] != null) groupType = GroupTypeTool.getByString(json["groupType"]); if (json['groupName'] != null) groupName = json['groupName']; if (json['notification'] != null) notification = json['notification']; if (json['introduction'] != null) introduction = json['introduction']; if (json['faceUrl'] != null) faceUrl = json['faceUrl']; if (json['allMuted'] != null) allMuted = json['allMuted']; if (json['owner'] != null) owner = json['owner']; if (json['createTime'] != null) createTime = json['createTime']; if (json['groupAddOpt'] != null) groupAddOpt = GroupAddOptTool.getByInt(json["groupAddOpt"]); if (json['lastInfoTime'] != null) lastInfoTime = json['lastInfoTime']; if (json['lastMessageTime'] != null) lastMessageTime = json['lastMessageTime']; if (json['memberCount'] != null) memberCount = json['memberCount']; if (json['onlineCount'] != null) onlineCount = json['onlineCount']; if (json['role'] != null) role = GroupMemberRoleTool.getByInt(json["role"]); if (json['recvOpt'] != null) recvOpt = ReceiveMessageOptTool.getByInt(json["recvOpt"]); if (json['joinTime'] != null) joinTime = json['joinTime']; if (json['customInfo'] != null) customInfo = (json['customInfo'] as Map).cast(); } Map toJson() { final Map data = new Map(); data['groupID'] = this.groupID; if (this.groupType != null) data['groupType'] = GroupTypeTool.toTypeString(this.groupType!); if (this.groupName != null) data['groupName'] = this.groupName; if (this.notification != null) data['notification'] = this.notification; if (this.introduction != null) data['introduction'] = this.introduction; if (this.faceUrl != null) data['faceUrl'] = this.faceUrl; if (this.allMuted != null) data['allMuted'] = this.allMuted; if (this.groupAddOpt != null) data['groupAddOpt'] = GroupAddOptTool.toInt(this.groupAddOpt!); if (this.customInfo != null) data['customInfo'] = this.customInfo; return data; } @override bool operator ==(Object other) => identical(this, other) || other is GroupInfoEntity && runtimeType == other.runtimeType && groupID == other.groupID; @override int get hashCode => groupID.hashCode; } ================================================ FILE: lib/entity/group_info_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_info_entity.dart'; /// 群信息结果实体 class GroupInfoResultEntity { /// 返回码,0代表成功,非零代表失败 late int resultCode; /// 返回消息描述 String? resultMessage; /// 群信息 GroupInfoEntity? groupInfo; GroupInfoResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['resultCode'] != null) resultCode = json['resultCode']; if (json['resultMessage'] != null) resultMessage = json['resultMessage']; if (json['groupInfo'] != null) groupInfo = GroupInfoEntity.fromJson(json['groupInfo']); } } ================================================ FILE: lib/entity/group_member_changed_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/list_util.dart'; /// 群成员改变通知实体 class GroupMemberChangedEntity { /// 群ID late String groupID; /// 群成员列表 late List changInfo; GroupMemberChangedEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["changInfo"] != null) changInfo = ListUtil.generateOBJList( json['changInfo']); } } /// 群成员改变信息实体 class GroupMemberChangedInfoEntity { /// 用户ID late String userID; /// 禁言时长 late int muteTime; GroupMemberChangedInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['muteTime'] != null) muteTime = json['muteTime']; } } ================================================ FILE: lib/entity/group_member_enter_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 群成员加入通知实体 class GroupMemberEnterEntity { /// 群ID late String groupID; /// 群成员列表 late List memberList; GroupMemberEnterEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["memberList"] != null) memberList = ListUtil.generateOBJList(json['memberList']); } } ================================================ FILE: lib/entity/group_member_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/group_member_role_enum.dart'; /// 群成员实体 class GroupMemberEntity { /// 用户ID late String userID; /// 用户昵称 String? nickName; /// 好友备注 String? friendRemark; /// 头像URL String? faceUrl; /// 角色 GroupMemberRoleEnum? role; /// 群成员禁言结束时间戳 int? muteUntil; /// 加入时间 int? joinTime; /// 自定义字段 Map? customInfo; /// 群成员名片 String? nameCard; GroupMemberEntity({ required this.userID, this.customInfo, this.nameCard, }); GroupMemberEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['nickName'] != null) nickName = json['nickName']; if (json['friendRemark'] != null) friendRemark = json['friendRemark']; if (json['faceUrl'] != null) faceUrl = json['faceUrl']; if (json['role'] != null) role = GroupMemberRoleTool.getByInt(json['role']); if (json['muteUntil'] != null) muteUntil = json['muteUntil']; if (json['joinTime'] != null) joinTime = json['joinTime']; if (json['customInfo'] != null) customInfo = (json['customInfo'] as Map).cast(); if (json['nameCard'] != null) nameCard = json['nameCard']; } Map toJson() { final Map data = new Map(); data['userID'] = this.userID; if (this.customInfo != null) data['customInfo'] = this.customInfo; if (this.nameCard != null) data['nameCard'] = this.nameCard; return data; } @override bool operator ==(Object other) => identical(this, other) || other is GroupMemberEntity && runtimeType == other.runtimeType && userID == other.userID; @override int get hashCode => userID.hashCode; } ================================================ FILE: lib/entity/group_member_info_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 群成员信息结果实体 class GroupMemberInfoResultEntity { /// 获取分页拉取的 seq。如果为 0 表示拉取结束。 late int nextSeq; /// 群信息 List? memberInfoList; GroupMemberInfoResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['nextSeq'] != null) nextSeq = json['nextSeq']; if (json['memberInfoList'] != null) memberInfoList = ListUtil.generateOBJList(json['memberInfoList']); } } ================================================ FILE: lib/entity/group_member_invited_or_kicked_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/list_util.dart'; /// 群成员邀请或踢出通知实体 class GroupMemberInvitedOrKickedEntity { /// 群ID late String groupID; /// 群成员列表信息 List? memberList; /// 操作用户 GroupMemberEntity? opUser; GroupMemberInvitedOrKickedEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["memberList"] != null) memberList = ListUtil.generateOBJList(json['memberList']); if (json["opUser"] != null) opUser = GroupMemberEntity.fromJson(json["opUser"]); } } ================================================ FILE: lib/entity/group_member_leave_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; /// 群成员离开通知实体 class GroupMemberLeaveEntity { /// 群ID late String groupID; /// 群成员信息 late GroupMemberEntity member; GroupMemberLeaveEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json["member"] != null) member = GroupMemberEntity.fromJson(json["member"]); } } ================================================ FILE: lib/entity/group_member_operation_result_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/operation_result_enum.dart'; /// 群成员操作结果实体 class GroupMemberOperationResultEntity { /// 操作结果 late OperationResultEnum result; /// 群成员ID late String memberID; GroupMemberOperationResultEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['result'] != null) result = OperationResultTool.getByInt(json['result']); if (json['memberID'] != null) memberID = json['memberID']; } } ================================================ FILE: lib/entity/group_receive_join_application_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; /// 群加入申请实体 class GroupReceiveJoinApplicationEntity { /// 群ID late String groupID; /// 群成员 GroupMemberEntity? member; /// 操作原因 String? opReason; GroupReceiveJoinApplicationEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json['opReason'] != null) opReason = json['opReason']; if (json["member"] != null) member = GroupMemberEntity.fromJson(json['member']); } } ================================================ FILE: lib/entity/group_receive_rest_entity.dart ================================================ import 'dart:convert'; /// 群接收到REST自定义信息通知实体 class GroupReceiveRESTEntity { /// 群ID late String groupID; /// 自定义数据 String? customData; GroupReceiveRESTEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['groupID'] != null) groupID = json['groupID']; if (json['customData'] != null) customData = json['customData']; } } ================================================ FILE: lib/entity/message_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/offline_push_info_entity.dart'; import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/enums/message_priority_enum.dart'; import 'package:tencent_im_plugin/enums/message_status_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 消息实体 class MessageEntity { /// 消息 ID late String msgID; /// 消息时间戳 int? timestamp; /// 消息发送者 userID String? sender; /// 消息发送者昵称 String? nickName; /// 好友备注。如果没有拉取过好友信息或者不是好友,返回 null String? friendRemark; /// 发送者头像 url String? faceUrl; /// 群组消息,nameCard 为发送者的群名片 String? nameCard; /// 群组消息,groupID 为接收消息的群组 ID,否则为 null String? groupID; /// 单聊消息,userID 为会话用户 ID,否则为 null。 假设自己和 userA 聊天,无论是自己发给 userA 的消息还是 userA 发给自己的消息,这里的 userID 均为 userA String? userID; /// 消息发送状态 MessageStatusEnum? status; /// 消息类型 MessageElemTypeEnum? elemType; /// 消息自定义数据(本地保存,不会发送到对端,程序卸载重装后失效) String? localCustomData; /// 消息自定义数据(本地保存,不会发送到对端,程序卸载重装后失效) int? localCustomInt; /// 消息发送者是否是自己 bool? self; /// 消息自己是否已读 bool? read; /// 消息对方是否已读(只有 C2C 消息有效) bool? peerRead; /// 消息优先级 MessagePriorityEnum? priority; /// 消息的离线推送信息 OfflinePushInfoEntity? offlinePushInfo; /// 群@用户列表 List? groupAtUserList; /// 消息的序列号 /// 群聊中的消息序列号云端生成,在群里是严格递增且唯一的。 单聊中的序列号是本地生成,不能保证严格递增且唯一。 int? seq; /// 描述信息,描述当前消息,可直接用于显示 String? note; /// 消息节点信息 MessageNode? node; /// 消息随机码 int? random; MessageEntity({ required this.msgID, this.timestamp, this.sender, this.nickName, this.friendRemark, this.faceUrl, this.nameCard, this.groupID, this.userID, required this.status, this.elemType, this.localCustomData, this.localCustomInt, this.self: true, this.read: true, this.peerRead: false, this.priority, this.offlinePushInfo, this.groupAtUserList, this.seq, this.note, this.node, this.random, }); MessageEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['msgID'] != null) msgID = json["msgID"]; if (json['timestamp'] != null) timestamp = json["timestamp"]; if (json['sender'] != null) sender = json["sender"]; if (json['nickName'] != null) nickName = json["nickName"]; if (json['friendRemark'] != null) friendRemark = json["friendRemark"]; if (json['faceUrl'] != null) faceUrl = json["faceUrl"]; if (json['nameCard'] != null) nameCard = json["nameCard"]; if (json['groupID'] != null) groupID = json["groupID"]; if (json['userID'] != null) userID = json["userID"]; if (json["status"] != null) status = MessageStatusTool.getByInt(json["status"]); if (json["elemType"] != null) elemType = MessageElemTypeTool.getByInt(json["elemType"]); if (json['localCustomData'] != null) localCustomData = json["localCustomData"]; if (json['localCustomInt'] != null) localCustomInt = json["localCustomInt"]; if (json["self"] != null) self = json["self"]; if (json["read"] != null) read = json["read"]; if (json["peerRead"] != null) peerRead = json["peerRead"]; if (json["priority"] != null) priority = MessagePriorityTool.getByInt(json["priority"]); if (json["offlinePushInfo"] != null) offlinePushInfo = OfflinePushInfoEntity.fromJson(json["offlinePushInfo"]); if (json['groupAtUserList'] != null) groupAtUserList = json["groupAtUserList"]?.cast(); if (json['seq'] != null) seq = json["seq"]; if (json['note'] != null) note = json["note"]; if (json['node'] != null) node = MessageElemTypeTool.getMessageNodeByMessageNodeType( elemType!, json["node"]); if (json['random'] != null) random = json["random"]; } Map toJson() { final Map data = new Map(); data['msgID'] = this.msgID; if (this.timestamp != null) data['timestamp'] = this.timestamp; if (this.sender != null) data['sender'] = this.sender; if (this.nickName != null) data['nickName'] = this.nickName; if (this.friendRemark != null) data['friendRemark'] = this.friendRemark; if (this.faceUrl != null) data['faceUrl'] = this.faceUrl; if (this.nameCard != null) data['nameCard'] = this.nameCard; if (this.groupID != null) data['groupID'] = this.groupID; if (this.userID != null) data['userID'] = this.userID; if (this.status != null) data['status'] = MessageStatusTool.toInt(this.status!); if (this.elemType != null) data['elemType'] = MessageElemTypeTool.toInt(this.elemType!); if (this.localCustomData != null) data['localCustomData'] = this.localCustomData; if (this.localCustomInt != null) data['localCustomInt'] = this.localCustomInt; if (this.self != null) data['self'] = this.self; if (this.read != null) data['read'] = this.read; if (this.peerRead != null) data['peerRead'] = this.peerRead; if (this.priority != null) data['priority'] = MessagePriorityTool.toInt(this.priority!); if (this.offlinePushInfo != null) data['offlinePushInfo'] = this.offlinePushInfo!.toJson(); if (this.groupAtUserList != null) data['groupAtUserList'] = this.groupAtUserList; if (this.seq != null) data['seq'] = this.seq; if (this.note != null) data['note'] = this.note; if (this.random != null) data['random'] = this.random; return data; } @override bool operator ==(Object other) => identical(this, other) || other is MessageEntity && runtimeType == other.runtimeType && msgID == other.msgID; @override int get hashCode => msgID.hashCode; } ================================================ FILE: lib/entity/message_receipt_entity.dart ================================================ import 'dart:convert'; /// 消息回执实体 class MessageReceiptEntity { /// 用户ID late String userID; /// 时间 int? timestamp; MessageReceiptEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json["userID"]; if (json['timestamp'] != null) timestamp = json["timestamp"]; } } ================================================ FILE: lib/entity/message_search_param.dart ================================================ // To parse this JSON data, do // // final messageSearchParam = messageSearchParamFromJson(jsonString); import 'dart:convert'; /// 消息搜索参数对象 class MessageSearchParam { MessageSearchParam({ this.conversationId, this.keyword, this.keywordMatchType, this.senderUserIds, this.messageTypes, this.searchTimePosition, this.searchTimePeriod, this.pageSize, this.pageIndex, }); /// 指定会话ID final String? conversationId; /// 指定关键字,最多支持5个 final List? keyword; /// 关键字匹配类型 final int? keywordMatchType; /// 发送人ID列表 final List? senderUserIds; /// 消息类型列表 final List? messageTypes; /// 搜索的起始时间点。默认为0即代表从现在开始搜索。UTC 时间戳,单位:秒 final int? searchTimePosition; /// 从起始时间点开始的过去时间范围,单位秒。默认为0即代表不限制时间范围,传24x60x60代表过去一天。 final int? searchTimePeriod; /// 每页结果数量:用于分页展示查找结果,如不希望分页可将其设置成 0,但如果结果太多,可能会带来性能问题。 final int? pageSize; /// 分页的页号:用于分页展示查找结果,从零开始起步。 比如:您希望每页展示 10 条结果,请按照如下规则调用: - 首次调用:通过参数 pageSize = 10, pageIndex = 0 调用 searchLocalMessage,从结果回调中的 totalCount 可以获知总共有多少条结果。 - 计算页数:可以获知总页数:totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1) 。 - 再次调用:可以通过指定参数 pageIndex (pageIndex < totalPage)返回后续页号的结果。 final int? pageIndex; factory MessageSearchParam.fromRawJson(String str) => MessageSearchParam.fromJson(json.decode(str)); String toRawJson() => json.encode(toJson()); factory MessageSearchParam.fromJson(Map json) => MessageSearchParam( conversationId: json["conversationID"] == null ? null : json["conversationID"], keyword: json["keyword"] == null ? null : List.from(json["keyword"].map((x) => x)), keywordMatchType: json["keywordMatchType"] == null ? null : json["keywordMatchType"], senderUserIds: json["senderUserIds"] == null ? null : List.from(json["senderUserIds"].map((x) => x)), messageTypes: json["messageTypes"] == null ? null : List.from(json["messageTypes"].map((x) => x)), searchTimePosition: json["searchTimePosition"] == null ? null : json["searchTimePosition"], searchTimePeriod: json["searchTimePeriod"] == null ? null : json["searchTimePeriod"], pageSize: json["pageSize"] == null ? null : json["pageSize"], pageIndex: json["pageIndex"] == null ? null : json["pageIndex"], ); Map toJson() => { "conversationID": conversationId == null ? null : conversationId, "keyword": keyword == null ? null : List.from(keyword!.map((x) => x)), "keywordMatchType": keywordMatchType == null ? null : keywordMatchType, "senderUserIds": senderUserIds == null ? null : List.from(senderUserIds!.map((x) => x)), "messageTypes": messageTypes == null ? null : List.from(messageTypes!.map((x) => x)), "searchTimePosition": searchTimePosition == null ? null : searchTimePosition, "searchTimePeriod": searchTimePeriod == null ? null : searchTimePeriod, "pageSize": pageSize == null ? null : pageSize, "pageIndex": pageIndex == null ? null : pageIndex, }; } ================================================ FILE: lib/entity/message_send_fail_entity.dart ================================================ import 'dart:convert'; /// 消息发送失败实体 class MessageSendFailEntity { /// 消息ID late String msgId; /// 错误码 late int code; /// 错误描述 String? desc; MessageSendFailEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['msgId'] != null) msgId = json["msgId"]; if (json['code'] != null) code = json["code"]; if (json['desc'] != null) desc = json["desc"]; } } ================================================ FILE: lib/entity/message_send_progress_entity.dart ================================================ import 'dart:convert'; /// 消息发送进度实体 class MessageSendProgressEntity { /// 消息ID late String msgId; /// 发送进度 late int progress; MessageSendProgressEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['msgId'] != null) msgId = json["msgId"]; if (json['progress'] != null) progress = json["progress"]; } } ================================================ FILE: lib/entity/offline_push_info_entity.dart ================================================ import 'dart:convert'; /// 离线推送信息实体 class OfflinePushInfoEntity { /// 通知栏标题 String? title; /// 通知栏内容 String? desc; /// 通知栏透传信息 String? ext; /// 离线推送声音设置(仅对 iOS 生效)。 当 sound = IOS_OFFLINE_PUSH_NO_SOUND,表示接收时不会播放声音。 如果要自定义 iOSSound,需要先把语音文件链接进 Xcode 工程,然后把语音文件名(带后缀)设置给 iOSSound。 String? iOSSound; /// 离线推送忽略 badge 计数(仅对 iOS 生效), 如果设置为 true,在 iOS 接收端,这条消息不会使 APP 的应用图标未读计数增加。 bool? ignoreIOSBadge; /// 离线推送设置 OPPO 手机 8.0 系统及以上的渠道 ID。 String? androidOPPOChannelID; /// 获取是否关闭离线推送状态。 bool? disablePush; OfflinePushInfoEntity({ this.title, this.desc, this.ext, this.iOSSound, this.ignoreIOSBadge, this.androidOPPOChannelID, this.disablePush, }); OfflinePushInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['title'] != null) title = json["title"]; if (json['desc'] != null) desc = json["desc"]; if (json['ext'] != null) ext = json["ext"]; if (json['iOSSound'] != null) iOSSound = json["iOSSound"]; if (json['ignoreIOSBadge'] != null) ignoreIOSBadge = json["ignoreIOSBadge"]; if (json['androidOPPOChannelID'] != null) androidOPPOChannelID = json["androidOPPOChannelID"]; if (json['disablePush'] != null) disablePush = json["disablePush"]; } Map toJson() { final Map data = new Map(); if (this.title != null) data['title'] = this.title; if (this.desc != null) data['desc'] = this.desc; if (this.ext != null) data['ext'] = this.ext; if (this.iOSSound != null) data['iOSSound'] = this.iOSSound; if (this.ignoreIOSBadge != null) data['ignoreIOSBadge'] = this.ignoreIOSBadge; if (this.androidOPPOChannelID != null) data['androidOPPOChannelID'] = this.androidOPPOChannelID; return data; } } ================================================ FILE: lib/entity/signaling_common_entity.dart ================================================ import 'dart:convert'; /// 信令通用实体 class SignalingCommonEntity { /// 邀请ID late String inviteID; /// 邀请人 String? inviter; /// 群ID String? groupID; /// 受邀人,一般是拒绝/接受时此内容才会有值 String? invitee; /// 被邀请人列表 List? inviteeList; /// 消息内容 String? data; SignalingCommonEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['inviteID'] != null) inviteID = json["inviteID"]; if (json['inviter'] != null) inviter = json["inviter"]; if (json['groupID'] != null) groupID = json["groupID"]; if (json['invitee'] != null) invitee = json["invitee"]; if (json['inviteeList'] != null) inviteeList = json["inviteeList"]?.cast(); if (json['data'] != null) this.data = json["data"]; } @override bool operator ==(Object other) => identical(this, other) || other is SignalingCommonEntity && runtimeType == other.runtimeType && inviteID == other.inviteID; @override int get hashCode => inviteID.hashCode; } ================================================ FILE: lib/entity/signaling_info_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/offline_push_info_entity.dart'; import 'package:tencent_im_plugin/enums/signaling_action_type_enum.dart'; import 'package:uuid/uuid.dart'; /// 信令信息实体 class SignalingInfoEntity { /// 邀请ID String? inviteID; /// 群ID String? groupID; /// 邀请人 String? inviter; /// 被邀请人 List? inviteeList; /// 数据 String? data; /// 超时 int? timeout; /// 类型 SignalingActionTypeEnum? actionType; /// ID int? businessID; /// 是否仅在线用户 bool? onlineUserOnly; /// 离线推送信息 OfflinePushInfoEntity? offlinePushInfo; SignalingInfoEntity({ this.inviteID, this.groupID, required this.inviter, required this.inviteeList, required this.data, this.timeout: 0, required this.actionType, this.businessID: 0, this.onlineUserOnly: false, }); SignalingInfoEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['inviteID'] != null) inviteID = json["inviteID"]; if (json['groupID'] != null) groupID = json["groupID"]; if (json['inviter'] != null) inviter = json["inviter"]; if (json['inviteeList'] != null) inviteeList = json["inviteeList"].cast(); if (json['data'] != null) this.data = json["data"]; if (json['timeout'] != null) timeout = json["timeout"]; if (json['actionType'] != null) if (json["actionType"] != null) actionType = SignalingActionTypeTool.getByInt(json["actionType"]); if (json['businessID'] != null) businessID = json["businessID"]; if (json['onlineUserOnly'] != null) onlineUserOnly = json["onlineUserOnly"]; if (json["offlinePushInfo"] != null) offlinePushInfo = OfflinePushInfoEntity.fromJson(json["offlinePushInfo"]); } Map toJson() { final Map data = new Map(); data['inviteID'] = this.inviteID ?? Uuid().v4().toString(); if (this.groupID != null) data['groupID'] = this.groupID; if (this.inviter != null) data['inviter'] = this.inviter; if (this.inviteeList != null) data['inviteeList'] = this.inviteeList; if (this.data != null) data['data'] = this.data; if (this.timeout != null) data['timeout'] = this.timeout; if (this.actionType != null) data['actionType'] = SignalingActionTypeTool.toInt(this.actionType!); if (this.businessID != null) data['businessID'] = this.businessID; if (this.onlineUserOnly != null) data['onlineUserOnly'] = this.onlineUserOnly; return data; } @override bool operator ==(Object other) => identical(this, other) || other is SignalingInfoEntity && runtimeType == other.runtimeType && inviteID == other.inviteID; @override int get hashCode => inviteID.hashCode; } ================================================ FILE: lib/entity/user_entity.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/user_allow_type_enum.dart'; import 'package:tencent_im_plugin/enums/user_gender_enum.dart'; /// 用户实体 class UserEntity { /// ID late String userID; /// 昵称 String? nickName; /// 头像 String? faceUrl; /// 签名 String? selfSignature; /// 性别 UserGenderEnum? gender; /// 角色 int? role; /// 等级 int? level; /// 生日 int? birthday; /// 好友验证方式 UserAllowTypeEnum? allowType; /// 自定义字段 Map? customInfo; UserEntity({ this.nickName, this.faceUrl, this.selfSignature, this.gender, this.role, this.level, this.allowType, this.customInfo, }); UserEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['userID'] != null) userID = json['userID']; if (json['nickName'] != null) nickName = json['nickName']; if (json['faceUrl'] != null) faceUrl = json['faceUrl']; if (json['selfSignature'] != null) selfSignature = json['selfSignature']; if (json['gender'] != null) gender = UserGenderTool.getByInt(json['gender']); if (json['role'] != null) role = json['role']; if (json['level'] != null) level = json['level']; if (json['birthday'] != null) birthday = json['birthday']; if (json['allowType'] != null) allowType = UserAllowTypeTool.getByInt(json['allowType']); if (json['customInfo'] != null) customInfo = (json['customInfo'] as Map).cast(); } Map toJson() { final Map data = new Map(); if (this.nickName != null) data['nickName'] = this.nickName; if (this.faceUrl != null) data['faceUrl'] = this.faceUrl; if (this.selfSignature != null) data['selfSignature'] = this.selfSignature; if (this.gender != null) data['gender'] = UserGenderTool.toInt(this.gender!); if (this.role != null) data['role'] = this.role; if (this.level != null) data['level'] = this.level; if (this.birthday != null) data['birthday'] = this.birthday; if (this.allowType != null) data['allowType'] = UserAllowTypeTool.toInt(this.allowType!); if (this.customInfo != null) data['customInfo'] = this.customInfo; return data; } @override bool operator ==(Object other) => identical(this, other) || other is UserEntity && runtimeType == other.runtimeType && userID == other.userID; @override int get hashCode => userID.hashCode; } ================================================ FILE: lib/entity_factory.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/entity/friend_application_entity.dart'; import 'package:tencent_im_plugin/entity/friend_application_result_entity.dart'; import 'package:tencent_im_plugin/entity/friend_group_entity.dart'; import 'package:tencent_im_plugin/entity/friend_info_entity.dart'; import 'package:tencent_im_plugin/entity/friend_info_result_entity.dart'; import 'package:tencent_im_plugin/entity/friend_operation_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_application_entity.dart'; import 'package:tencent_im_plugin/entity/group_at_info_entity.dart'; import 'package:tencent_im_plugin/entity/group_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_info_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_operation_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_info_entity.dart'; import 'package:tencent_im_plugin/entity/message_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/entity/message_receipt_entity.dart'; import 'package:tencent_im_plugin/entity/user_entity.dart'; import 'entity/conversation_entity.dart'; class EntityFactory { static T? generateOBJ(json) { if (json is String) { json = jsonDecode(json); } if (1 == 0) { return null; } else if (T.toString() == "GroupInfoEntity") { return GroupInfoEntity.fromJson(json) as T; } else if (T.toString() == "MessageEntity") { return MessageEntity.fromJson(json) as T; } else if (T.toString() == "GroupMemberEntity") { return GroupMemberEntity.fromJson(json) as T; } else if (T.toString() == "GroupInfoResultEntity") { return GroupInfoResultEntity.fromJson(json) as T; } else if (T.toString() == "GroupMemberOperationResultEntity") { return GroupMemberOperationResultEntity.fromJson(json) as T; } else if (T.toString() == "GroupApplicationEntity") { return GroupApplicationEntity.fromJson(json) as T; } else if (T.toString() == "ConversationEntity") { return ConversationEntity.fromJson(json) as T; } else if (T.toString() == "GroupAtInfoEntity") { return GroupAtInfoEntity.fromJson(json) as T; } else if (T.toString() == "UserEntity") { return UserEntity.fromJson(json) as T; } else if (T.toString() == "FriendOperationResultEntity") { return FriendOperationResultEntity.fromJson(json) as T; } else if (T.toString() == "FriendInfoEntity") { return FriendInfoEntity.fromJson(json) as T; } else if (T.toString() == "FriendInfoResultEntity") { return FriendInfoResultEntity.fromJson(json) as T; } else if (T.toString() == "FriendApplicationResultEntity") { return FriendApplicationResultEntity.fromJson(json) as T; } else if (T.toString() == "FriendApplicationEntity") { return FriendApplicationEntity.fromJson(json) as T; } else if (T.toString() == "FriendGroupEntity") { return FriendGroupEntity.fromJson(json) as T; } else if (T.toString() == "GroupChangedInfoEntity") { return GroupChangedInfoEntity.fromJson(json) as T; } else if (T.toString() == "GroupMemberChangedInfoEntity") { return GroupMemberChangedInfoEntity.fromJson(json) as T; } else if (T.toString() == "MessageReceiptEntity") { return MessageReceiptEntity.fromJson(json) as T; } else { return null; } } } ================================================ FILE: lib/enums/conversation_type_enum.dart ================================================ /// 会话类型枚举 enum ConversationTypeEnum { /// 非法类型 Invalid, /// 单聊 C2C, /// 群聊 Group, } class ConversationTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static ConversationTypeEnum getByInt(int index) => ConversationTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(ConversationTypeEnum level) => level.index; } ================================================ FILE: lib/enums/download_type_enum.dart ================================================ /// 下载类型枚举 enum DownloadTypeEnum { /// 语音 Sound, /// 视频 Video, /// 视频缩略图 VideoThumbnail, /// 文件对象 File, } class DownloadTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static DownloadTypeEnum getByInt(int index) => DownloadTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(DownloadTypeEnum level) => level.index; } ================================================ FILE: lib/enums/friend_application_agree_type_enum.dart ================================================ /// 好友申请接收时类型枚举 enum FriendApplicationAgreeTypeEnum { // 同意加好友(建立单向好友) Agree, // 同意加好友并加对方为好友(建立双向好友) AgreeAndAdd, } /// 枚举工具 class FriendApplicationAgreeTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static FriendApplicationAgreeTypeEnum getByInt(int index) => FriendApplicationAgreeTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(FriendApplicationAgreeTypeEnum level) => level.index; } ================================================ FILE: lib/enums/friend_application_type_enum.dart ================================================ /// 好友申请类型枚举 enum FriendApplicationTypeEnum { // 别人发给我的加好友请求 ComeIn, // 我发给别人的加好友请求 SendOut, // 别人发给我的和我发给别人的加好友请求。仅在拉取时有效。 Both, } /// 枚举工具 class FriendApplicationTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static FriendApplicationTypeEnum getByInt(int index) => FriendApplicationTypeEnum.values[index - 1]; /// 将枚举转换为整型 static int toInt(FriendApplicationTypeEnum level) => level.index + 1; } ================================================ FILE: lib/enums/friend_relation_type_enum.dart ================================================ /// 好友关系枚举 enum FriendRelationTypeEnum { // 不是好友 None, // 在我的好友列表 MyFriendList, // 我在对方好友列表 OtherFriendList, // 互为好友 BothWay, } /// 枚举工具 class FriendRelationTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static FriendRelationTypeEnum getByInt(int index) => FriendRelationTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(FriendRelationTypeEnum level) => level.index; } ================================================ FILE: lib/enums/friend_status_enum.dart ================================================ /// 好友状态枚举 enum FriendStatusEnum { /// 操作成功 SUCC, /// 请求参数错误,请根据错误描述检查请求是否正确 PARAM_INVALID, /// 加好友、响应好友时有效:自己的好友数已达系统上限 SELF_FRIEND_FULL, /// 加好友、响应好友时有效:对方的好友数已达系统上限 THEIR_FRIEND_FULL, /// 加好友时有效:被加好友在自己的黑名单中 IN_SELF_BLACK_LIST, /// 加好友时有效:被加好友设置为禁止加好友 FRIEND_SIDE_FORBID_ADD, /// 加好友时有效:已被被添加好友设置为黑名单 IN_OTHER_SIDE_BLACK_LIST, /// 加好友时有效:等待好友审核同意 PENDING } /// 枚举工具 class FriendStatusEnumTool { /// 根据数标获得枚举 static FriendStatusEnum? getEnumByIndex(index) { switch (index) { case 0: return FriendStatusEnum.SUCC; case 30001: return FriendStatusEnum.PARAM_INVALID; case 30010: return FriendStatusEnum.SELF_FRIEND_FULL; case 30014: return FriendStatusEnum.THEIR_FRIEND_FULL; case 30515: return FriendStatusEnum.IN_SELF_BLACK_LIST; case 30516: return FriendStatusEnum.FRIEND_SIDE_FORBID_ADD; case 30525: return FriendStatusEnum.IN_OTHER_SIDE_BLACK_LIST; case 30539: return FriendStatusEnum.PENDING; default: return null; } } /// 根据枚举获得数标 static int? getIndexByEnum(e) { switch (e) { case FriendStatusEnum.SUCC: return 0; case FriendStatusEnum.PARAM_INVALID: return 30001; case FriendStatusEnum.SELF_FRIEND_FULL: return 30010; case FriendStatusEnum.THEIR_FRIEND_FULL: return 30514; case FriendStatusEnum.IN_SELF_BLACK_LIST: return 30515; case FriendStatusEnum.FRIEND_SIDE_FORBID_ADD: return 30516; case FriendStatusEnum.IN_OTHER_SIDE_BLACK_LIST: return 30525; case FriendStatusEnum.PENDING: return 30539; default: return null; } } } ================================================ FILE: lib/enums/friend_type_enum.dart ================================================ /// 好友类型枚举 enum FriendTypeEnum { // 单项加好友 Single, // 双向加好友 Both, } /// 枚举工具 class FriendTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static FriendTypeEnum getByInt(int index) => FriendTypeEnum.values[index - 1]; /// 将枚举转换为整型 static int toInt(FriendTypeEnum level) => level.index + 1; } ================================================ FILE: lib/enums/get_message_type_enum.dart ================================================ /// 获得消息类型枚举 enum GetMessageTypeEnum { // 云端更老的消息 GetCloudOlderMsg, // 云端更新的消息 GetCloudNewerMsg, // 本地更老的消息 GetLocalOlderMsg, // 本地更新的消息 GetLocalNewerMsg, } /// 枚举工具 class GetMessageTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GetMessageTypeEnum getByInt(int index) => GetMessageTypeEnum.values[index - 1]; /// 将枚举转换为整型 static int toInt(GetMessageTypeEnum level) => level.index + 1; } ================================================ FILE: lib/enums/group_add_opt_enum.dart ================================================ /// 加群选项 enum GroupAddOptEnum { /// 禁止加群 Forbid, /// 需要管理员审批 Auth, /// 自由加入 Any, } class GroupAddOptTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupAddOptEnum getByInt(int index) => GroupAddOptEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupAddOptEnum level) => level.index; } ================================================ FILE: lib/enums/group_application_handler_result_enum.dart ================================================ /// 群申请处理结果枚举 enum GroupApplicationHandlerResultEnum { /// 拒绝 Refuse, /// 接收 Agree, } class GroupApplicationHandlerResultTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupApplicationHandlerResultEnum getByInt(int index) => GroupApplicationHandlerResultEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupApplicationHandlerResultEnum level) => level.index; } ================================================ FILE: lib/enums/group_application_handler_status_enum.dart ================================================ /// 群申请处理状态枚举 enum GroupApplicationHandlerStatusEnum { /// 未处理 Unhandled, /// 其他人处理 ByOther, /// 自己已处理 BySelf, } class GroupApplicationHandlerStatusTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupApplicationHandlerStatusEnum getByInt(int index) => GroupApplicationHandlerStatusEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupApplicationHandlerStatusEnum level) => level.index; } ================================================ FILE: lib/enums/group_application_type_enum.dart ================================================ /// 群申请类型枚举 enum GroupApplicationTypeEnum { /// 主动申请 Join, /// 被邀请 Invite, } class GroupApplicationTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupApplicationTypeEnum getByInt(int index) => GroupApplicationTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupApplicationTypeEnum level) => level.index; } ================================================ FILE: lib/enums/group_at_type_enum.dart ================================================ /// 群@类型枚举 enum GroupAtTypeEnum { /// 非法类型 Unknown, /// @我 AtMe, /// @所有人 AtAll, /// @群里所有人,并单独@我 AtAllAtMe } class GroupAtTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupAtTypeEnum getByInt(int index) => GroupAtTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupAtTypeEnum level) => level.index; } ================================================ FILE: lib/enums/group_info_changed_type_enum.dart ================================================ /// 群信息改变类型枚举 enum GroupInfoChangedTypeEnum { /// 非法值 Invalid, /// 群名 Name, /// 群简介 Introduction, /// 群公告 Notification, /// 群头像 FaceUrl, /// 群主 Owner, /// 自定义字段 Custom, } class GroupInfoChangedTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupInfoChangedTypeEnum getByInt(int index) => GroupInfoChangedTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupInfoChangedTypeEnum level) => level.index; } ================================================ FILE: lib/enums/group_member_filter_enum.dart ================================================ /// 群成员过滤枚举 enum GroupMemberFilterEnum { /// 所有类型 All, /// 群主 Owner, /// 群管理员 Admin, /// 普通群成员 Common, } class GroupMemberFilterTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupMemberFilterEnum getByInt(int index) { switch (index) { case 0: return GroupMemberFilterEnum.All; case 1: return GroupMemberFilterEnum.Owner; case 2: return GroupMemberFilterEnum.Admin; case 4: return GroupMemberFilterEnum.Common; } throw ArgumentError("参数异常"); } /// 将枚举转换为整型 static int toInt(GroupMemberFilterEnum role) { switch (role) { case GroupMemberFilterEnum.All: return 0; case GroupMemberFilterEnum.Owner: return 1; case GroupMemberFilterEnum.Admin: return 2; case GroupMemberFilterEnum.Common: return 4; } } } ================================================ FILE: lib/enums/group_member_role_enum.dart ================================================ /// 群成员角色枚举 enum GroupMemberRoleEnum { /// 未定义 Undefined, /// 群成员 Member, /// 群管理员 Admin, /// 群主 Owner, } class GroupMemberRoleTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupMemberRoleEnum getByInt(int index) { switch (index) { case 0: return GroupMemberRoleEnum.Undefined; case 200: return GroupMemberRoleEnum.Member; case 300: return GroupMemberRoleEnum.Admin; case 400: return GroupMemberRoleEnum.Owner; } throw ArgumentError("参数异常"); } /// 将枚举转换为整型 static int toInt(GroupMemberRoleEnum role) { switch (role) { case GroupMemberRoleEnum.Undefined: return 0; case GroupMemberRoleEnum.Member: return 200; case GroupMemberRoleEnum.Admin: return 300; case GroupMemberRoleEnum.Owner: return 400; } } } ================================================ FILE: lib/enums/group_system_type.dart ================================================ /// 群系统提示类型 enum GroupSystemType { INVALID, ADD_GROUP_REQUEST_TYPE, ADD_GROUP_ACCEPT_TYPE, ADD_GROUP_REFUSE_TYPE, KICK_OFF_FROM_GROUP_TYPE, DELETE_GROUP_TYPE, CREATE_GROUP_TYPE, INVITED_TO_GROUP_TYPE, QUIT_GROUP_TYPE, GRANT_ADMIN_TYPE, CANCEL_ADMIN_TYPE, REVOKE_GROUP_TYPE, INVITE_TO_GROUP_REQUEST_TYPE, INVITATION_ACCEPTED_TYPE, INVITATION_REFUSED_TYPE, CUSTOM_INFO, } class GroupSystemTypeTool { /// 根据int值获得枚举类型 static GroupSystemType? intToGroupSystemType(int value) { switch (value) { case 0: return GroupSystemType.INVALID; case 1: return GroupSystemType.ADD_GROUP_REQUEST_TYPE; case 2: return GroupSystemType.ADD_GROUP_ACCEPT_TYPE; case 3: return GroupSystemType.ADD_GROUP_REFUSE_TYPE; case 4: return GroupSystemType.KICK_OFF_FROM_GROUP_TYPE; case 5: return GroupSystemType.DELETE_GROUP_TYPE; case 6: return GroupSystemType.CREATE_GROUP_TYPE; case 7: return GroupSystemType.INVITED_TO_GROUP_TYPE; case 8: return GroupSystemType.QUIT_GROUP_TYPE; case 9: return GroupSystemType.GRANT_ADMIN_TYPE; case 10: return GroupSystemType.CANCEL_ADMIN_TYPE; case 11: return GroupSystemType.REVOKE_GROUP_TYPE; case 12: return GroupSystemType.INVITE_TO_GROUP_REQUEST_TYPE; case 13: return GroupSystemType.INVITATION_ACCEPTED_TYPE; case 14: return GroupSystemType.INVITATION_REFUSED_TYPE; case 255: return GroupSystemType.CUSTOM_INFO; } return null; } } ================================================ FILE: lib/enums/group_tips_group_info_type.dart ================================================ /// 群资料变更消息类型 enum GroupTipsGroupInfoType { /// 非法值 Invalid, /// 修改群名称 ModifyName, /// 修改群简介 ModifyIntroduction, /// 修改群公告 ModifyNotification, /// 修改群头像URL ModifyFaceUrl, /// 修改群主 ModifyOwner, /// 修改群自定义字段 ModifyCustom, } ================================================ FILE: lib/enums/group_tips_type_enum.dart ================================================ /// 群组事件通知类型 enum GroupTipsTypeEnum { /// 非法 Invalid, /// 主动入群(memberList 加入群组,非 Work 群有效) Join, /// 被邀请入群(opMember 邀请 memberList 入群,Work 群有效) Invite, /// 退出群组 Quit, /// 踢出群 (opMember 把 memberList 踢出群组) Kicked, /// 设置管理员 (opMember 把 memberList 设置为管理员) Admin, /// 取消管理员 (opMember 取消 memberList 管理员身份) CancelAdmin, /// 群资料变更 (opMember 修改群资料:groupName & introduction & notification & faceUrl & owner & custom) GroupInfoChange, /// 群成员资料变更 (opMember 修改群成员资料:muteTime) MemberInfoChange, } /// 枚举工具 class GroupTipsTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static GroupTipsTypeEnum getByInt(int index) => GroupTipsTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(GroupTipsTypeEnum data) => data.index; } ================================================ FILE: lib/enums/group_type_enum.dart ================================================ import 'package:tencent_im_plugin/utils/enum_util.dart'; /// 群类型 enum GroupTypeEnum { /// 工作群 Work, /// 公开群 Public, /// 会议群 Meeting, /// 直播群 AVChatRoom, } class GroupTypeTool { /// 根据字符串类型值获得枚举 /// [type] 字符串常量 /// [Return] 枚举对象 static GroupTypeEnum? getByString(String type) => EnumUtil.nameOf(GroupTypeEnum.values, type); /// 将枚举转换为整型 static String toTypeString(GroupTypeEnum type) => EnumUtil.getEnumName(type); } ================================================ FILE: lib/enums/image_type_enum.dart ================================================ import 'dart:io'; /// 图片类型 /// 由于腾讯云 Android 和 IOS 的 V2TIMImageType 对象不相同,所以需要单独解析 /// Android 的下标为 0、1、2,IOS的为 1、2、4 enum ImageTypeEnum { /// 原图 Original, /// 缩略图 Thumb, /// 大图 Large, } class ImageTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static ImageTypeEnum getByInt(int /*!*/ index) { // 单独解析Android if (Platform.isAndroid) { return ImageTypeEnum.values[index]; } switch (index) { case 1: return ImageTypeEnum.Original; case 2: return ImageTypeEnum.Thumb; case 4: return ImageTypeEnum.Large; } throw ArgumentError("参数异常"); } /// 将枚举转换为整型 static int toInt(ImageTypeEnum data) { // 单独解析Android if (Platform.isAndroid) { return data.index; } switch (data) { case ImageTypeEnum.Original: return 1; case ImageTypeEnum.Thumb: return 2; case ImageTypeEnum.Large: return 4; } } } ================================================ FILE: lib/enums/log_print_level.dart ================================================ /// 日志打印等级 enum LogPrintLevel { none, debug, info, warn, error, } class LogPrintLevelTool { /// 将枚举转换为整型 static int? toInt(LogPrintLevel level) { switch (level) { case LogPrintLevel.none: return 0; case LogPrintLevel.debug: return 3; case LogPrintLevel.info: return 4; case LogPrintLevel.warn: return 5; case LogPrintLevel.error: return 6; } } } ================================================ FILE: lib/enums/login_status_enum.dart ================================================ /// 登录状态枚举 enum LoginStatusEnum { // 已登录 Logined, // 登录中 Logining, // 未登录 Logout, } class LoginStatusTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static LoginStatusEnum getByInt(int index) => LoginStatusEnum.values[index - 1]; } ================================================ FILE: lib/enums/message_elem_type_enum.dart ================================================ import 'package:tencent_im_plugin/message_node/custom_message_node.dart'; import 'package:tencent_im_plugin/message_node/face_message_node.dart'; import 'package:tencent_im_plugin/message_node/file_message_node.dart'; import 'package:tencent_im_plugin/message_node/group_tips_message_node.dart'; import 'package:tencent_im_plugin/message_node/image_message_node.dart'; import 'package:tencent_im_plugin/message_node/location_message_node.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; import 'package:tencent_im_plugin/message_node/sound_message_node.dart'; import 'package:tencent_im_plugin/message_node/text_message_node.dart'; import 'package:tencent_im_plugin/message_node/video_message_node.dart'; /// 消息节点类型 enum MessageElemTypeEnum { // 没有元素 None, // 文本 Text, // 自定义 Custom, // 图片 Image, // 语音 Sound, // 视频 Video, // 文件 File, // 位置 Location, // 表情 Face, // 群提示 GroupTips, } class MessageElemTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static MessageElemTypeEnum getByInt(int index) => MessageElemTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(MessageElemTypeEnum level) => level.index; /// 根据消息节点类型获得消息节点 /// [nodeType] 节点类型 /// [json] json值 static MessageNode? getMessageNodeByMessageNodeType( MessageElemTypeEnum nodeType, Map json) { switch (nodeType) { case MessageElemTypeEnum.None: break; case MessageElemTypeEnum.Text: return TextMessageNode.fromJson(json); case MessageElemTypeEnum.Custom: return CustomMessageNode.fromJson(json); case MessageElemTypeEnum.Image: return ImageMessageNode.fromJson(json); case MessageElemTypeEnum.Sound: return SoundMessageNode.fromJson(json); case MessageElemTypeEnum.Video: return VideoMessageNode.fromJson(json); case MessageElemTypeEnum.File: return FileMessageNode.fromJson(json); case MessageElemTypeEnum.Location: return LocationMessageNode.fromJson(json); case MessageElemTypeEnum.Face: return FaceMessageNode.fromJson(json); case MessageElemTypeEnum.GroupTips: return GroupTipsMessageNode.fromJson(json); } return null; } } ================================================ FILE: lib/enums/message_priority_enum.dart ================================================ /// 消息优先级枚举 enum MessagePriorityEnum { // 默认为普通优先级 Default, // 高优先级,一般用于礼物等重要消息 Hign, // 普通优先级,一般用于普通消息 Normal, // 低优先级,一般用于点赞消息 Low, // 未知,保留状态,Android部分场景会出现 Unknown, } class MessagePriorityTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static MessagePriorityEnum getByInt(int index) => MessagePriorityEnum.values[index]; /// 将枚举转换为整型 static int toInt(MessagePriorityEnum level) => level.index; } ================================================ FILE: lib/enums/message_status_enum.dart ================================================ /// 消息状态 enum MessageStatusEnum { /// 未知 Unknown, /// 发送中 Sending, /// 发送成功 SendSucc, /// 发送失败 SendFail, /// 删除 HasDeleted, /// 导入到本地的消息 Imported, /// 已撤回 HasRevoked, } class MessageStatusTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static MessageStatusEnum getByInt(int index) { switch (index) { case 0: return MessageStatusEnum.Unknown; case 1: return MessageStatusEnum.Sending; case 2: return MessageStatusEnum.SendSucc; case 3: return MessageStatusEnum.SendFail; case 4: return MessageStatusEnum.HasDeleted; case 5: return MessageStatusEnum.Imported; case 6: return MessageStatusEnum.HasRevoked; } throw ArgumentError("参数异常"); } /// 将枚举转换为整型 static int toInt(MessageStatusEnum status) { switch (status) { case MessageStatusEnum.Unknown: return 0; case MessageStatusEnum.Sending: return 1; case MessageStatusEnum.SendSucc: return 2; case MessageStatusEnum.SendFail: return 3; case MessageStatusEnum.HasDeleted: return 4; case MessageStatusEnum.Imported: return 5; case MessageStatusEnum.HasRevoked: return 6; } } } ================================================ FILE: lib/enums/operation_result_enum.dart ================================================ /// 操作结果枚举 enum OperationResultEnum { /// 操作失败 Fail, /// 操作成功 Succ, /// 无效操作 Invalid, /// 等待处理 Pending, } class OperationResultTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static OperationResultEnum getByInt(int index) => OperationResultEnum.values[index]; /// 将枚举转换为整型 static int toInt(OperationResultEnum level) => level.index; } ================================================ FILE: lib/enums/pendency_examine_type_enum.dart ================================================ /// 未决审核类型枚举 enum PendencyExamineTypeEnum { // 同意加好友(建立单向好友) AGREE, // 同意加好友并加对方为好友(建立双向好友) AGREE_AND_ADD, // 拒绝对方好友请求 REJECT, } /// 枚举工具 class PendencyExamineTypeEnumTool { /// 根据数标获得枚举 static PendencyExamineTypeEnum? getEnumByIndex(index) { switch (index) { case 0: return PendencyExamineTypeEnum.AGREE; case 1: return PendencyExamineTypeEnum.AGREE_AND_ADD; case 2: return PendencyExamineTypeEnum.REJECT; default: return null; } } /// 根据枚举获得数标 static int? getIndexByEnum(e) { switch (e) { case PendencyExamineTypeEnum.AGREE: return 0; case PendencyExamineTypeEnum.AGREE_AND_ADD: return 1; case PendencyExamineTypeEnum.REJECT: return 2; default: return null; } } } ================================================ FILE: lib/enums/pendency_type_enum.dart ================================================ /// 未决类型 enum PendencyTypeEnum { /// 别人发给我的未决请求 COME_IN, /// 我发给别人的未决请求 SEND_OUT, /// 别人发给我的以及我发给别人的所有未决请求,仅在拉取时有效。 BOTH, } /// 枚举工具 class PendencyTypeTool { /// 根据数标获得枚举 static PendencyTypeEnum? getEnumByIndex(index) { switch (index) { case 1: return PendencyTypeEnum.COME_IN; case 2: return PendencyTypeEnum.SEND_OUT; case 3: return PendencyTypeEnum.BOTH; default: return null; } } /// 根据枚举获得数标 static int? getIndexByEnum(e) { switch (e) { case PendencyTypeEnum.COME_IN: return 1; case PendencyTypeEnum.SEND_OUT: return 2; case PendencyTypeEnum.BOTH: return 3; default: return null; } } } ================================================ FILE: lib/enums/receive_message_opt_enum.dart ================================================ /// 接收消息选项 enum ReceiveMessageOptEnum { /// 在线正常接收消息,离线时会有厂商的离线推送通知 ReceiveAndNotify, /// 不会接收到消息 NotReceive, /// 在线正常接收消息,离线不会有推送通知 ReceiveNotNotify, } class ReceiveMessageOptTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static ReceiveMessageOptEnum getByInt(int index) => ReceiveMessageOptEnum.values[index]; /// 将枚举转换为整型 static int toInt(ReceiveMessageOptEnum level) => level.index; } ================================================ FILE: lib/enums/signaling_action_type_enum.dart ================================================ /// 信令操作类型枚举 enum SignalingActionTypeEnum { // 邀请方发起邀请 Invite, // 邀请方取消邀请 Cancel, // 被邀请方接受邀请 Accept, // 被邀请方拒绝邀请 Reject, // 邀请超时 Timeout } class SignalingActionTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static SignalingActionTypeEnum getByInt(int index) => SignalingActionTypeEnum.values[index - 1]; /// 将枚举转换为整型 static int toInt(SignalingActionTypeEnum level) => level.index + 1; } ================================================ FILE: lib/enums/sns_tips_type.dart ================================================ /// 关系链变更类型 enum SnsTipsType { /// 未知 INVALID, /// 增加好友消息 ADD_FRIEND, /// 删除好友 DEL_FRIEND, /// 增加好友申请 ADD_FRIEND_REQ, /// 删除好友申请 DEL_FRIEND_REQ, /// 添加黑名单 ADD_BLACKLIST, /// 删除黑名单 DEL_BLACKLIST, /// 未决已读上报 PENDENCY_REPORT, /// 关系链资料变更 SNS_PROFILE_CHANGE, /// 推荐数据增加 ADD_RECOMMEND, /// 推荐数据减少 DEL_RECOMMEND, /// 已决增加 ADD_DECIDE, /// 已决减少 DEL_DECIDE, /// 推荐已读上报 RECOMMEND_REPORT, /// 已决已读上报 DECIDE_REPORT } ================================================ FILE: lib/enums/tencent_im_listener_type_enum.dart ================================================ /// 监听器类型枚举 enum TencentImListenerTypeEnum { /// 新消息通知 NewMessage, /// C2C已读回执 C2CReadReceipt, /// 消息撤回 MessageRevoked, /// 同步服务开始 SyncServerStart, /// 同步服务完成 SyncServerFinish, /// 同步服务失败 SyncServerFailed, /// 新会话 NewConversation, /// 会话刷新 ConversationChanged, /// 好友申请新增通知 FriendApplicationListAdded, /// 好友申请删除通知 FriendApplicationListDeleted, /// 好友申请已读通知 FriendApplicationListRead, /// 好友新增通知 FriendListAdded, /// 好友删除通知 FriendListDeleted, /// 黑名单新增通知 BlackListAdd, /// 黑名单删除通知 BlackListDeleted, /// 好友资料更新通知 FriendInfoChanged, /// 有用户加入群 MemberEnter, /// 有用户离开群 MemberLeave, /// 有用户被拉入群 MemberInvited, /// 有用户被踢出群 MemberKicked, /// 群成员信息被修改 MemberInfoChanged, /// 创建群 GroupCreated, /// 群被解散 GroupDismissed, /// 群被回收 GroupRecycled, /// 群信息被修改 GroupInfoChanged, /// 有新的加群申请 ReceiveJoinApplication, /// 加群信息已被管理员处理 ApplicationProcessed, /// 指定管理员身份 GrantAdministrator, /// 取消管理员身份 RevokeAdministrator, /// 主动退出群组 QuitFromGroup, /// 收到 RESTAPI 下发的自定义系统消息 ReceiveRESTCustomData, /// 收到群属性更新的回调 GroupAttributeChanged, /// 正在连接到腾讯云服务器 Connecting, /// 网络连接成功 ConnectSuccess, /// 网络连接失败 ConnectFailed, /// 踢下线 KickedOffline, /// 当前用户的资料发生了更新 SelfInfoUpdated, /// 用户登录的 userSig 过期(用户需要重新获取 userSig 后登录) UserSigExpired, /// 收到信令邀请 ReceiveNewInvitation, /// 信令被邀请者接受邀请 InviteeAccepted, /// 信令被邀请者拒绝邀请 InviteeRejected, /// 信令邀请被取消 InvitationCancelled, /// 信令邀请超时 InvitationTimeout, /// 下载进度 DownloadProgress, /// 消息发送成功 MessageSendSucc, /// 消息发送失败 MessageSendFail, /// 消息发送进度更新 MessageSendProgress, } ================================================ FILE: lib/enums/user_allow_type_enum.dart ================================================ /// 用户验证方式枚举 enum UserAllowTypeEnum { // 允许任何人 AllowAny, // 需要确认 NeedConfirm, // 拒绝任何人 DenyAny, } class UserAllowTypeTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static UserAllowTypeEnum getByInt(int index) => UserAllowTypeEnum.values[index]; /// 将枚举转换为整型 static int toInt(UserAllowTypeEnum level) => level.index; } ================================================ FILE: lib/enums/user_gender_enum.dart ================================================ /// 用户性别枚举 enum UserGenderEnum { // 未知 Unknown, // 男 Male, // 女 Female, } class UserGenderTool { /// 根据Int类型值获得枚举 /// [index] Int常量 /// [Return] 枚举对象 static UserGenderEnum getByInt(int index) => UserGenderEnum.values[index]; /// 将枚举转换为整型 static int toInt(UserGenderEnum level) => level.index; } ================================================ FILE: lib/list_util.dart ================================================ import 'dart:convert'; import 'entity_factory.dart'; class ListUtil { /// 根据泛型生成集合 static List generateOBJList(arr) { if (arr is String) { arr = jsonDecode(arr); } List data = []; for (var item in arr) { var d = EntityFactory.generateOBJ(item); if (d != null) { data.add(d); } } return data; } } ================================================ FILE: lib/listener/tencent_im_plugin_listener.dart ================================================ import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import 'package:tencent_im_plugin/entity/conversation_entity.dart'; import 'package:tencent_im_plugin/entity/download_progress_entity.dart'; import 'package:tencent_im_plugin/entity/error_entity.dart'; import 'package:tencent_im_plugin/entity/friend_application_entity.dart'; import 'package:tencent_im_plugin/entity/friend_info_entity.dart'; import 'package:tencent_im_plugin/entity/group_administrator_op_entity.dart'; import 'package:tencent_im_plugin/entity/group_application_processed_entity.dart'; import 'package:tencent_im_plugin/entity/group_attribute_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_dismissed_or_recycled_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_enter_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_invited_or_kicked_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_leave_entity.dart'; import 'package:tencent_im_plugin/entity/group_receive_join_application_entity.dart'; import 'package:tencent_im_plugin/entity/group_receive_rest_entity.dart'; import 'package:tencent_im_plugin/entity/message_entity.dart'; import 'package:tencent_im_plugin/entity/message_receipt_entity.dart'; import 'package:tencent_im_plugin/entity/message_send_fail_entity.dart'; import 'package:tencent_im_plugin/entity/message_send_progress_entity.dart'; import 'package:tencent_im_plugin/entity/signaling_common_entity.dart'; import 'package:tencent_im_plugin/entity/user_entity.dart'; import 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart'; import 'package:tencent_im_plugin/list_util.dart'; import 'package:tencent_im_plugin/utils/enum_util.dart'; /// 监听器对象 class TencentImPluginListener { /// 日志对象 static Logger _logger = Logger(); /// 监听器列表 static Set listeners = Set(); TencentImPluginListener(MethodChannel channel) { // 绑定监听器 channel.setMethodCallHandler((methodCall) async { // 解析参数 Map arguments = jsonDecode(methodCall.arguments); switch (methodCall.method) { case 'onListener': // 获得原始类型和参数 TencentImListenerTypeEnum type = EnumUtil.nameOf( TencentImListenerTypeEnum.values, arguments['type'])!; var originalParams = arguments['params']; // 封装回调类型和参数 var params = originalParams; try { switch (type) { case TencentImListenerTypeEnum.NewMessage: params = MessageEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.C2CReadReceipt: params = ListUtil.generateOBJList( originalParams); break; case TencentImListenerTypeEnum.MessageRevoked: params = originalParams; break; case TencentImListenerTypeEnum.SyncServerStart: break; case TencentImListenerTypeEnum.SyncServerFinish: break; case TencentImListenerTypeEnum.SyncServerFailed: break; case TencentImListenerTypeEnum.NewConversation: params = ListUtil.generateOBJList( originalParams); break; case TencentImListenerTypeEnum.ConversationChanged: params = ListUtil.generateOBJList( originalParams); break; case TencentImListenerTypeEnum.FriendApplicationListAdded: params = ListUtil.generateOBJList( originalParams); break; case TencentImListenerTypeEnum.FriendApplicationListDeleted: break; case TencentImListenerTypeEnum.FriendApplicationListRead: break; case TencentImListenerTypeEnum.FriendListAdded: params = ListUtil.generateOBJList(originalParams); break; case TencentImListenerTypeEnum.FriendListDeleted: break; case TencentImListenerTypeEnum.BlackListAdd: params = ListUtil.generateOBJList(originalParams); break; case TencentImListenerTypeEnum.BlackListDeleted: break; case TencentImListenerTypeEnum.FriendInfoChanged: params = ListUtil.generateOBJList(originalParams); break; case TencentImListenerTypeEnum.MemberEnter: params = GroupMemberEnterEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MemberLeave: params = GroupMemberLeaveEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MemberInvited: params = GroupMemberInvitedOrKickedEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MemberKicked: params = GroupMemberInvitedOrKickedEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MemberInfoChanged: params = GroupMemberChangedEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.GroupCreated: break; case TencentImListenerTypeEnum.GroupDismissed: params = GroupDismissedOrRecycledEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.GroupRecycled: params = GroupDismissedOrRecycledEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.GroupInfoChanged: params = GroupChangedEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.ReceiveJoinApplication: params = GroupReceiveJoinApplicationEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.ApplicationProcessed: params = GroupApplicationProcessedEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.GrantAdministrator: params = GroupAdministratorOpEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.RevokeAdministrator: params = GroupAdministratorOpEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.QuitFromGroup: break; case TencentImListenerTypeEnum.ReceiveRESTCustomData: params = GroupReceiveRESTEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.GroupAttributeChanged: params = GroupAttributeChangedEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.Connecting: break; case TencentImListenerTypeEnum.ConnectSuccess: break; case TencentImListenerTypeEnum.ConnectFailed: params = ErrorEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.KickedOffline: break; case TencentImListenerTypeEnum.SelfInfoUpdated: params = UserEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.UserSigExpired: break; case TencentImListenerTypeEnum.ReceiveNewInvitation: params = SignalingCommonEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.InviteeAccepted: params = SignalingCommonEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.InviteeRejected: params = SignalingCommonEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.InvitationCancelled: params = SignalingCommonEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.InvitationTimeout: params = SignalingCommonEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.DownloadProgress: params = DownloadProgressEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MessageSendSucc: params = MessageEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MessageSendFail: params = MessageSendFailEntity.fromJson(originalParams); break; case TencentImListenerTypeEnum.MessageSendProgress: params = MessageSendProgressEntity.fromJson(originalParams); break; } } catch (err) { _logger.e(err, "$type 监听器错误:$err,请联系开发者进行处理!Github Issues: https://github.com/JiangJuHong/FlutterTencentImPlugin/issues"); } // 回调触发 for (var item in listeners) { item(type, params); } break; default: throw MissingPluginException(); } }); } /// 添加消息监听 void addListener(TencentImListenerValue func) { listeners.add(func); } /// 移除消息监听 void removeListener(TencentImListenerValue func) { listeners.remove(func); } } /// 监听器值模型 typedef TencentImListenerValue

= void Function( TencentImListenerTypeEnum type, P? params); ================================================ FILE: lib/message_node/custom_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 自定义消息节点 class CustomMessageNode extends MessageNode { /// 自定义数据 String? data; /// 描述信息 String? desc; /// 扩展信息 String? ext; CustomMessageNode({ required this.data, this.desc, this.ext, }) : super(MessageElemTypeEnum.Custom); CustomMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Custom) { if (json['data'] != null) data = json['data']; if (json['desc'] != null) desc = json['desc']; if (json['ext'] != null) ext = json['ext']; } @override Map toJson() { final Map data = super.toJson(); data["data"] = this.data; data["desc"] = this.desc; data["ext"] = this.ext; return data; } } ================================================ FILE: lib/message_node/face_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 表情消息节点 class FaceMessageNode extends MessageNode { /// 索引 late int index; /// 数据 late String data; FaceMessageNode({ required this.index, required this.data, }) : super(MessageElemTypeEnum.Face); FaceMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Face) { if (json['index'] != null) this.index = json["index"]; if (json['data'] != null) this.data = json["data"]; } @override Map toJson() { final Map data = super.toJson(); data["index"] = this.index; data["data"] = this.data; return data; } } ================================================ FILE: lib/message_node/file_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 文件消息节点 class FileMessageNode extends MessageNode { /// 文件路径 String? filePath; /// 文件名 String? fileName; /// 文件ID String? _uuid; /// 文件大小 int? _size; FileMessageNode({ required this.filePath, required this.fileName, }) : super(MessageElemTypeEnum.File); FileMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.File) { if (json['filePath'] != null) this.filePath = json["filePath"]; if (json['fileName'] != null) this.fileName = json["fileName"]; if (json['uuid'] != null) this._uuid = json["uuid"]; if (json['size'] != null) this._size = json["size"]; } /// 获得UUID String? get uuid => _uuid; /// 获得文件大小 int? get size => _size; @override Map toJson() { final Map data = super.toJson(); data["filePath"] = this.filePath; data["fileName"] = this.fileName; return data; } } ================================================ FILE: lib/message_node/group_tips_message_node.dart ================================================ import 'package:tencent_im_plugin/entity/group_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_changed_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/enums/group_tips_type_enum.dart'; import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/list_util.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 群提示节点 class GroupTipsMessageNode extends MessageNode { /// 群ID late String groupID; /// 群组事件通知类型 late GroupTipsTypeEnum type; /// 操作者 GroupMemberEntity? opMember; /// 被操作人列表 List? memberList; /// 群资料变更信息列表,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE时有效 List? groupChangeInfoList; /// 群成员变更信息列表,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE时有效 List? memberChangeInfoList; /// 当前群成员数,仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_JOIN, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_QUIT, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_KICKED的时候有效 late int memberCount; GroupTipsMessageNode() : super(MessageElemTypeEnum.GroupTips); GroupTipsMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.GroupTips) { if (json["groupID"] != null) this.groupID = json["groupID"]; if (json["type"] != null) this.type = GroupTipsTypeTool.getByInt(json["type"]); if (json["opMember"] != null) this.opMember = GroupMemberEntity.fromJson(json["opMember"]); if (json["memberList"] != null) this.memberList = ListUtil.generateOBJList(json["memberList"]); if (json["groupChangeInfoList"] != null) this.groupChangeInfoList = ListUtil.generateOBJList( json["groupChangeInfoList"]); if (json["memberChangeInfoList"] != null) this.memberChangeInfoList = ListUtil.generateOBJList( json["memberChangeInfoList"]); if (json["memberCount"] != null) this.memberCount = json["memberCount"]; } } ================================================ FILE: lib/message_node/image_message_node.dart ================================================ import 'dart:convert'; import 'package:tencent_im_plugin/enums/image_type_enum.dart'; import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 图片消息节点 class ImageMessageNode extends MessageNode { /// 图片路径 String? path; /// 图片列表,根据类型分开 Map? _imageData; ImageMessageNode({ required this.path, }) : super(MessageElemTypeEnum.Image); ImageMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Image) { if (json['path'] != null) path = json['path']; if (json['imageData'] != null) { _imageData = Map(); (json['imageData'] as List).forEach((v) { ImageEntity imageEntity = ImageEntity.fromJson(v); _imageData![imageEntity.type!] = imageEntity; }); } } /// 获得图片列表 Map? get imageData => _imageData; @override Map toJson() { final Map data = super.toJson(); data["path"] = this.path; return data; } } /// 图片实体 class ImageEntity { /// 大小 int? size; /// 宽度 int? width; /// 类型 ImageTypeEnum? type; /// uuid String? uuid; /// url String? url; /// 高度 int? height; ImageEntity({ this.size, this.width, this.type, this.uuid, this.url, this.height, }); ImageEntity.fromJson(data) { Map json = data is Map ? data.cast() : jsonDecode(data); if (json['size'] != null) size = json['size']; if (json['width'] != null) width = json['width']; if (json['type'] != null) type = ImageTypeTool.getByInt(json["type"]); if (json['uUID'] != null) uuid = json['uUID']; if (json['url'] != null) url = json['url']; if (json['height'] != null) height = json['height']; } } ================================================ FILE: lib/message_node/location_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 位置节点 class LocationMessageNode extends MessageNode { /// 位置描述 late String desc; /// 经度 late double longitude; /// 纬度 late double latitude; LocationMessageNode({ required this.desc, required this.longitude, required this.latitude, }) : super(MessageElemTypeEnum.Location); LocationMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Location) { if (json['desc'] != null) desc = json['desc']; if (json['longitude'] != null) longitude = json['longitude']; if (json['latitude'] != null) latitude = json['latitude']; } @override Map toJson() { final Map data = super.toJson(); data["desc"] = this.desc; data["longitude"] = this.longitude; data["latitude"] = this.latitude; return data; } } ================================================ FILE: lib/message_node/message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; /// 消息节点 class MessageNode { /// 新消息节点类型 MessageElemTypeEnum nodeType; MessageNode(this.nodeType); Map toJson() { final Map data = new Map(); data["nodeType"] = MessageElemTypeTool.toInt(this.nodeType); return data; } } ================================================ FILE: lib/message_node/sound_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 语音消息节点 class SoundMessageNode extends MessageNode { /// 语音ID String? _uuid; /// 路径 String? path; /// 时长 late int duration; /// 数据大小 int? _dataSize; SoundMessageNode({ required this.path, required this.duration, }) : super(MessageElemTypeEnum.Sound); SoundMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Sound) { if (json['uuid'] != null) _uuid = json['uuid']; if (json['path'] != null) path = json['path']; if (json['duration'] != null) duration = json['duration']; if (json['dataSize'] != null) _dataSize = json['dataSize']; } /// 获得语音ID String? get uuid => _uuid; /// 获得数据大小 int? get dataSize => _dataSize; @override Map toJson() { final Map data = super.toJson(); data["path"] = this.path; data["duration"] = this.duration; return data; } } ================================================ FILE: lib/message_node/text_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 文本消息节点 class TextMessageNode extends MessageNode { /// 文本内容 late String content; /// @的用户列表,只在群聊中有效 List? _atUserList; /// 是否需要@所有人 bool _atAll = false; TextMessageNode({ required this.content, List? atUserList, bool atAll: false, }) : this._atUserList = atUserList, this._atAll = atAll, super(MessageElemTypeEnum.Text); TextMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Text) { if (json['content'] != null) content = json['content']; } /// 设置@列表 set atUserList(List value) => _atUserList = value; /// 设置@所有人 set atAll(bool value) => _atAll = value; @override Map toJson() { final Map data = super.toJson(); data["content"] = this.content; data["atUserList"] = this._atUserList; data["atAll"] = this._atAll; return data; } } ================================================ FILE: lib/message_node/video_message_node.dart ================================================ import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; /// 适配消息节点 class VideoMessageNode extends MessageNode { /// 视频路径 String? videoPath; /// 视频UUID String? _videoUuid; /// 视频大小 int? _videoSize; /// 时长 late int duration; /// 缩略图路径 String? snapshotPath; /// 缩略图UUID String? _snapshotUuid; /// 缩略图大小 int? _snapshotSize; /// 缩略图宽度 int? _snapshotWidth; /// 缩略图高度 int? _snapshotHeight; VideoMessageNode({ required this.videoPath, required this.duration, required this.snapshotPath, }) : super(MessageElemTypeEnum.Video); VideoMessageNode.fromJson(Map json) : super(MessageElemTypeEnum.Video) { if (json['videoPath'] != null) videoPath = json["videoPath"]; if (json['videoUuid'] != null) _videoUuid = json["videoUuid"]; if (json['videoSize'] != null) _videoSize = json["videoSize"]; if (json['duration'] != null) duration = json["duration"]; if (json['snapshotPath'] != null) snapshotPath = json["snapshotPath"]; if (json['snapshotUuid'] != null) _snapshotUuid = json["snapshotUuid"]; if (json['snapshotSize'] != null) _snapshotSize = json["snapshotSize"]; if (json['snapshotWidth'] != null) _snapshotWidth = json["snapshotWidth"]; if (json['snapshotHeight'] != null) _snapshotHeight = json["snapshotHeight"]; } /// 获得视频UUID String? get videoUuid => _videoUuid; /// 获得视频大小 int? get videoSize => _videoSize; /// 获得缩略图UUID String? get snapshotUuid => _snapshotUuid; /// 获得缩略图大小 int? get snapshotSize => _snapshotSize; /// 获得缩略图宽度 int? get snapshotWidth => _snapshotWidth; /// 获得缩略图高度 int? get snapshotHeight => _snapshotHeight; @override Map toJson() { final Map data = super.toJson(); data["videoPath"] = this.videoPath; data["duration"] = this.duration; data["snapshotPath"] = this.snapshotPath; return data; } } ================================================ FILE: lib/tencent_im_plugin.dart ================================================ import 'dart:async'; import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:tencent_im_plugin/entity/conversation_entity.dart'; import 'package:tencent_im_plugin/entity/conversation_result_entity.dart'; import 'package:tencent_im_plugin/entity/find_friend_application_entity.dart'; import 'package:tencent_im_plugin/entity/find_group_application_entity.dart'; import 'package:tencent_im_plugin/entity/find_message_entity.dart'; import 'package:tencent_im_plugin/entity/friend_add_application_entity.dart'; import 'package:tencent_im_plugin/entity/friend_application_result_entity.dart'; import 'package:tencent_im_plugin/entity/friend_check_result_entity.dart'; import 'package:tencent_im_plugin/entity/friend_group_entity.dart'; import 'package:tencent_im_plugin/entity/friend_info_entity.dart'; import 'package:tencent_im_plugin/entity/friend_info_result_entity.dart'; import 'package:tencent_im_plugin/entity/friend_operation_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_application_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_create_member_entity.dart'; import 'package:tencent_im_plugin/entity/group_info_entity.dart'; import 'package:tencent_im_plugin/entity/group_info_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_info_result_entity.dart'; import 'package:tencent_im_plugin/entity/group_member_operation_result_entity.dart'; import 'package:tencent_im_plugin/entity/message_search_param.dart'; import 'package:tencent_im_plugin/entity/offline_push_info_entity.dart'; import 'package:tencent_im_plugin/entity/signaling_info_entity.dart'; import 'package:tencent_im_plugin/entity/user_entity.dart'; import 'package:tencent_im_plugin/enums/friend_application_agree_type_enum.dart'; import 'package:tencent_im_plugin/enums/friend_type_enum.dart'; import 'package:tencent_im_plugin/enums/get_message_type_enum.dart'; import 'package:tencent_im_plugin/enums/group_member_filter_enum.dart'; import 'package:tencent_im_plugin/enums/group_member_role_enum.dart'; import 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart'; import 'package:tencent_im_plugin/enums/login_status_enum.dart'; import 'package:tencent_im_plugin/enums/message_priority_enum.dart'; import 'package:tencent_im_plugin/list_util.dart'; import 'package:tencent_im_plugin/listener/tencent_im_plugin_listener.dart'; import 'package:tencent_im_plugin/message_node/message_node.dart'; import 'package:tencent_im_plugin/entity/message_entity.dart'; import 'package:tencent_im_plugin/enums/log_print_level.dart'; class TencentImPlugin { static const MethodChannel _channel = const MethodChannel('tencent_im_plugin'); /// 监听器对象 static TencentImPluginListener listener = TencentImPluginListener(_channel); /// C2C会话前缀 static const String conversationC2CPrefix = "c2c_"; /// 群聊会话前缀 static const String conversationGroupPrefix = "group_"; /// 获得会话ID,可在 [conversationID] 会话ID | [userID] 用户ID | [groupID] 群组ID 三选一 static String _getConversationID({String? conversationID, String? userID, String? groupID}) { String? cID = conversationID; if (cID == null && userID != null) { cID = conversationC2CPrefix + userID; } else if (cID == null && groupID != null) { cID = conversationGroupPrefix + groupID; } if (cID == null) throw Exception("conversationID、userID、groupID 不能都为空"); return cID; } /// 初始化SDK /// [appid] 应用ID /// [logPrintLevel] 日志打印级别 static initSDK({required String appid, LogPrintLevel logPrintLevel: LogPrintLevel.error}) { return _channel.invokeMethod('initSDK', {"appid": appid, "logPrintLevel": LogPrintLevelTool.toInt(logPrintLevel)}); } /// 反初始化SDK static unInitSDK() => _channel.invokeMethod('unInitSDK'); /// 获取SDK版本 /// [Return] SDK版本 static Future getVersion() async => await _channel.invokeMethod('getVersion'); /// 获取服务器当前时间 /// [Return] 服务器时间,单位 s static Future getServerTime() async => await _channel.invokeMethod('getServerTime'); /// 登录腾讯云IM /// [userID] 用户ID /// [userSig] 用户签名 static Future login({required String userID, required String userSig}) { return _channel.invokeMethod('login', {"userID": userID, "userSig": userSig}); } /// 退出登录腾讯云IM static Future logout() => _channel.invokeMethod('logout'); /// 获得用户登录状态 /// [Return] 用户当前登录状态 static Future getLoginStatus() async => LoginStatusTool.getByInt(await (_channel.invokeMethod('getLoginStatus'))); /// 获得当前登录用户 /// [Return] 当前用户ID static Future getLoginUser() => _channel.invokeMethod('getLoginUser'); /// 邀请某个人 /// [invitee] 被邀请人用户 ID /// [data] 自定义数据 /// [onlineUserOnly] 是否只有在线用户才能收到邀请,如果设置为 true,只有在线用户才能收到, 并且 invite 操作也不会产生历史消息(针对该次 invite 的后续 cancel、accept、reject、timeout 操作也同样不会产生历史消息)。 /// [offlinePushInfo] 离线推送信息,其中 desc 为必填字段,推送的时候会默认展示 desc 信息。 /// [timeout] 超时时间,单位秒,如果设置为 0,SDK 不会做超时检测,也不会触发 onInvitationTimeout 回调 /// [Return] 邀请 ID,如果邀请失败,返回 null static Future invite({required String invitee, required String data, OfflinePushInfoEntity? offlinePushInfo, bool onlineUserOnly: false, int timeout: 0}) { return _channel.invokeMethod('invite', { "invitee": invitee, "data": data, "onlineUserOnly": onlineUserOnly, "offlinePushInfo": jsonEncode(offlinePushInfo ?? OfflinePushInfoEntity()), "timeout": timeout, }); } /// 邀请群内的某些人 /// [groupID] 发起邀请所在群组 /// [inviteeList] 被邀请人列表,inviteeList 必须已经在 groupID 群里,否则邀请无效 /// [data] 自定义数据 /// [onlineUserOnly] 是否只有在线用户才能收到邀请,如果设置为 true,只有在线用户才能收到, 并且 invite 操作也不会产生历史消息(针对该次 invite 的后续 cancel、accept、reject、timeout 操作也同样不会产生历史消息)。 /// [timeout] 超时时间,单位秒,如果设置为 0,SDK 不会做超时检测,也不会触发 onInvitationTimeout 回调 /// [Return] 邀请 ID,如果邀请失败,返回 null static Future inviteInGroup({required String groupID, required List inviteeList, required String data, bool onlineUserOnly: false, int timeout: 0}) { return _channel.invokeMethod('inviteInGroup', { "groupID": groupID, "inviteeList": inviteeList.join(","), "data": data, "onlineUserOnly": onlineUserOnly, "timeout": timeout, }); } /// 邀请方取消邀请 /// [inviteID] 邀请ID /// [data] 自定义数据 static Future cancel({required String inviteID, required String data}) { return _channel.invokeMethod('cancel', { "inviteID": inviteID, "data": data, }); } /// 接收方接收邀请 /// [inviteID] 邀请ID /// [data] 自定义数据 static Future accept({required String inviteID, required String data}) { return _channel.invokeMethod('accept', { "inviteID": inviteID, "data": data, }); } /// 接收方拒绝邀请 /// [inviteID] 邀请ID /// [data] 自定义数据 static Future reject({required String inviteID, required String data}) { return _channel.invokeMethod('reject', { "inviteID": inviteID, "data": data, }); } /// 获取信令信息 /// [message] 消息对象 /// [Return] V2TIMSignalingInfo 信令信息,如果为 null,则 msg 不是一条信令消息。 static Future getSignalingInfo({required FindMessageEntity message}) async { return SignalingInfoEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getSignalingInfo', { "message": jsonEncode(message), })))); } /// 添加邀请信令(可以用于群离线推送消息触发的邀请信令) /// [info] 信令信息对象 static Future addInvitedSignaling({required SignalingInfoEntity info}) { return _channel.invokeMethod('addInvitedSignaling', { "info": jsonEncode(info), }); } /// 发送消息 /// [receiver] 消息接收者的 userID, 如果是发送 C2C 单聊消息,只需要指定 receiver 即可。 /// [groupID] 目标群组 ID,如果是发送群聊消息,只需要指定 groupID 即可。 /// [ol] 是否为在线消息(无痕),如果为true,将使用 sendOnlineMessage 通道进行消息发送 /// [localCustomInt] 自定义Int /// [localCustomStr] 自定义Str /// [node] 消息节点 /// [priority] 消息优先级,仅针对群聊消息有效。请把重要消息设置为高优先级(比如红包、礼物消息),高频且不重要的消息设置为低优先级(比如点赞消息)。 /// [offlinePushInfo] 离线推送时携带的标题和内容。 /// [Return] 消息ID static Future sendMessage({ String? receiver, String? groupID, required MessageNode node, bool ol: false, int? localCustomInt, String? localCustomStr, MessagePriorityEnum priority: MessagePriorityEnum.Default, OfflinePushInfoEntity? offlinePushInfo, }) { return _channel.invokeMethod( 'sendMessage', { "receiver": receiver, "groupID": groupID, "node": jsonEncode(node), "ol": ol, "localCustomInt": localCustomInt, "localCustomStr": localCustomStr, "priority": MessagePriorityTool.toInt(priority), "offlinePushInfo": offlinePushInfo == null ? null : jsonEncode(offlinePushInfo), }..removeWhere((key, value) => value == null), ); } /// 重发消息 /// [message] 消息查找对象 /// [receiver] 消息接收者的 userID, 如果是发送 C2C 单聊消息,只需要指定 receiver 即可。 /// [groupID] 目标群组 ID,如果是发送群聊消息,只需要指定 groupID 即可。 /// [ol] 是否为在线消息(无痕),如果为true,将使用 sendOnlineMessage 通道进行消息发送 /// [localCustomInt] 自定义Int /// [localCustomStr] 自定义Str /// [priority] 消息优先级,仅针对群聊消息有效。请把重要消息设置为高优先级(比如红包、礼物消息),高频且不重要的消息设置为低优先级(比如点赞消息)。 /// [offlinePushInfo] 离线推送时携带的标题和内容。 /// [Return] 消息ID static Future resendMessage({ required FindMessageEntity message, String? receiver, String? groupID, bool ol: false, int? localCustomInt, String? localCustomStr, MessagePriorityEnum priority: MessagePriorityEnum.Default, OfflinePushInfoEntity? offlinePushInfo, }) { return _channel.invokeMethod( 'resendMessage', { "message": jsonEncode(message), "receiver": receiver, "groupID": groupID, "ol": ol, "localCustomInt": localCustomInt, "localCustomStr": localCustomStr, "priority": MessagePriorityTool.toInt(priority), "offlinePushInfo": offlinePushInfo == null ? null : jsonEncode(offlinePushInfo), }..removeWhere((key, value) => value == null), ); } /// 撤回消息 /// [message] 消息查找对象 static Future revokeMessage({required FindMessageEntity message}) { return _channel.invokeMethod('revokeMessage', { "message": jsonEncode(message), }); } /// 获取历史消息高级接口 /// [userID] 用户ID /// [groupID] 群聊ID /// [count] 拉取消息的个数,不宜太多,会影响消息拉取的速度,这里建议一次拉取 20 个 /// [lastMsg] 获取消息的起始消息,如果传 null,起始消息为会话的最新消息 /// [type] 拉取消息类型,可以设置拉取本地、云端更老或则更新的消息。 static Future> getHistoryMessageList({String? userID, String? groupID, required int count, GetMessageTypeEnum type: GetMessageTypeEnum.GetCloudOlderMsg, FindMessageEntity? lastMsg}) async { if (userID == null && groupID == null) throw ArgumentError("userID 和 groupID 不能同时为空!"); return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod( 'getHistoryMessageList', { "userID": userID, "groupID": groupID, "count": count, "type": GetMessageTypeTool.toInt(type), "lastMsg": lastMsg == null ? null : jsonEncode(lastMsg), }..removeWhere((key, value) => value == null), )))); } /// 获得单聊历史记录 /// [userId] 用户ID /// [count] 拉取消息的个数,不宜太多,会影响消息拉取的速度,这里建议一次拉取 20 个 /// [lastMsg] 获取消息的起始消息,如果传 null,起始消息为会话的最新消息 static Future> getC2CHistoryMessageList({required String userID, required int count, FindMessageEntity? lastMsg}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod( 'getC2CHistoryMessageList', { "userID": userID, "count": count, "lastMsg": lastMsg == null ? null : jsonEncode(lastMsg), }..removeWhere((key, value) => value == null), )))); } /// 获得群聊历史记录 /// [groupID] 群ID /// [count] 拉取消息的个数,不宜太多,会影响消息拉取的速度,这里建议一次拉取 20 个 /// [lastMsg] 获取消息的起始消息,如果传 null,起始消息为会话的最新消息 static Future> getGroupHistoryMessageList({required String groupID, required int count, FindMessageEntity? lastMsg}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod( 'getGroupHistoryMessageList', { "groupID": groupID, "count": count, "lastMsg": lastMsg == null ? null : jsonEncode(lastMsg), }..removeWhere((key, value) => value == null), )))); } /// 设置聊天记录为已读,此为 markC2CMessageAsRead 和 markGroupMessageAsRead 的封装 /// [userID] 用户ID /// [groupID] 群ID static Future markMessageAsRead({String? userID, String? groupID}) { if (userID == null && groupID == null) throw ArgumentError("userID 和 groupID 不能同时为空!"); if (userID != null) { return markC2CMessageAsRead(userID: userID); } else { return markGroupMessageAsRead(groupID: groupID!); } } /// 设置单聊已读 /// [groupID] 群ID static Future markC2CMessageAsRead({required String userID}) { return _channel.invokeMethod('markC2CMessageAsRead', { "userID": userID, }); } /// 设置群聊已读 /// [groupID] 群ID static Future markGroupMessageAsRead({required String groupID}) { return _channel.invokeMethod('markGroupMessageAsRead', { "groupID": groupID, }); } /// 删除本地消息 /// [message] 消息对象 static Future deleteMessageFromLocalStorage({required FindMessageEntity message}) { return _channel.invokeMethod('deleteMessageFromLocalStorage', { "message": jsonEncode(message), }); } /// 删除本地及漫游消息 /// 该接口会删除本地历史的同时也会把漫游消息即保存在服务器上的消息也删除,卸载重装后无法再拉取到。需要注意的是: /// 1. 一次最多只能删除 30 条消息 /// 2. 要删除的消息必须属于同一会话 /// 3. 一秒钟最多只能调用一次该接口 /// 4. 如果该账号在其他设备上拉取过这些消息,那么调用该接口删除后,这些消息仍然会保存在那些设备上,即删除消息不支持多端同步。 /// [message] 消息对象 static Future deleteMessages({required List message}) { return _channel.invokeMethod('deleteMessages', { "message": jsonEncode(message), }); } /// 向群组消息列表中添加一条消息 /// [groupID] 群ID /// [sender] 发送人 /// [message] 消息对象 static Future insertGroupMessageToLocalStorage({required String groupID, required String sender, required MessageNode node}) { return _channel.invokeMethod('insertGroupMessageToLocalStorage', { "groupID": groupID, "sender": sender, "node": jsonEncode(node), }); } /// 向用户消息列表中添加一条消息 /// [userID] 用户ID /// [sender] 发送人 /// [message] 消息对象 static Future insertC2CMessageToLocalStorage({required String userID, required String sender, required MessageNode node}) { return _channel.invokeMethod('insertC2CMessageToLocalStorage', { "userID": userID, "sender": sender, "node": jsonEncode(node), }); } /// 下载视频 /// [message] 消息对象 /// [path] 下载路径 static Future downloadVideo({required FindMessageEntity message, required String path}) { return _channel.invokeMethod('downloadVideo', { "message": jsonEncode(message), "path": path, }); } /// 下载视频缩略图 /// [message] 消息对象 /// [path] 下载路径 static Future downloadVideoThumbnail({required FindMessageEntity message, required String path}) { return _channel.invokeMethod('downloadVideoThumbnail', { "message": jsonEncode(message), "path": path, }); } /// 下载语音 /// [message] 消息对象 /// [path] 下载路径 static Future downloadSound({required FindMessageEntity message, required String path}) { return _channel.invokeMethod('downloadSound', { "message": jsonEncode(message), "path": path, }); } /// 下载视频 /// [message] 消息对象 /// [path] 下载路径 static Future downloadFile({required FindMessageEntity message, required String path}) { return _channel.invokeMethod('downloadFile', { "message": jsonEncode(message), "path": path, }); } /// 设置消息本地Str /// [message] 消息对象 /// [data] 数据对象 static Future setMessageLocalCustomStr({required FindMessageEntity message, required String data}) { return _channel.invokeMethod('setMessageLocalCustomStr', { "message": jsonEncode(message), "data": data, }); } /// 设置消息本地Int /// [message] 消息对象 /// [data] 数据对象 static Future setMessageLocalCustomInt({required FindMessageEntity message, required int data}) { return _channel.invokeMethod('setMessageLocalCustomInt', { "message": jsonEncode(message), "data": data, }); } /// 查找消息列表 /// [messages] 需要获得的消息查找对象 static Future> findMessages({required List messages}) async { return ListUtil.generateOBJList(await _channel.invokeMethod('findMessages', { "messages": jsonEncode(messages), })); } /// 创建群,[info]对象建议使用[GroupInfoEntity.create],进行创建 /// [info] 群信息对象 /// [memberList] 指定初始的群成员(直播群 AVChatRoom 不支持指定初始群成员,memberList 请传 null) /// [Return] 群ID static Future createGroup({required GroupInfoEntity info, List? memberList}) { return _channel.invokeMethod( 'createGroup', { "info": jsonEncode(info), "memberList": memberList == null ? null : jsonEncode(memberList), }..removeWhere((key, value) => value == null), ); } /// 加入群 /// [groupID] 群ID /// [message] 描述 static Future joinGroup({required String groupID, required String message}) { return _channel.invokeMethod('joinGroup', { "groupID": groupID, "message": message, }); } /// 退出群 /// [groupID] 群ID static Future quitGroup({required String groupID}) { return _channel.invokeMethod('quitGroup', { "groupID": groupID, }); } /// 解散群 /// [groupID] 群ID static Future dismissGroup({required String groupID}) { return _channel.invokeMethod('dismissGroup', { "groupID": groupID, }); } /// 获取已经加入的群列表(不包括已加入的直播群) static Future> getJoinedGroupList() async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getJoinedGroupList')))); } /// 拉取群资料 /// [groupIDList] 群ID列表 static Future> getGroupsInfo({required List groupIDList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getGroupsInfo', { "groupIDList": groupIDList.join(","), })))); } /// 修改群资料 /// [info] 群信息 static Future setGroupInfo({required GroupInfoEntity info}) async { return _channel.invokeMethod('setGroupInfo', { "info": jsonEncode(info), }); } /// 搜索群列表 /// /// [keywordList] 关键字列表 /// [isSearchGroupID] 是否根据群ID搜索 /// [isSearchGroupName] 是否根据群名称搜索 static Future> searchGroups({required List keywordList, bool isSearchGroupID: false, bool isSearchGroupName: false}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('searchGroups', { "keywordList": keywordList, "isSearchGroupID": isSearchGroupID, "isSearchGroupName": isSearchGroupName, })))); } /// 搜索群成员列表 /// /// [keywordList] 关键字列表 /// [groupIDList] 群ID列表 /// [isSearchMemberNameCard] 是否根据群名片搜索 /// [isSearchMemberUserID] 是否根据群用户ID搜索 /// [isSearchMemberRemark] 是否根据群用户备注搜索 /// [isSearchMemberNickName] 是否根据群用户昵称搜索 static Future searchGroupMembers({ required List keywordList, required List groupIDList, bool isSearchMemberNameCard: false, bool isSearchMemberUserID: false, bool isSearchMemberRemark: false, bool isSearchMemberNickName: false, }) async { return _channel.invokeMethod('searchGroupMembers', { "keywordList": keywordList, "groupIDList": groupIDList, "isSearchMemberNameCard": isSearchMemberNameCard, "isSearchMemberUserID": isSearchMemberUserID, "isSearchMemberRemark": isSearchMemberRemark, "isSearchMemberNickName": isSearchMemberNickName, }); } /// 修改群消息接收选项 /// [ids] 用户ID列表 /// [opt] 消息接收选项 static Future setC2CReceiveMessageOpt({required List ids, required ReceiveMessageOptEnum opt}) async { return _channel.invokeMethod('setC2CReceiveMessageOpt', {"ids": ids, "opt": ReceiveMessageOptTool.toInt(opt)}); } /// 修改群消息接收选项 /// [groupID] 群ID /// [opt] 消息接收选项 static Future setGroupReceiveMessageOpt({required String groupID, required ReceiveMessageOptEnum opt}) async { return _channel.invokeMethod('setGroupReceiveMessageOpt', {"groupID": groupID, "opt": ReceiveMessageOptTool.toInt(opt)}); } /// 获得C2C消息接收选项 /// [ids] 用户ID列表 /// [Return] key: 用户ID,Value: 消息接收选项 static Future> getC2CReceiveMessageOpt({required List ids}) async { Map result = await _channel.invokeMethod('getC2CReceiveMessageOpt', ids); return result.map((key, value) => MapEntry(key, ReceiveMessageOptTool.getByInt(value))); } /// 初始化群属性,会清空原有的群属性列表 /// [groupID] 群ID /// [attributes] 群属性 /// 1. attributes 的使用限制如下: /// 2. 目前只支持 AVChatRoom /// 3. key 最多支持16个,长度限制为32字节 /// 4. value 长度限制为4k /// 5. 总的 attributes(包括 key 和 value)限制为16k /// 6. initGroupAttributes、setGroupAttributes、deleteGroupAttributes 接口合并计算, SDK 限制为5秒10次,超过后回调8511错误码;后台限制1秒5次,超过后返回10049错误码 /// 7. getGroupAttributes 接口 SDK 限制5秒20次 static Future initGroupAttributes({required String groupID, required Map attributes}) async { return _channel.invokeMethod('initGroupAttributes', { "groupID": groupID, "attributes": jsonEncode(attributes), }); } /// 设置群属性。已有该群属性则更新其 value 值,没有该群属性则添加该属性。 /// [groupID] 群ID /// [attributes] 群属性 static Future setGroupAttributes({required String groupID, required Map attributes}) async { return _channel.invokeMethod('setGroupAttributes', { "groupID": groupID, "attributes": jsonEncode(attributes), }); } /// 删除指定群属性,keys 传 null 则清空所有群属性。 /// [groupID] 群ID /// [keys] 群属性Key,keys 传 null 则清空所有群属性。 static Future deleteGroupAttributes({required String groupID, List? keys}) async { return _channel.invokeMethod( 'deleteGroupAttributes', { "groupID": groupID, "keys": keys == null ? null : keys.join(","), }..removeWhere((key, value) => value == null), ); } /// 获取指定群属性,keys 传 null 则获取所有群属性。 /// [groupID] 群ID /// [keys] 群属性Key,keys 传 null 则清空所有群属性。 static Future> getGroupAttributes({required String groupID, List? keys}) async { return (jsonDecode(await (_channel.invokeMethod( 'getGroupAttributes', { "groupID": groupID, "keys": keys == null ? null : keys.join(","), }..removeWhere((key, value) => value == null), )))) .cast(); } /// 获取指定群在线人数 /// [groupID] 群ID static Future getGroupOnlineMemberCount({required String groupID}) async { return await _channel.invokeMethod('getGroupOnlineMemberCount', { "groupID": groupID, }); } /// 获取群成员列表。 /// [groupID] 群ID /// [filter] 指定群成员类型 /// [nextSeq] 分页拉取标志,第一次拉取填0,回调成功如果 nextSeq 不为零,需要分页,传入再次拉取,直至为0。 static Future getGroupMemberList({required String groupID, GroupMemberFilterEnum filter: GroupMemberFilterEnum.All, int nextSeq: 0}) async { return GroupMemberInfoResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getGroupMemberList', { "groupID": groupID, "filter": GroupMemberFilterTool.toInt(filter), "nextSeq": nextSeq, })))); } /// 获取指定的群成员资料。 /// [groupID] 群ID /// [memberList] 群成员列表 static Future> getGroupMembersInfo({required String groupID, required List memberList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getGroupMembersInfo', { "groupID": groupID, "memberList": memberList.join(","), })))); } /// 修改指定的群成员资料。 /// [groupID] 群ID /// [info] 群成员对象 static Future setGroupMemberInfo({required String groupID, required GroupMemberEntity info}) { return _channel.invokeMethod('setGroupMemberInfo', { "groupID": groupID, "info": jsonEncode(info), }); } /// 禁言(只有管理员或群主能够调用)。 /// [groupID] 群ID /// [userID] 用户ID /// [seconds] 禁言时长 static Future muteGroupMember({required String groupID, required String userID, required int seconds}) { return _channel.invokeMethod('muteGroupMember', { "groupID": groupID, "userID": userID, "seconds": seconds, }); } /// 邀请他人入群 /// [groupID] 群ID /// [userList] 用户ID列表 static Future> inviteUserToGroup({required String groupID, required List userList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('inviteUserToGroup', { "groupID": groupID, "userList": userList.join(","), })))); } /// 踢人 /// [groupID] 群ID /// [memberList] 群成员ID列表 /// [reason] 理由 static Future> kickGroupMember({required String groupID, required List memberList, String reason: ""}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('kickGroupMember', { "groupID": groupID, "memberList": memberList.join(","), "reason": reason, })))); } /// 切换群成员的角色。 /// [groupID] 群ID /// [userID] 用户ID /// [role] 角色 static Future setGroupMemberRole({required String groupID, required String userID, required GroupMemberRoleEnum role}) { return _channel.invokeMethod('setGroupMemberRole', {"groupID": groupID, "userID": userID, "role": GroupMemberRoleTool.toInt(role)}); } /// 转让群主 /// [groupID] 群ID /// [userID] 用户ID static Future transferGroupOwner({required String groupID, required String userID}) { return _channel.invokeMethod('transferGroupOwner', {"groupID": groupID, "userID": userID}); } /// 获取加群的申请列表 static Future getGroupApplicationList() async { return GroupApplicationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getGroupApplicationList')))); } /// 同意某一条加群申请 /// [application] 申请对象 /// [reason] 理由 static Future acceptGroupApplication({required FindGroupApplicationEntity application, String reason: ""}) { return _channel.invokeMethod('acceptGroupApplication', {"application": jsonEncode(application), "reason": reason}); } /// 拒绝某一条加群申请 /// [application] 申请对象 /// [reason] 理由 static Future refuseGroupApplication({required FindGroupApplicationEntity application, String reason: ""}) { return _channel.invokeMethod('refuseGroupApplication', {"application": jsonEncode(application), "reason": reason}); } /// 标记申请列表为已读 static Future setGroupApplicationRead() { return _channel.invokeMethod('setGroupApplicationRead'); } /// 获取会话列表 /// [nextSeq] 分页拉取的游标,第一次默认取传 0,后续分页拉传上一次分页拉取成功回调里的 nextSeq /// [count] 分页拉取的个数,一次分页拉取不宜太多,会影响拉取的速度,建议每次拉取 100 个会话 static Future getConversationList({int nextSeq: 0, int count: 100}) async { return ConversationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getConversationList', {"nextSeq": nextSeq, "count": count})))); } /// 获得指定会话([conversationID] | [userID] | [groupID] 参数三选一) /// [conversationID] 会话ID /// [userID] 用户ID /// [groupID] 群ID static Future getConversation({String? conversationID, String? userID, String? groupID}) async { return ConversationEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getConversation', {"conversationID": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID)})))); } /// 删除会话([conversationID] | [userID] | [groupID] 参数三选一) /// [conversationID] 会话ID /// [userID] 用户ID /// [groupID] 群ID static Future deleteConversation({String? conversationID, String? userID, String? groupID}) { return _channel.invokeMethod('deleteConversation', {"conversationID": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID)}); } /// 设置会话草稿([conversationID] | [userID] | [groupID] 参数三选一) /// [conversationID] 会话ID /// [userID] 用户ID /// [groupID] 群ID /// [draftText] 草稿内容,null代表取消设置 static Future setConversationDraft({String? conversationID, String? userID, String? groupID, String? draftText}) { return _channel.invokeMethod( 'setConversationDraft', { "conversationID": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID), "draftText": draftText, }..removeWhere((key, value) => value == null), ); } /// 会话置顶,可在 [conversationID] 会话ID | [userID] 用户ID | [groupID] 群组ID 三选一 /// [isPinned] 是否需要置顶 static Future pinConversation({String? conversationID, String? userID, String? groupID, required bool? isPinned}) { return _channel.invokeMethod('pinConversation', {"conversationID": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID), "isPinned": isPinned}); } /// 获得会话总未读数 /// 未读总数会减去设置为免打扰的会话的未读数,即消息接收选项设置为 V2TIMMessage.V2TIM_NOT_RECEIVE_MESSAGE 的会话。 static Future getTotalUnreadMessageCount() async => await _channel.invokeMethod('getTotalUnreadMessageCount'); /// 获取用户资料 /// [userList] 用户ID列表 static Future> getUsersInfo({required List userIDList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getUsersInfo', { "userIDList": userIDList.join(","), })))); } /// 修改个人资料,注意:此接口调用后马上调用 getUsersInfo 可能会刷新不及时,可以使用Future. /// [info] 资料对象 static Future setSelfInfo({required UserEntity info}) { return _channel.invokeMethod('setSelfInfo', {"info": jsonEncode(info)}); } /// 添加用户到黑名单 /// [userIDList] 用户ID列表 static Future> addToBlackList({ required List userIDList, }) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('addToBlackList', {"userIDList": userIDList.join(",")})))); } /// 从黑名单中删除 /// [userIDList] 用户ID列表 static Future> deleteFromBlackList({ required List userIDList, }) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('deleteFromBlackList', {"userIDList": userIDList.join(",")})))); } /// 获得黑名单列表 static Future> getBlackList() async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getBlackList')))); } /// 设置离线推送Token,Android使用setOfflinePushConfig,IOS使用setAPNS /// [token] Token /// [bussid] 推送证书 ID,是在 IM 控制台上生成的 /// /// [tpns] 是否是tpnsToken static Future setOfflinePushConfig({required String token, required int bussid, required bool tpns}) { return _channel.invokeMethod('setOfflinePushConfig', { "token": token, "bussid": bussid, "tpns": tpns, }); } /// 设置未读桌标,Android使用doBackground,IOS更改setAPNSListener值 /// [number] 桌标数量 static Future setUnreadBadge({required int number}) { return _channel.invokeMethod('setUnreadBadge', { "number": number, }); } /// 获得好友列表 static Future> getFriendList() async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getFriendList')))); } /// 获得指定好友信息 /// [userIDList] 好友ID列表 static Future> getFriendsInfo({required List userIDList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('getFriendsInfo', { "userIDList": userIDList.join(","), })))); } /// 设置好友资料 /// [info] 好友资料 static Future setFriendInfo({required FriendInfoEntity info}) { return _channel.invokeMethod('setFriendInfo', { "info": jsonEncode(info), }); } /// 添加好友 /// [info] 申请对象 static Future addFriend({required FriendAddApplicationEntity info}) async { return FriendOperationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('addFriend', { "info": jsonEncode(info), })))); } /// 删除好友 /// [userIDList] 好友ID列表,ID 建议一次最大 100 个,因为数量过多可能会导致数据包太大被后台拒绝,后台限制数据包最大为 1M /// [deleteType] 删除类型 static Future> deleteFromFriendList({required List userIDList, required FriendTypeEnum deleteType}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('deleteFromFriendList', { "userIDList": userIDList.join(","), "deleteType": FriendTypeTool.toInt(deleteType), })))); } /// 检查好友关系 /// [userID] 用户ID /// [checkType] 检测类型类型 static Future checkFriend({required String userID, required FriendTypeEnum checkType}) async { return FriendCheckResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('checkFriend', { "userID": userID, "checkType": FriendTypeTool.toInt(checkType), })))); } /// 获取好友申请列表 static Future getFriendApplicationList() async { return FriendApplicationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getFriendApplicationList')))); } /// 同意好友申请 /// [application] 查找好友申请对象实体 /// [responseType] 建立关系类型 static Future acceptFriendApplication({required FindFriendApplicationEntity application, required FriendApplicationAgreeTypeEnum responseType}) async { return FriendOperationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('acceptFriendApplication', { "application": jsonEncode(application), "responseType": FriendApplicationAgreeTypeTool.toInt(responseType), })))); } /// 拒绝好友申请 /// [application] 查找好友申请对象实体 static Future refuseFriendApplication({required FindFriendApplicationEntity application}) async { return FriendOperationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('refuseFriendApplication', { "application": jsonEncode(application), })))); } /// 删除好友申请 /// [application] 查找好友申请对象实体 static Future deleteFriendApplication({required FindFriendApplicationEntity application}) { return _channel.invokeMethod('deleteFriendApplication', { "application": jsonEncode(application), }); } /// 设置好友申请为已读 static Future setFriendApplicationRead() { return _channel.invokeMethod('setFriendApplicationRead'); } /// 新建好友分组 /// [groupName] 组名 /// [userIDList] 用户列表 static Future> createFriendGroup({required String groupName, required List userIDList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('createFriendGroup', { "groupName": groupName, "userIDList": userIDList.join(","), })))); } /// 获取分组信息 /// [groupNameList] 分组名称 static Future> getFriendGroups({List? groupNameList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod( 'getFriendGroups', { "groupNameList": groupNameList?.join(","), }..removeWhere((key, value) => value == null), )))); } /// 删除好友分组 /// [groupNameList] 分组名称 static Future deleteFriendGroup({required List groupNameList}) { return _channel.invokeMethod('deleteFriendGroup', { "groupNameList": groupNameList.join(","), }); } /// 修改分组名称 /// [oldName] 旧名称 /// [newName] 新名称 static Future renameFriendGroup({required String oldName, required String newName}) { return _channel.invokeMethod('renameFriendGroup', { "oldName": oldName, "newName": newName, }); } /// 添加好友到分组 /// [groupName] 组名 /// [userIDList] 好友ID static Future> addFriendsToFriendGroup({required String groupName, required List userIDList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('addFriendsToFriendGroup', { "groupName": groupName, "userIDList": userIDList.join(","), })))); } /// 从分组中删除好友 /// [groupName] 组名 /// [userIDList] 好友ID static Future> deleteFriendsFromFriendGroup({required String groupName, required List userIDList}) async { return ListUtil.generateOBJList(jsonDecode(await (_channel.invokeMethod('deleteFriendsFromFriendGroup', { "groupName": groupName, "userIDList": userIDList.join(","), })))); } /// 根据[param] 消息搜索参数对象 搜索本地消息 static Future searchLocalMessages({required MessageSearchParam param}) { return _channel.invokeListMethod("searchLocalMessages", param.toJson()); } /// 添加消息监听 static void addListener(TencentImListenerValue func) => listener.addListener(func); /// 移除消息监听 static void removeListener(TencentImListenerValue func) => listener.removeListener(func); } ================================================ FILE: lib/utils/enum_util.dart ================================================ /// 枚举工具类 class EnumUtil { /// 获得枚举的名称(不包含前缀) static String getEnumName(enumObj) { var es = enumObj.toString().split("."); return es[es.length - 1]; } /// 根据名字获得枚举 static T? nameOf(List array, String name) { for (var item in array) { if (EnumUtil.getEnumName(item) == name) { return item; } } return null; } } ================================================ FILE: pubspec.yaml ================================================ name: tencent_im_plugin description: This plug-in integrates Tencent cloud 'imsdk', realizes cross platform im access, and is compatible with Android and IOS devices. version: 3.0.0 homepage: https://www.yuque.com/jiangjuhong/tencent-im-flutter/zk6p14 repository: https://github.com/JiangJuHong/FlutterTencentImPlugin environment: sdk: '>=2.12.0 <3.0.0' flutter: ">=1.12.0" dependencies: flutter: sdk: flutter # 生成UUID(https://pub.dev/packages/uuid) uuid: ^3.0.3 # 日志输出(https://pub.dev/packages/logger) logger: ^1.0.0 dev_dependencies: flutter_test: sdk: flutter # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter. flutter: # This section identifies this Flutter project as a plugin project. # The androidPackage and pluginClass identifiers should not ordinarily # be modified. They are used by the tooling to maintain consistency when # adding or updating assets for this project. plugin: platforms: android: package: top.huic.tencent_im_plugin pluginClass: TencentImPlugin ios: pluginClass: TencentImPlugin # To add assets to your plugin package, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg # # For details regarding assets in packages, see # https://flutter.dev/assets-and-images/#from-packages # # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. # To add custom fonts to your plugin package, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: # fonts: # - family: Schyler # fonts: # - asset: fonts/Schyler-Regular.ttf # - asset: fonts/Schyler-Italic.ttf # style: italic # - family: Trajan Pro # fonts: # - asset: fonts/TrajanPro.ttf # - asset: fonts/TrajanPro_Bold.ttf # weight: 700 # # For details regarding fonts in packages, see # https://flutter.dev/custom-fonts/#from-packages