[
  {
    "path": ".all-contributorsrc",
    "content": "{\n  \"files\": [\n    \"README.md\"\n  ],\n  \"imageSize\": 100,\n  \"commit\": false,\n  \"contributors\": [\n    {\n      \"login\": \"kxr224\",\n      \"name\": \"cyrus\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/28681083?v=4\",\n      \"profile\": \"https://github.com/kxr224\",\n      \"contributions\": [\n        \"bug\"\n      ]\n    },\n    {\n      \"login\": \"songjiabin\",\n      \"name\": \"宋佳宾\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/13177100?v=4\",\n      \"profile\": \"https://github.com/songjiabin\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ligui-iOS\",\n      \"name\": \"ligui-iOS\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20856361?v=4\",\n      \"profile\": \"https://github.com/ligui-iOS\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"laiiihz\",\n      \"name\": \"LAIIIHZ\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/35956195?v=4\",\n      \"profile\": \"http://laiiihz.github.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    }\n  ],\n  \"contributorsPerLine\": 7,\n  \"projectName\": \"FlutterTencentImPlugin\",\n  \"projectOwner\": \"JiangJuHong\",\n  \"repoType\": \"github\",\n  \"repoHost\": \"https://github.com\",\n  \"skipCi\": true\n}\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: https://www.yuque.com/jiangjuhong/tencent-im-flutter/ygi582 # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.dart_tool/\n\n.packages\n.pub/\n.idea\n*.iml\nbuild/\n"
  },
  {
    "path": ".metadata",
    "content": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrades etc.\n#\n# This file should be version controlled and should not be manually edited.\n\nversion:\n  revision: d345a3b303ce041846ff895eb49a104bef133c4b\n  channel: master\n\nproject_type: plugin\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 0.1.0\n* 集成腾讯云IMSDK，包含Android 和 IOS\n\n## 0.1.1\n* 修复Android设备上找不到符号的BUG\n\n## 0.1.2\n* 修复IOS上Json字符串中包含特殊字符的问题\n* 修复IOS监听器无效的问题\n\n## 0.1.3\n* 修复 MessageEntity 中 sessionType 始终为空的问题\n\n## 0.1.4\n* 修复 GroupTipsNode 节点nil对象引起闪退问题\n\n## 0.1.5\n* 修复 GroupTipsNode 节点nil对象引起闪退问题\n\n## 0.1.6\n* 修复IOS上添加好友必须传递所有参数的问题\n* 修改 getParam 方法代码结构\n\n## 0.1.7\n* 修复IOS上获得未决列表时解析异常的问题\n\n## 0.1.8\n* 修复Android设备上自定义消息未解码的问题\n\n## 0.1.9\n* 修复安卓上获得单个会话异常\n\n## 0.1.10\n* 修复IOS设备上回调数据非JSON类型时多了个 \"\"\n\n## 0.1.11\n* 修复消息解析异常\n\n## 0.1.12\n* 移除base64 工具类\n* 解决fastjson byte[] 序列化为base64字符串的问题\n\n## 0.1.13\n* 修复运行异常\n\n## 0.1.14\n* 完成消息撤回功能\n\n## 0.1.15\n* 增加删除单条消息功能\n* 修改json工具类，解决非字符串类型以字符串类型返回\n\n## 0.1.16\n* 修复字符串数组解析JSON时格式问题\n\n## 0.1.17\n* 增加设置消息自定义字符串和自定义整型\n\n## 0.1.18\n* 增加发送消息后返回消息对象\n\n## 0.1.19\n* 兼容所有发送消息后返回消息对象\n\n## 0.1.20\n* 会话列表增加能够获得发送人信息\n\n## 0.1.21\n* 发送新消息后，返回的数据对象有问题\n\n## 0.1.22\n* 修复 setMessageCustomInt 和 setMessageCustomString 报错的问题\n\n## 0.2.0\n1. 将发送消息统一更改为 sendMessage ,使用不同消息节点即可发送不同消息\n1. MessageEntity 增加 note 属性，对非自定消息可直接用于展示\n1. 发送节点和接收实体合二为一，发送时仅需设置构造器参数即可，接收时会自动填充内容\n1. 视频、语音，将不再自动下载，提供语音/视频下载方法\n1. 视频、语音和图片提供上传/下载进度监听器，分别为:ListenerTypeEnum.UploadProgress/ListenerTypeEnum.DownloadProgress\n1. 除 PendencyPageEntity 和 GroupPendencyPageEntity 外的所有Entity 重写 == 和 hashCode，可直接进行判断是否相等\n\n## 0.2.1\n* 修订文档\n\n## 0.2.2\n* 修改类名称\n\n## 0.2.3\n* 修复枚举名称\n\n## 0.2.4\n* 图片节点增加清晰度参数\n* 图片增加默认值填充\n\n## 0.2.5\n* 移除图片节点转换\n\n## 0.2.6\n修复ImageNode无法赋值的问题\n\n## 0.2.7\n修复自定义消息无法赋值的问题\n\n## 0.2.8\n修复删除会话无法删除本地消息的问题\n\n## 0.2.9\n* 修复MessageEntity传递方式\n* getMessages 和 getLocalMessages 增加根据lastMessage来筛选\n\n## 0.2.10\n* 修复 getMessage 和 getLocalMessage 根据lastMessage筛选 无效的问题\n\n## 0.2.11\n* 修复IOS无法获得消息的问题\n\n## 0.2.12\n* 修复Android获得消息报错\n\n## 0.2.13\n* 增加通用节点 Other\n\n## 0.2.14\n* 增加GroupTips节点\n\n## 0.2.15\n* 升级版本，无改动\n\n## 0.2.16\n* 优化：无论是群聊还是个人都会触发撤回回调\n\n## 0.2.17\n* 优化：群提示通知、群通知节点，使用同一个实体\n\n## 0.2.18\n* 修复：群提示节点userList始终为空的问题\n\n## 0.2.19\n* 增加: SNSSystemElem 的解析\n\n## 0.2.20\n* 增加：findMessage、saveMessage\n* 增加：init 时可配置日志相关内容\n\n## 0.2.21\n* 修复：IOS onReConnFailed、onConnFailed和onDisconnect 回调时崩溃的问题\n\n## 0.2.22\n* 修复：获取会话用户时，有时候获取不到\n\n## 0.2.23\n* 解决代码错误\n\n## 0.2.24\n* 修复Android：获取会话用户时，有时候获取不到\n\n## 0.2.25\n* 取消Android logout 方法的校验\n* 修改离线获取会话列表\n* 修改离线获取会话列表\n* 修改离线获取消息\n\n## 0.2.26\n* 增加监听器文档说明\n* 修改 modifyMemberInfo 参数不一致的问题\n* 修复Android创建群聊时，无法设置群成员的问题\n* 修复IOS创建群聊无法设置群成员问题\n\n## 0.2.27\n* 升级IM SDK版本为 4.8.10\n* 增加离线推送\n\n## 0.2.28\n* 修复 setToken int 无法转换为 long 的问题\n* 离线推送注册增加文档说明\n\n## 0.2.30\n* 修复 Android Int 转换为 Long 时报错\n\n## 0.2.31\n* 创建群组的群成员设置为可选属性\n\n## 0.2.32\n* 修复IOS applyJoinGroup 包错问题\n* 修复Demo NewMessages 监听器添加数据失败\n\n## 0.2.33\n* 修复IOS申请加入群组闪退问题\n* 修改申请加入群组 reason 为必传\n\n## 0.2.34\n* 修复 Native 和 Flutter 模型参数不一致\n\n## 0.2.35\n* 解决群未决处理TIMGroupPendencyItem的selfIdentifier为空的问题\n\n## 0.2.36\n* 解决发送图片后可能出现的错误\n* createGroup 接口增加 customInfo 信息\n* 替换Demo中视频缩略图获取的方案\n* 解决IOS Pod Install 后会报错\n\n## 0.2.37\n* 更换离线推送Token字符串解析方式(原方式不支持APNS)\n\n## 0.2.38\n* 修改 android getConversation 传入非存在sessionId的时候闪退问题\n\n## 0.2.39\n* 增加 GroupSystem 节点解析\n\n## 0.2.40\n* 增加 TIMProfileSystemElem 节点解析\n\n## 0.2.41\n* 修复IOS设备下 deleteConversation 接口无法接收返回值的问题\n\n## 0.2.42\n* 修复IOS运行报错\n\n## 0.2.43\n* 修复 ValueCallBack 错误码和描述信息反了的问题\n* 对登录操作不再做 isEmpty 验证\n\n## 0.2.44\n* 优化文本节点隐晦出现BUG的问题\n\n## 1.0.0\n* 集成 SDK 5.1.1\n\n## 1.0.1\n* 优化Demo\n\n## 1.0.2\n* 修复回调调用异常的问题\n\n## 1.0.3\n* 修复对象解析错误异常\n\n## 1.0.4\n* 修复 getFriendGroups 接口参数为必传的问题\n\n## 1.0.5\n* 升级SDK到 5.1.2\n* 增加 getGroupOnlineMemberCount 接口\n\n## 1.0.6\n* 修复 C2CReadReceipt 回调异常的问题\n\n## 1.1.0\n* 优化会话相关接口，提供内部转换\n* 增加 getHistoryMessageList 和 markMessageAsRead 接口\n\n## 1.1.1\n* 修改混淆文件\n\n## 1.1.2\n* 修复 SignalingCommonEntity 实体转换失败的问题\n\n## 1.1.3\n* 修复消息发送进度回调数据转换异常的问题\n\n## 1.1.4\n* 修复 addFriend 添加好友异常的问题\n\n## 1.1.5\n* 修复 MessageRevoked 监听没有参数问题\n\n## 1.1.6\n* 增加 GroupTips 数据节点解析\n\n## 1.2.0\n* 1. Android 和 IOS 将所有监听器的参数二次转换为 json 取消\n* 2. 适配Flutter\n\n## 1.2.1\n* 增加 setMessageLocalCustomStr 和 setMessageLocalCustomInt 接口\n\n## 1.2.2\n* 修复下载进度出现Optiona的问题\n\n## 1.2.3\n* 修复部分回调没有正确接收到参数的问题\n* Demo增加生成签名\n* 修复部分回调在 IOS 端下包含 Optional 的问题\n* 升级SDK版本为 5.1.10\n\n## 1.2.4\n* 修复 setMessageLocalCustomStr 执行失败的问题\n* Demo增加发起会话\n* 修复 onReceiveNewInvitation 解包失败的问题\n\n## 1.2.5\n* 修复回调非主线程闪退问题\n\n## 1.2.6\n* 修复获得会话传递nextSeq异常的问题\n\n## 1.2.7\n* 修复Android端fastjson打包闪退的问题\n* DownloadProgress 回调增加 type 属性\n* 消息重发接口\n* IOS发送消息进度和失败消息的ID未解包的问题\n\n## 1.2.8\n* 新增 downloadFile 接口\n* 新增 findMessages 接口\n* 对部分关键实体实体重写 == 操作符(非所有实体)\n* 修复IOS端不能发送视频的问题\n* 修复 BeanUtils 访问权限导致调用内部方法报错的问题\n\n## 1.2.9\n* 修复文件发送失败的问题\n\n## 1.2.10\n* 修复发送文件FileName不生效的问题\n\n## 1.2.11\n* 修复 Android getGroupOnlineMemberCount 接口无法解析的问题\n\n## 1.2.12\n* 修复信令data为空的问题\n\n## 1.2.13\n* 修复unInit后再次init，会导致监听器重复的问题\n* 修复IOS上at列表为空时会导致闪退\n* 修复ios上at功能异常的问题\n* 增加getVersion、和getServerTime接口\n* 增加群自定义字段\n* 升级SDK为 5.1.50\n* 自定义节点增加 desc 和 ext 字段\n* 用户资料增加 role 和 level 字段\n* 更新getHistoryMessageList接口，增加type属性\n* 消息对象增加 random\n\n## 1.2.14\n* fix \"修复IOS环境下自定义节点 desc 和 ext 无法使用的问题\"\n* fix \"修复 inviteInGroup 接口在Android下会闪退的问题\"\n* feat \"更新内部依赖插件版本\"\n* docs \"更新文档\"\n\n## 2.0.0\n* feat 增加空安全\n\n## 2.0.1\n* docs 格式化文档\n\n## 2.0.2\n* 优化空安全\n\n## 2.0.3\n* fix 修复android调用createGroup返回的群ID中含有字符串的问题\n* feat Demo中增加创建群聊\n* feat 升级SDK版本为 5.1.62\n* fix 修复ios setGroupInfo 接口会清空其它字段的问题\n* fix 修复ios setSelfInfo 无效的问题\n\n## 2.0.4\n* feat 增加FindFriendApplicationEntity 快速创建方法\n\n## 2.0.5\n* feat FileMessageNode 节点中，filePath 和 fileName 增加可为空选择\n\n## 3.0.0\n* feat 调整所有空返回值结果为明确指定\n* feat 升级版本到最新增强版 `5.5.897`\n* feat ``setGroupReceiveMessageOpt`` 设置群接收消息选项接口\n* feat ``setC2CReceiveMessageOpt`` 设置C2C接收消息选项接口\n* feat ``ReceiveMessageOptEnum`` 接收消息选项枚举类\n* feat ``pinConversation`` 置顶会话接口\n* feat ``getTotalUnreadMessageCount`` 获得会话总未读数接口\n* feat ``conversation`` 增加 ``pinned`` 会话是否置顶属性\n* feat `MessageStatusEnum` 增加 Imported 属性\n* Remove ``setReceiveMessageOpt`` 接口\n* Remove ``GroupReceiveMessageOptEnum`` 枚举\n* fix 修复 SignalingInfoEntity 反序列化报错的问题\n* fix 修复信令邀请回调没有群ID的问题\n* fix 修复IOS信令相关接口闪退的问题\n* fix 修复Android CustomMessageEntity 创建抛出空指针问题\n* fix 修复Android getGroupMemberList 接口nextSeq传递无效的问题\n* fix 修复部分接口在ios设置自定义字段无效\n* fix 修复Android和IOS Tag_Profile_Custom_ 不统一问题"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   Copyright 2013-2018 Docker, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       https://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n\n[![](https://img.shields.io/badge/flutter2.0-NullSafety-1)](#)\n[![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-)\n[![](https://img.shields.io/badge/Version-社区版-1)](#)\n[![](https://img.shields.io/pub/v/tencent_im_plugin.svg)](https://pub.dartlang.org/packages/tencent_im_plugin)\n[![](https://img.shields.io/github/license/JiangJuHong/FlutterTencentImPlugin)](https://www.apache.org/licenses/LICENSE-2.0)\n[![](https://img.shields.io/badge/qq群-850923396-1)](https://jq.qq.com/?_wv=1027&k=QxCWMlUf)\n\n</div>\n\n# What is FlutterTencentIm ？\n\n# 终章\n## 致所有FlutterTencentIm贡献者及用户\n````\n即日起，FlutterTencentIm停止维护，永久保留仓库代码。感谢所有贡献者的帮助，同时感谢所有用户长期以来的支持。\n如果您的项目中还需要集成TIM服务，请移至: https://cloud.tencent.com/document/product/269/51940 或 https://github.com/TencentCloud/chat-sdk-flutter/tree/main/example。\n关闭说明:\n    1. 腾讯终于推出了官方SDK，维护更稳定，推荐使用\n\n一个项目的征途结束了，开源的步伐永远不滞。\n欢迎加入Flutter讨论群，QQ群号: 850923396\n````\n\nFlutterTencentIM是基于[腾讯云即时通讯](https://cloud.tencent.com/product/im)服务进行的Flutter封装，为Flutter提供即时通讯服务.\n\n# 3. X has arrived?\n\n最新计划为3.x，大致更改内容如下:  \n【注意: 这是未完成的内容，请谨慎使用】3.x对原有接口进行了细微调整，您可根据 [升级文档](/README_3.0_upgrade.md) 进行升级\n\n| 功能列表                 | 进度 |\n|:-----------------------|:-----|\n| 保持基础接口不变          | ✅   |\n| SDK从原有标准版升级为增强版 | ✅   |\n| 增加增强版所有功能         | ☑️   |\n\n# Notice\n\n💐💐\n新版插件支持空安全(`null-safety`)，如需查看非空安全版本，请切换分支到:`sdk-5.1.x-non-null-safety`💐💐  \n💐 FlutterTencentIm 开放 Pull Request，merge 成功后会在 README.md\n上留下您的大名并超链到您的 Github 主页！\n\n# 官方版和社区版的区别\n\n* 两者的区别：本质上官方版和社区版都是基于IM的SDK进行封装，官方版的更偏向三端写法类似(Android、IOS、Flutter)，社区版则提供更便捷的使用方式(1分钟上手即用)(例:\n  FlutterImPlugin.login)。\n* 该如何选择：根据个人编码习惯选择即可。\n* 维护的周期：社区版和官方版均在持续迭代，发现异常将会在第一时间进行修复。\n\n# Sdk Version\n\n| 平台     | SDK版本 |\n|:--------|:-------|\n| Android | 5.5.897 |\n| IOS     | 5.5.897 |\n\n# Links\n\n* [Document](https://www.yuque.com/jiangjuhong/tencent-im-flutter/zk6p14)\n* [Chat](https://jq.qq.com/?_wv=1027&k=QxCWMlUf)\n* [Sponsor](https://www.yuque.com/jiangjuhong/tencent-im-flutter/ygi582)\n\n# Customization\n\n如果您的项目有定制化需求，可通过QQ(690717394) 或 邮箱(690717394@qq.com)\n联系我，该项服务为有偿服务，具体价格根据需求量进行决定。\n\n# Other Plugins\n\n````\n我同时维护的还有以下插件，如果您感兴趣与我一起进行维护，请通过Github联系我，欢迎 issues 和 PR。\n````\n\n| 平台     | 插件                                                                                            | 描述                       | 版本                                                                                                                                 |\n|:--------|:------------------------------------------------------------------------------------------------|:--------------------------|:------------------------------------------------------------------------------------------------------------------------------------|\n| Flutter | [FlutterVideoPlayerLibrary-Desc](https://github.com/JiangJuHong/FlutterVideoPlayerLibrary-Desc) | Flutter 最好用的播放器(UI库) | -                                                                                                                                   |\n| 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) |\n| 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)           |\n| 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)         |\n| 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)       |\n| 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)       |\n| 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)               |\n| 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)         |\n| Flutter | [FlutterQiniucloudLivePlugin](https://github.com/JiangJuHong/FlutterQiniucloudLivePlugin)       | Flutter 七牛云直播云插件     | 暂未发布，通过 git 集成                                                                                                                |\n\n## Contributors ✨\n\nThanks goes to these wonderful people\n([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n\n<table>\n  <tr>\n    <td align=\"center\"><a href=\"https://github.com/kxr224\"><img src=\"https://avatars.githubusercontent.com/u/28681083?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>cyrus</b></sub></a><br /><a href=\"https://github.com/JiangJuHong/FlutterTencentImPlugin/issues?q=author%3Akxr224\" title=\"Bug reports\">🐛</a></td>\n    <td align=\"center\"><a href=\"https://github.com/songjiabin\"><img src=\"https://avatars.githubusercontent.com/u/13177100?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>宋佳宾</b></sub></a><br /><a href=\"https://github.com/JiangJuHong/FlutterTencentImPlugin/commits?author=songjiabin\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"https://github.com/ligui-iOS\"><img src=\"https://avatars.githubusercontent.com/u/20856361?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>ligui-iOS</b></sub></a><br /><a href=\"https://github.com/JiangJuHong/FlutterTencentImPlugin/commits?author=ligui-iOS\" title=\"Code\">💻</a></td>\n    <td align=\"center\"><a href=\"http://laiiihz.github.io\"><img src=\"https://avatars.githubusercontent.com/u/35956195?v=4?s=100\" width=\"100px;\" alt=\"\"/><br /><sub><b>LAIIIHZ</b></sub></a><br /><a href=\"https://github.com/JiangJuHong/FlutterTencentImPlugin/commits?author=laiiihz\" title=\"Code\">💻</a></td>\n  </tr>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n\nThis project follows the\n[all-contributors](https://github.com/all-contributors/all-contributors)\nspecification. Contributions of any kind welcome!\n"
  },
  {
    "path": "README_3.0_upgrade.md",
    "content": "# 3.0升级文档\n\n## 通用变化\n\n* 将 `setReceiveMessageOpt` 替换为 `setGroupReceiveMessageOpt`\n* 将 `GroupReceiveMessageOptEnum` 替换为 `ReceiveMessageOptEnum`\n* `MessageStatusEnum` 增加 Imported 属性\n\n## 新增内容\n\n* 新增 ``setGroupReceiveMessageOpt`` 设置群接收消息选项接口\n* 新增 ``setC2CReceiveMessageOpt`` 设置C2C接收消息选项接口\n* 新增 ``ReceiveMessageOptEnum`` 接收消息选项枚举类\n* 新增 ``pinConversation`` 置顶会话接口\n* 新增 ``getTotalUnreadMessageCount`` 获得会话总未读数接口\n* 新增 ``conversation`` 增加 ``pinned`` 会话是否置顶属性\n* 新增 ``insertC2CMessageToLocalStorage`` 添加C2C会话接口\n* 新增 ``setOfflinePushConfig`` 接口增加 tpns 参数\n* 新增 ``searchGroups`` 搜索群接口\n* 新增 ``searchGroupMembers`` 搜索群成员接口\n* 新增 ``UserEntity`` 增加 生日(birthday) 属性\n\n## 移除内容\n\n* 移除 ``setReceiveMessageOpt`` 接口\n* 移除 ``GroupReceiveMessageOptEnum`` 枚举"
  },
  {
    "path": "android/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": "android/build.gradle",
    "content": "group 'top.huic.tencent_im_plugin'\nversion '1.0'\n\nbuildscript {\n    repositories {\n//        maven { url 'https://maven.aliyun.com/repository/google' }\n//        maven { url 'https://maven.aliyun.com/repository/jcenter' }\n//        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }\n        google()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.5.3'\n    }\n}\n\nrootProject.allprojects {\n    repositories {\n//        maven { url 'https://maven.aliyun.com/repository/google' }\n//        maven { url 'https://maven.aliyun.com/repository/jcenter' }\n//        maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }\n        google()\n        jcenter()\n    }\n}\n\napply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion 28\n\n    defaultConfig {\n        minSdkVersion 16\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n        ndk {\n            abiFilters \"armeabi-v7a\"\n        }\n        // library 混淆 -> 随 library 引用，自动添加到 apk 打包混淆\n        consumerProguardFiles 'consumer-proguard-rules.txt'\n    }\n    lintOptions {\n        disable 'InvalidPackage'\n    }\n    dependencies {\n        api 'com.tencent.imsdk:imsdk-plus:6.1.2155'\n        api 'com.alibaba:fastjson:1.1.72.android'\n    }\n}\n"
  },
  {
    "path": "android/consumer-proguard-rules.txt",
    "content": "# 腾讯云IM\n-keep class com.tencent.** { *; }\n\n# FastJson\n-dontwarn com.alibaba.fastjson.**\n-keep class com.alibaba.fastjson.**{*;}\n\n# 泛型\n-keepattributes Signature\n\n# 不混淆Serializable接口的子类\n-keepclassmembers class * implements java.io.Serializable { *; }\n\n# 忽略实体类\n-keep class top.huic.tencent_im_plugin.** {*;}"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Dec 05 14:15:15 CST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-5.4.1-all.zip\n"
  },
  {
    "path": "android/gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx1536M\nandroid.enableR8=true\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "android/settings.gradle",
    "content": "rootProject.name = 'tencent_im_plugin'\n"
  },
  {
    "path": "android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  package=\"top.huic.tencent_im_plugin\">\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.CAMERA\" />\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n</manifest>\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/DownloadCallBack.java",
    "content": "package top.huic.tencent_im_plugin;\n\nimport com.tencent.imsdk.v2.V2TIMDownloadCallback;\nimport com.tencent.imsdk.v2.V2TIMElem;\n\nimport java.util.HashMap;\n\nimport io.flutter.plugin.common.MethodChannel;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * 下载回调\n */\npublic class DownloadCallBack implements V2TIMDownloadCallback {\n\n    /**\n     * 结果方法\n     */\n    private MethodChannel.Result result;\n\n    /**\n     * 下载路径\n     */\n    private String path;\n\n    /**\n     * 消息ID\n     */\n    private String msgId;\n\n    /**\n     * 下载类型\n     */\n    private DownloadTypeEnum type;\n\n    public DownloadCallBack() {\n    }\n\n    public DownloadCallBack(String path) {\n        this.path = path;\n    }\n\n    public DownloadCallBack(MethodChannel.Result result, String path, String msgId, DownloadTypeEnum type) {\n        this.result = result;\n        this.path = path;\n        this.msgId = msgId;\n        this.type = type;\n    }\n\n    @Override\n    public void onProgress(final V2TIMElem.V2ProgressInfo v2ProgressInfo) {\n        TencentImPlugin.invokeListener(ListenerTypeEnum.DownloadProgress, new HashMap<String, Object>() {\n            {\n                put(\"type\", type.getValue());\n                put(\"msgId\", msgId);\n                put(\"currentSize\", v2ProgressInfo.getCurrentSize());\n                put(\"totalSize\", v2ProgressInfo.getTotalSize());\n            }\n        });\n    }\n\n    /**\n     * 成功事件\n     */\n    @Override\n    public void onSuccess() {\n        if (result != null) {\n            result.success(path);\n        }\n    }\n\n\n    /**\n     * 失败事件\n     *\n     * @param code 错误码\n     * @param desc 错误描述\n     */\n    @Override\n    public void onError(int code, String desc) {\n        if (this.result != null) {\n            result.error(String.valueOf(code), desc, desc);\n        }\n    }\n\n    /**\n     * 下载类型枚举\n     */\n    public enum DownloadTypeEnum {\n        /**\n         * 语音\n         */\n        Sound(0),\n\n        /**\n         * 视频\n         */\n        Video(1),\n\n        /**\n         * 视频缩略图\n         */\n        VideoThumbnail(2),\n\n        /**\n         * 视频缩略图\n         */\n        File(3);\n\n        /**\n         * 枚举对应的常量值\n         */\n        private Integer value;\n\n        DownloadTypeEnum(Integer value) {\n            this.value = value;\n        }\n\n        public Integer getValue() {\n            return value;\n        }\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/TencentImPlugin.java",
    "content": "package top.huic.tencent_im_plugin;\n\nimport android.content.Context;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport com.tencent.imsdk.v2.V2TIMConversation;\nimport com.tencent.imsdk.v2.V2TIMConversationResult;\nimport com.tencent.imsdk.v2.V2TIMCreateGroupMemberInfo;\nimport com.tencent.imsdk.v2.V2TIMFriendApplication;\nimport com.tencent.imsdk.v2.V2TIMFriendApplicationResult;\nimport com.tencent.imsdk.v2.V2TIMFriendCheckResult;\nimport com.tencent.imsdk.v2.V2TIMFriendGroup;\nimport com.tencent.imsdk.v2.V2TIMFriendInfo;\nimport com.tencent.imsdk.v2.V2TIMFriendInfoResult;\nimport com.tencent.imsdk.v2.V2TIMFriendOperationResult;\nimport com.tencent.imsdk.v2.V2TIMGroupApplication;\nimport com.tencent.imsdk.v2.V2TIMGroupApplicationResult;\nimport com.tencent.imsdk.v2.V2TIMGroupInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupInfoResult;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberFullInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberInfoResult;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberOperationResult;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberSearchParam;\nimport com.tencent.imsdk.v2.V2TIMGroupSearchParam;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMMessageListGetOption;\nimport com.tencent.imsdk.v2.V2TIMMessageSearchParam;\nimport com.tencent.imsdk.v2.V2TIMMessageSearchResult;\nimport com.tencent.imsdk.v2.V2TIMOfflinePushConfig;\nimport com.tencent.imsdk.v2.V2TIMOfflinePushInfo;\nimport com.tencent.imsdk.v2.V2TIMReceiveMessageOptInfo;\nimport com.tencent.imsdk.v2.V2TIMSDKConfig;\nimport com.tencent.imsdk.v2.V2TIMSendCallback;\nimport com.tencent.imsdk.v2.V2TIMSignalingInfo;\nimport com.tencent.imsdk.v2.V2TIMUserFullInfo;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport io.flutter.embedding.engine.plugins.FlutterPlugin;\nimport io.flutter.plugin.common.MethodCall;\nimport io.flutter.plugin.common.MethodChannel;\nimport io.flutter.plugin.common.MethodChannel.MethodCallHandler;\nimport io.flutter.plugin.common.MethodChannel.Result;\nimport io.flutter.plugin.common.PluginRegistry.Registrar;\nimport top.huic.tencent_im_plugin.entity.CustomConversationEntity;\nimport top.huic.tencent_im_plugin.entity.CustomConversationResultEntity;\nimport top.huic.tencent_im_plugin.entity.CustomFriendAddApplication;\nimport top.huic.tencent_im_plugin.entity.CustomMessageEntity;\nimport top.huic.tencent_im_plugin.entity.FindMessageEntity;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\nimport top.huic.tencent_im_plugin.listener.CustomAdvancedMsgListener;\nimport top.huic.tencent_im_plugin.listener.CustomConversationListener;\nimport top.huic.tencent_im_plugin.listener.CustomFriendshipListener;\nimport top.huic.tencent_im_plugin.listener.CustomGroupListener;\nimport top.huic.tencent_im_plugin.listener.CustomSDKListener;\nimport top.huic.tencent_im_plugin.listener.CustomSignalingListener;\nimport top.huic.tencent_im_plugin.message.AbstractMessageNode;\nimport top.huic.tencent_im_plugin.message.entity.AbstractMessageEntity;\nimport top.huic.tencent_im_plugin.util.CommonUtil;\nimport top.huic.tencent_im_plugin.util.JsonUtil;\nimport top.huic.tencent_im_plugin.util.TencentImUtils;\n\n/**\n * TencentImPlugin\n */\npublic class TencentImPlugin implements FlutterPlugin, MethodCallHandler {\n    /**\n     * 全局上下文\n     */\n    public static Context context;\n\n    /**\n     * 与Flutter的通信管道\n     */\n    private static MethodChannel channel;\n\n    /**\n     * Sdk监听器\n     */\n    private final CustomSDKListener sdkListener = new CustomSDKListener();\n\n    /**\n     * 消息监听器\n     */\n    private final CustomAdvancedMsgListener advancedMsgListener = new CustomAdvancedMsgListener();\n\n    /**\n     * 会话监听器\n     */\n    private final CustomConversationListener conversationListener = new CustomConversationListener();\n\n    /**\n     * 群监听器\n     */\n    private final CustomGroupListener groupListener = new CustomGroupListener();\n\n    /**\n     * 关系链监听器\n     */\n    private final CustomFriendshipListener friendshipListener = new CustomFriendshipListener();\n\n    /**\n     * 信令监听器\n     */\n    private final CustomSignalingListener signalingListener = new CustomSignalingListener();\n\n    public TencentImPlugin() {\n    }\n\n    private TencentImPlugin(Context context, MethodChannel channel) {\n        TencentImPlugin.context = context;\n        TencentImPlugin.channel = channel;\n        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.mask;\n    }\n\n    @Override\n    public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) {\n        final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), \"tencent_im_plugin\");\n        channel.setMethodCallHandler(new TencentImPlugin(flutterPluginBinding.getApplicationContext(), channel));\n    }\n\n    // This static function is optional and equivalent to onAttachedToEngine. It supports the old\n    // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting\n    // plugin registration via this function while apps migrate to use the new Android APIs\n    // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.\n    //\n    // It is encouraged to share logic between onAttachedToEngine and registerWith to keep\n    // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called\n    // depending on the user's project. onAttachedToEngine or registerWith must both be defined\n    // in the same class.\n    public static void registerWith(Registrar registrar) {\n        final MethodChannel channel = new MethodChannel(registrar.messenger(), \"tencent_im_plugin\");\n        channel.setMethodCallHandler(new TencentImPlugin(registrar.context(), channel));\n    }\n\n    @Override\n    public void onMethodCall(MethodCall call, Result result) {\n        try {\n            Method method = this.getClass().getDeclaredMethod(call.method, MethodCall.class, Result.class);\n            method.setAccessible(true);\n            method.invoke(this, call, result);\n        } catch (NoSuchMethodException e) {\n            result.notImplemented();\n        } catch (IllegalAccessException e) {\n            result.notImplemented();\n        } catch (InvocationTargetException ignored) {\n        }\n    }\n\n\n    @Override\n    public void onDetachedFromEngine(FlutterPluginBinding binding) {\n    }\n\n    /**\n     * 腾讯云Im初始化事件\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void initSDK(MethodCall methodCall, Result result) {\n        String appid = CommonUtil.getParam(methodCall, result, \"appid\");\n        Integer logPrintLevel = methodCall.argument(\"logPrintLevel\");\n\n        // 初始化 SDK\n        V2TIMSDKConfig sdkConfig = new V2TIMSDKConfig();\n        if (logPrintLevel != null) {\n            sdkConfig.setLogLevel(logPrintLevel);\n        }\n        V2TIMManager.getInstance().initSDK(context, Integer.parseInt(appid), sdkConfig, sdkListener);\n\n        // 绑定消息监听\n        V2TIMManager.getMessageManager().addAdvancedMsgListener(this.advancedMsgListener);\n\n        // 绑定会话监听器\n        V2TIMManager.getConversationManager().setConversationListener(this.conversationListener);\n\n        // 绑定群监听器\n        V2TIMManager.getInstance().setGroupListener(this.groupListener);\n\n        // 绑定关系链监听器\n        V2TIMManager.getFriendshipManager().setFriendListener(this.friendshipListener);\n\n        // 绑定信令监听器\n        V2TIMManager.getSignalingManager().addSignalingListener(this.signalingListener);\n\n        result.success(null);\n    }\n\n\n    /**\n     * 反初始化\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void unInitSDK(MethodCall methodCall, Result result) {\n        V2TIMManager.getInstance().unInitSDK();\n        V2TIMManager.getMessageManager().removeAdvancedMsgListener(this.advancedMsgListener);\n        V2TIMManager.getSignalingManager().removeSignalingListener(this.signalingListener);\n        result.success(null);\n    }\n\n    /**\n     * 获得SDK版本\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getVersion(MethodCall methodCall, Result result) {\n        result.success(V2TIMManager.getInstance().getVersion());\n    }\n\n    /**\n     * 获得服务器当前时间\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getServerTime(MethodCall methodCall, Result result) {\n        result.success(V2TIMManager.getInstance().getServerTime());\n    }\n\n    /**\n     * 腾讯云 IM 登录\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void login(MethodCall methodCall, final Result result) {\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        String userSig = CommonUtil.getParam(methodCall, result, \"userSig\");\n\n        // 登录操作\n        V2TIMManager.getInstance().login(userID, userSig, new VoidCallBack(result));\n    }\n\n    /**\n     * 腾讯云 IM 退出登录\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void logout(MethodCall methodCall, final Result result) {\n        V2TIMManager.getInstance().logout(new VoidCallBack(result));\n    }\n\n    /**\n     * 获得登录状态\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getLoginStatus(MethodCall methodCall, final Result result) {\n        result.success(V2TIMManager.getInstance().getLoginStatus());\n    }\n\n    /**\n     * 腾讯云 获得当前登录用户\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getLoginUser(MethodCall methodCall, final Result result) {\n        result.success(V2TIMManager.getInstance().getLoginUser());\n    }\n\n    /**\n     * 邀请某个人\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void invite(MethodCall methodCall, final Result result) {\n        String invitee = CommonUtil.getParam(methodCall, result, \"invitee\");\n        String data = CommonUtil.getParam(methodCall, result, \"data\");\n        Boolean onlineUserOnly = CommonUtil.getParam(methodCall, result, \"onlineUserOnly\");\n        String offlinePushInfoStr = CommonUtil.getParam(methodCall, result, \"offlinePushInfo\");\n        int timeout = CommonUtil.getParam(methodCall, result, \"timeout\");\n\n        // 将离线推送配置转换为JSON对象以及离线推送对象\n        JSONObject jsonObject = JSON.parseObject(offlinePushInfoStr);\n        V2TIMOfflinePushInfo offlinePushInfo = JSON.parseObject(offlinePushInfoStr, V2TIMOfflinePushInfo.class);\n        if (jsonObject.get(\"disablePush\") != null) {\n            offlinePushInfo.disablePush(jsonObject.getBoolean(\"disablePush\"));\n        }\n\n        // 发送邀请，并同步返回结果\n        result.success(V2TIMManager.getSignalingManager().invite(invitee, data, onlineUserOnly, offlinePushInfo, timeout, new VoidCallBack(null)));\n    }\n\n    /**\n     * 邀请群内的某些人\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void inviteInGroup(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        List<String> inviteeList = new ArrayList<>(Arrays.asList(CommonUtil.getParam(methodCall, result, \"inviteeList\").toString().split(\",\")));\n        String data = CommonUtil.getParam(methodCall, result, \"data\");\n        Boolean onlineUserOnly = CommonUtil.getParam(methodCall, result, \"onlineUserOnly\");\n        int timeout = CommonUtil.getParam(methodCall, result, \"timeout\");\n\n        // 发送邀请，并同步返回结果\n        result.success(V2TIMManager.getSignalingManager().inviteInGroup(groupID, inviteeList, data, onlineUserOnly, timeout, new VoidCallBack(null)));\n    }\n\n    /**\n     * 邀请方取消邀请\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void cancel(MethodCall methodCall, final Result result) {\n        String inviteID = CommonUtil.getParam(methodCall, result, \"inviteID\");\n        String data = CommonUtil.getParam(methodCall, result, \"data\");\n        V2TIMManager.getSignalingManager().cancel(inviteID, data, new VoidCallBack(result));\n    }\n\n    /**\n     * 接收方接收邀请\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void accept(MethodCall methodCall, final Result result) {\n        String inviteID = CommonUtil.getParam(methodCall, result, \"inviteID\");\n        String data = CommonUtil.getParam(methodCall, result, \"data\");\n        V2TIMManager.getSignalingManager().accept(inviteID, data, new VoidCallBack(result));\n    }\n\n    /**\n     * 接收方拒绝邀请\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void reject(MethodCall methodCall, final Result result) {\n        String inviteID = CommonUtil.getParam(methodCall, result, \"inviteID\");\n        String data = CommonUtil.getParam(methodCall, result, \"data\");\n        V2TIMManager.getSignalingManager().reject(inviteID, data, new VoidCallBack(result));\n    }\n\n    /**\n     * 获得信令信息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getSignalingInfo(MethodCall methodCall, final Result result) {\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                result.success(JsonUtil.toJSONString(V2TIMManager.getSignalingManager().getSignalingInfo(message)));\n            }\n        });\n    }\n\n    /**\n     * 添加邀请信令（可以用于群离线推送消息触发的邀请信令）\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void addInvitedSignaling(MethodCall methodCall, final Result result) {\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        V2TIMManager.getSignalingManager().addInvitedSignaling(JSON.parseObject(info, V2TIMSignalingInfo.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 发送消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void sendMessage(MethodCall methodCall, final Result result) {\n        String nodeStr = CommonUtil.getParam(methodCall, result, \"node\");\n        Map node = JSON.parseObject(nodeStr, Map.class);\n\n        // 设置节点信息获得V2TIMMessage对象\n        AbstractMessageNode messageNode = MessageNodeType.getMessageNodeTypeByV2TIMConstant(Integer.valueOf(node.get(\"nodeType\").toString())).getMessageNodeInterface();\n        AbstractMessageEntity messageEntity = (AbstractMessageEntity) JSON.parseObject(nodeStr, messageNode.getEntityClass());\n        V2TIMMessage message = messageNode.getV2TIMMessage(messageEntity);\n\n        // 发送消息\n        this._sendMessage(message, methodCall, result);\n    }\n\n    /**\n     * 重发消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void resendMessage(final MethodCall methodCall, final Result result) {\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                _sendMessage(message, methodCall, result);\n            }\n        });\n    }\n\n    /**\n     * 发送消息\n     *\n     * @param message    V2TIMMessage消息对象\n     * @param methodCall Flutter方法调用对象\n     * @param result     Flutter 返回结果\n     */\n    private void _sendMessage(V2TIMMessage message, MethodCall methodCall, final Result result) {\n        String receiver = methodCall.argument(\"receiver\");\n        final String groupID = methodCall.argument(\"groupID\");\n        boolean ol = CommonUtil.getParam(methodCall, result, \"ol\");\n        Integer priority = CommonUtil.getParam(methodCall, result, \"priority\");\n        String offlinePushInfo = methodCall.argument(\"offlinePushInfo\");\n        Integer localCustomInt = methodCall.argument(\"localCustomInt\");\n        String localCustomStr = methodCall.argument(\"localCustomStr\");\n\n        if (localCustomInt != null) {\n            message.setLocalCustomInt(localCustomInt);\n        }\n        if (localCustomStr != null) {\n            message.setLocalCustomData(localCustomStr);\n        }\n\n        final String[] msgId = new String[1];\n        V2TIMSendCallback<V2TIMMessage> callback = new V2TIMSendCallback<V2TIMMessage>() {\n            @Override\n            public void onError(final int i, final String s) {\n                TencentImPlugin.invokeListener(ListenerTypeEnum.MessageSendFail, new HashMap<String, Object>() {\n                    {\n                        put(\"msgId\", msgId[0]);\n                        put(\"code\", i);\n                        put(\"desc\", s);\n                    }\n                });\n            }\n\n            @Override\n            public void onSuccess(V2TIMMessage o) {\n                TencentImPlugin.invokeListener(ListenerTypeEnum.MessageSendSucc, new CustomMessageEntity(o));\n            }\n\n            @Override\n            public void onProgress(final int i) {\n                TencentImPlugin.invokeListener(ListenerTypeEnum.MessageSendProgress, new HashMap<String, Object>() {\n                    {\n                        put(\"msgId\", msgId[0]);\n                        put(\"progress\", i);\n                    }\n                });\n            }\n        };\n\n        // 发送消息\n        msgId[0] = V2TIMManager.getMessageManager().sendMessage(message, receiver, groupID, priority, ol, offlinePushInfo == null ? null : JSON.parseObject(offlinePushInfo, V2TIMOfflinePushInfo.class), callback);\n        result.success(msgId[0]);\n    }\n\n\n    /**\n     * 撤回消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void revokeMessage(MethodCall methodCall, final Result result) {\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                V2TIMManager.getMessageManager().revokeMessage(message, new VoidCallBack(result));\n            }\n        });\n    }\n\n    /**\n     * 获得单聊历史记录\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getC2CHistoryMessageList(MethodCall methodCall, final Result result) {\n        final String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        final int count = CommonUtil.getParam(methodCall, result, \"count\");\n        final String lastMsgStr = methodCall.argument(\"lastMsg\");\n\n        // 返回回调对象\n        final ValueCallBack<List<V2TIMMessage>> resultCallBack = new ValueCallBack<List<V2TIMMessage>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {\n                List<CustomMessageEntity> resultData = new ArrayList<>(v2TIMMessages.size());\n                for (V2TIMMessage v2TIMMessage : v2TIMMessages) {\n                    resultData.add(new CustomMessageEntity(v2TIMMessage));\n                }\n                result.success(JsonUtil.toJSONString(resultData));\n            }\n        };\n\n\n        // 根据是否传递最后一条消息进行特殊处理\n        if (lastMsgStr == null) {\n            V2TIMManager.getMessageManager().getC2CHistoryMessageList(userID, count, null, resultCallBack);\n        } else {\n            TencentImUtils.getMessageByFindMessageEntity(lastMsgStr, new ValueCallBack<V2TIMMessage>(result) {\n                @Override\n                public void onSuccess(V2TIMMessage message) {\n                    V2TIMManager.getMessageManager().getC2CHistoryMessageList(userID, count, message, resultCallBack);\n                }\n            });\n        }\n    }\n\n    /**\n     * 获得群聊历史记录\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupHistoryMessageList(MethodCall methodCall, final Result result) {\n        final String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        final int count = CommonUtil.getParam(methodCall, result, \"count\");\n        String lastMsgStr = methodCall.argument(\"lastMsg\");\n\n        // 返回回调对象\n        final ValueCallBack<List<V2TIMMessage>> resultCallBack = new ValueCallBack<List<V2TIMMessage>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {\n                List<CustomMessageEntity> resultData = new ArrayList<>(v2TIMMessages.size());\n                for (V2TIMMessage v2TIMMessage : v2TIMMessages) {\n                    resultData.add(new CustomMessageEntity(v2TIMMessage));\n                }\n                result.success(JsonUtil.toJSONString(resultData));\n            }\n        };\n\n\n        // 根据是否传递最后一条消息进行特殊处理\n        if (lastMsgStr == null) {\n            V2TIMManager.getMessageManager().getGroupHistoryMessageList(groupID, count, null, resultCallBack);\n        } else {\n            TencentImUtils.getMessageByFindMessageEntity(lastMsgStr, new ValueCallBack<V2TIMMessage>(result) {\n                @Override\n                public void onSuccess(V2TIMMessage message) {\n                    V2TIMManager.getMessageManager().getGroupHistoryMessageList(groupID, count, message, resultCallBack);\n                }\n            });\n        }\n    }\n\n    /**\n     * 获得消息记录\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getHistoryMessageList(MethodCall methodCall, final Result result) {\n        final String groupID = methodCall.argument(\"groupID\");\n        final String userID = methodCall.argument(\"userID\");\n        final int count = CommonUtil.getParam(methodCall, result, \"count\");\n        final int type = CommonUtil.getParam(methodCall, result, \"type\");\n        String lastMsgStr = methodCall.argument(\"lastMsg\");\n\n        // 返回回调对象\n        final ValueCallBack<List<V2TIMMessage>> resultCallBack = new ValueCallBack<List<V2TIMMessage>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {\n                List<CustomMessageEntity> resultData = new ArrayList<>(v2TIMMessages.size());\n                for (V2TIMMessage v2TIMMessage : v2TIMMessages) {\n                    resultData.add(new CustomMessageEntity(v2TIMMessage));\n                }\n                result.success(JsonUtil.toJSONString(resultData));\n            }\n        };\n\n        // 根据是否传递最后一条消息进行特殊处理\n        final V2TIMMessageListGetOption opt = new V2TIMMessageListGetOption();\n        opt.setUserID(userID);\n        opt.setGroupID(groupID);\n        opt.setGetType(type);\n        opt.setCount(count);\n        if (lastMsgStr == null) {\n            V2TIMManager.getMessageManager().getHistoryMessageList(opt, resultCallBack);\n        } else {\n            TencentImUtils.getMessageByFindMessageEntity(lastMsgStr, new ValueCallBack<V2TIMMessage>(result) {\n                @Override\n                public void onSuccess(V2TIMMessage message) {\n                    opt.setLastMsg(message);\n                    V2TIMManager.getMessageManager().getHistoryMessageList(opt, resultCallBack);\n                }\n            });\n        }\n    }\n\n    /**\n     * 设置单聊已读\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void markC2CMessageAsRead(MethodCall methodCall, final Result result) {\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        V2TIMManager.getMessageManager().markC2CMessageAsRead(userID, new VoidCallBack(result));\n    }\n\n    /**\n     * 设置群聊已读\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void markGroupMessageAsRead(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        V2TIMManager.getMessageManager().markGroupMessageAsRead(groupID, new VoidCallBack(result));\n    }\n\n    /**\n     * 删除本地消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteMessageFromLocalStorage(MethodCall methodCall, final Result result) {\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                V2TIMManager.getMessageManager().deleteMessageFromLocalStorage(message, new VoidCallBack(result));\n            }\n        });\n    }\n\n    /**\n     * 删除本地及漫游消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteMessages(MethodCall methodCall, final Result result) {\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(JSON.parseArray(message, FindMessageEntity.class), new ValueCallBack<List<V2TIMMessage>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMMessage> ms) {\n                V2TIMManager.getMessageManager().deleteMessages(ms, new VoidCallBack(result));\n            }\n        });\n\n\n    }\n\n    /**\n     * 向群组消息列表中添加一条消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void insertGroupMessageToLocalStorage(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String sender = CommonUtil.getParam(methodCall, result, \"sender\");\n        String nodeStr = CommonUtil.getParam(methodCall, result, \"node\");\n        Map node = JSON.parseObject(nodeStr, Map.class);\n\n        // 获得消息对象\n        AbstractMessageNode messageNode = MessageNodeType.getMessageNodeTypeByV2TIMConstant(Integer.valueOf(node.get(\"nodeType\").toString())).getMessageNodeInterface();\n        AbstractMessageEntity messageEntity = (AbstractMessageEntity) JSON.parseObject(nodeStr, messageNode.getEntityClass());\n\n        // 添加消息\n        V2TIMManager.getMessageManager().insertGroupMessageToLocalStorage(messageNode.getV2TIMMessage(messageEntity), groupID, sender, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                result.success(null);\n            }\n        });\n    }\n\n\n    /**\n     * 向群组消息列表中添加一条消息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void insertC2CMessageToLocalStorage(MethodCall methodCall, final Result result) {\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        String sender = CommonUtil.getParam(methodCall, result, \"sender\");\n        String nodeStr = CommonUtil.getParam(methodCall, result, \"node\");\n        Map node = JSON.parseObject(nodeStr, Map.class);\n\n        // 获得消息对象\n        AbstractMessageNode messageNode = MessageNodeType.getMessageNodeTypeByV2TIMConstant(Integer.valueOf(node.get(\"nodeType\").toString())).getMessageNodeInterface();\n        AbstractMessageEntity messageEntity = (AbstractMessageEntity) JSON.parseObject(nodeStr, messageNode.getEntityClass());\n\n        // 添加消息\n        V2TIMManager.getMessageManager().insertC2CMessageToLocalStorage(messageNode.getV2TIMMessage(messageEntity), userID, sender, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                result.success(null);\n            }\n        });\n    }\n\n    /**\n     * 下载视频\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void downloadVideo(MethodCall methodCall, final Result result) {\n        final String path = CommonUtil.getParam(methodCall, result, \"path\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                message.getVideoElem().downloadVideo(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.Video));\n            }\n        });\n    }\n\n    /**\n     * 下载视频缩略图\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void downloadVideoThumbnail(MethodCall methodCall, final Result result) {\n        final String path = CommonUtil.getParam(methodCall, result, \"path\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                message.getVideoElem().downloadSnapshot(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.VideoThumbnail));\n            }\n        });\n    }\n\n    /**\n     * 下载语音\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void downloadSound(MethodCall methodCall, final Result result) {\n        final String path = CommonUtil.getParam(methodCall, result, \"path\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                message.getSoundElem().downloadSound(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.Sound));\n            }\n        });\n    }\n\n    /**\n     * 下载文件\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void downloadFile(MethodCall methodCall, final Result result) {\n        final String path = CommonUtil.getParam(methodCall, result, \"path\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                message.getFileElem().downloadFile(path, new DownloadCallBack(result, path, message.getMsgID(), DownloadCallBack.DownloadTypeEnum.File));\n            }\n        });\n    }\n\n    /**\n     * 设置消息本地Str\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setMessageLocalCustomStr(MethodCall methodCall, final Result result) {\n        final String data = CommonUtil.getParam(methodCall, result, \"data\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                message.setLocalCustomData(data);\n                result.success(null);\n            }\n        });\n    }\n\n    /**\n     * 设置消息本地Int\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setMessageLocalCustomInt(MethodCall methodCall, final Result result) {\n        final Integer data = CommonUtil.getParam(methodCall, result, \"data\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        TencentImUtils.getMessageByFindMessageEntity(message, new ValueCallBack<V2TIMMessage>(result) {\n            @Override\n            public void onSuccess(V2TIMMessage message) {\n                message.setLocalCustomInt(data);\n                result.success(null);\n            }\n        });\n    }\n\n    /**\n     * 查找消息列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void findMessages(MethodCall methodCall, final Result result) {\n        String messages = CommonUtil.getParam(methodCall, result, \"messages\");\n        TencentImUtils.getMessageByFindMessageEntity(JSON.parseArray(messages, FindMessageEntity.class), new ValueCallBack<List<V2TIMMessage>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {\n                List<CustomMessageEntity> ms = new ArrayList<>(v2TIMMessages.size());\n                for (V2TIMMessage v2TIMMessage : v2TIMMessages) {\n                    ms.add(new CustomMessageEntity(v2TIMMessage));\n                }\n                result.success(JsonUtil.toJSONString(ms));\n            }\n        });\n    }\n\n    /**\n     * 创建群\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void createGroup(MethodCall methodCall, final Result result) {\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        String memberListStr = methodCall.argument(\"memberList\");\n        V2TIMManager.getGroupManager().createGroup(JSON.parseObject(info, V2TIMGroupInfo.class), memberListStr == null ? null : JSON.parseArray(memberListStr, V2TIMCreateGroupMemberInfo.class), new ValueCallBack<String>(result));\n    }\n\n    /**\n     * 加入群\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void joinGroup(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String message = CommonUtil.getParam(methodCall, result, \"message\");\n        V2TIMManager.getInstance().joinGroup(groupID, message, new VoidCallBack(result));\n    }\n\n    /**\n     * 退出群\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void quitGroup(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        V2TIMManager.getInstance().quitGroup(groupID, new VoidCallBack(result));\n    }\n\n    /**\n     * 解散群\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void dismissGroup(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        V2TIMManager.getInstance().dismissGroup(groupID, new VoidCallBack(result));\n    }\n\n    /**\n     * 获得已加入的群列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getJoinedGroupList(MethodCall methodCall, final Result result) {\n        V2TIMManager.getGroupManager().getJoinedGroupList(new ValueCallBack<List<V2TIMGroupInfo>>(result));\n    }\n\n    /**\n     * 拉取群资料\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupsInfo(MethodCall methodCall, final Result result) {\n        String groupIDList = CommonUtil.getParam(methodCall, result, \"groupIDList\");\n        V2TIMManager.getGroupManager().getGroupsInfo(Arrays.asList(groupIDList.split(\",\")), new ValueCallBack<List<V2TIMGroupInfoResult>>(result));\n    }\n\n    /**\n     * 修改群资料\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setGroupInfo(MethodCall methodCall, final Result result) {\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        V2TIMManager.getGroupManager().setGroupInfo(JSON.parseObject(info, V2TIMGroupInfo.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 搜索群\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void searchGroups(MethodCall methodCall, final Result result) {\n        List<String> keywordList = CommonUtil.getParam(methodCall, result, \"keywordList\");\n        Boolean isSearchGroupID = CommonUtil.getParam(methodCall, result, \"isSearchGroupID\");\n        Boolean isSearchGroupName = CommonUtil.getParam(methodCall, result, \"isSearchGroupName\");\n\n        // 群搜索\n        V2TIMGroupSearchParam param = new V2TIMGroupSearchParam();\n        param.setKeywordList(keywordList);\n        param.setSearchGroupName(isSearchGroupName);\n        param.setSearchGroupID(isSearchGroupID);\n        V2TIMManager.getGroupManager().searchGroups(param, new ValueCallBack<List<V2TIMGroupInfo>>(result));\n    }\n\n    /**\n     * 搜索群成员\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void searchGroupMembers(MethodCall methodCall, final Result result) {\n        List<String> keywordList = CommonUtil.getParam(methodCall, result, \"keywordList\");\n        List<String> groupIDList = CommonUtil.getParam(methodCall, result, \"groupIDList\");\n        Boolean isSearchMemberNameCard = CommonUtil.getParam(methodCall, result, \"isSearchMemberNameCard\");\n        Boolean isSearchMemberUserID = CommonUtil.getParam(methodCall, result, \"isSearchMemberUserID\");\n        Boolean isSearchMemberRemark = CommonUtil.getParam(methodCall, result, \"isSearchMemberRemark\");\n        Boolean isSearchMemberNickName = CommonUtil.getParam(methodCall, result, \"isSearchMemberNickName\");\n\n        // 搜索群成员\n        V2TIMGroupMemberSearchParam param = new V2TIMGroupMemberSearchParam();\n        param.setKeywordList(keywordList);\n        param.setGroupIDList(groupIDList);\n        param.setSearchMemberNameCard(isSearchMemberNameCard);\n        param.setSearchMemberUserID(isSearchMemberUserID);\n        param.setSearchMemberRemark(isSearchMemberRemark);\n        param.setSearchMemberNickName(isSearchMemberNickName);\n\n        V2TIMManager.getGroupManager().searchGroupMembers(param, new ValueCallBack<HashMap<String, List<V2TIMGroupMemberFullInfo>>>(result));\n    }\n\n    /**\n     * 修改C2C消息接收选项\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setC2CReceiveMessageOpt(MethodCall methodCall, final Result result) {\n        List<String> ids = CommonUtil.getParam(methodCall, result, \"ids\");\n        int opt = CommonUtil.getParam(methodCall, result, \"opt\");\n        V2TIMManager.getMessageManager().setC2CReceiveMessageOpt(ids, opt, new VoidCallBack(result));\n    }\n\n    /**\n     * 修改群消息接收选项\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setGroupReceiveMessageOpt(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        int opt = CommonUtil.getParam(methodCall, result, \"opt\");\n        V2TIMManager.getMessageManager().setGroupReceiveMessageOpt(groupID, opt, new VoidCallBack(result));\n    }\n\n    /**\n     * 获得C2C消息接收选项\n     */\n    private void getC2CReceiveMessageOpt(MethodCall call, final Result result) {\n        V2TIMManager.getMessageManager().getC2CReceiveMessageOpt(call.<List<String>>arguments(), new ValueCallBack<List<V2TIMReceiveMessageOptInfo>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMReceiveMessageOptInfo> v2TIMReceiveMessageOptInfos) {\n                Map<String, Integer> res = new HashMap<>(v2TIMReceiveMessageOptInfos.size(), 1);\n                for (V2TIMReceiveMessageOptInfo item : v2TIMReceiveMessageOptInfos) {\n                    res.put(item.getUserID(), item.getC2CReceiveMessageOpt());\n                }\n                result.success(res);\n            }\n        });\n    }\n\n    /**\n     * 初始化群属性，会清空原有的群属性列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void initGroupAttributes(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String attributes = CommonUtil.getParam(methodCall, result, \"attributes\");\n        V2TIMManager.getGroupManager().initGroupAttributes(groupID, JSON.parseObject(attributes, HashMap.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 设置群属性。已有该群属性则更新其 value 值，没有该群属性则添加该属性。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setGroupAttributes(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String attributes = CommonUtil.getParam(methodCall, result, \"attributes\");\n        V2TIMManager.getGroupManager().setGroupAttributes(groupID, JSON.parseObject(attributes, HashMap.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 删除指定群属性，keys 传 null 则清空所有群属性。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteGroupAttributes(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String keys = methodCall.argument(\"keys\");\n        V2TIMManager.getGroupManager().deleteGroupAttributes(groupID, keys == null ? null : Arrays.asList(keys.split(\",\")), new VoidCallBack(result));\n    }\n\n    /**\n     * 获取指定群属性，keys 传 null 则获取所有群属性。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupAttributes(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String keys = methodCall.argument(\"keys\");\n        V2TIMManager.getGroupManager().getGroupAttributes(groupID, keys == null ? null : Arrays.asList(keys.split(\",\")), new ValueCallBack<Map<String, String>>(result));\n    }\n\n    /**\n     * 获取指定群在线人数\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupOnlineMemberCount(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        V2TIMManager.getGroupManager().getGroupOnlineMemberCount(groupID, new ValueCallBack<Integer>(result) {\n            @Override\n            public void onSuccess(Integer data) {\n                result.success(data);\n            }\n        });\n    }\n\n    /**\n     * 获取群成员列表。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupMemberList(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        int filter = CommonUtil.getParam(methodCall, result, \"filter\");\n        long nextSeq = Long.parseLong(CommonUtil.getParam(methodCall, result, \"nextSeq\").toString());\n        V2TIMManager.getGroupManager().getGroupMemberList(groupID, filter, nextSeq, new ValueCallBack<V2TIMGroupMemberInfoResult>(result));\n    }\n\n    /**\n     * 获取指定的群成员资料。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupMembersInfo(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String memberList = CommonUtil.getParam(methodCall, result, \"memberList\");\n        V2TIMManager.getGroupManager().getGroupMembersInfo(groupID, Arrays.asList(memberList.split(\",\")), new ValueCallBack<List<V2TIMGroupMemberFullInfo>>(result));\n    }\n\n    /**\n     * 修改指定的群成员资料。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setGroupMemberInfo(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        V2TIMManager.getGroupManager().setGroupMemberInfo(groupID, JSON.parseObject(info, V2TIMGroupMemberFullInfo.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 禁言。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void muteGroupMember(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        int seconds = CommonUtil.getParam(methodCall, result, \"seconds\");\n        V2TIMManager.getGroupManager().muteGroupMember(groupID, userID, seconds, new VoidCallBack(result));\n    }\n\n\n    /**\n     * 邀请他人入群。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void inviteUserToGroup(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String userList = CommonUtil.getParam(methodCall, result, \"userList\");\n        V2TIMManager.getGroupManager().inviteUserToGroup(groupID, Arrays.asList(userList.split(\",\")), new ValueCallBack<List<V2TIMGroupMemberOperationResult>>(result));\n    }\n\n    /**\n     * 踢人。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void kickGroupMember(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String memberList = CommonUtil.getParam(methodCall, result, \"memberList\");\n        String reason = CommonUtil.getParam(methodCall, result, \"reason\");\n        V2TIMManager.getGroupManager().kickGroupMember(groupID, Arrays.asList(memberList.split(\",\")), reason, new ValueCallBack<List<V2TIMGroupMemberOperationResult>>(result));\n    }\n\n    /**\n     * 切换群成员角色。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setGroupMemberRole(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        int role = CommonUtil.getParam(methodCall, result, \"role\");\n        V2TIMManager.getGroupManager().setGroupMemberRole(groupID, userID, role, new VoidCallBack(result));\n    }\n\n    /**\n     * 转让群主。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void transferGroupOwner(MethodCall methodCall, final Result result) {\n        String groupID = CommonUtil.getParam(methodCall, result, \"groupID\");\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        V2TIMManager.getGroupManager().transferGroupOwner(groupID, userID, new VoidCallBack(result));\n    }\n\n    /**\n     * 获得群申请列表。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getGroupApplicationList(MethodCall methodCall, final Result result) {\n        V2TIMManager.getGroupManager().getGroupApplicationList(new ValueCallBack<V2TIMGroupApplicationResult>(result));\n    }\n\n\n    /**\n     * 同意某一条加群申请。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void acceptGroupApplication(MethodCall methodCall, final Result result) {\n        String application = CommonUtil.getParam(methodCall, result, \"application\");\n        final String reason = CommonUtil.getParam(methodCall, result, \"reason\");\n        TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(application, new ValueCallBack<V2TIMGroupApplication>(result) {\n            @Override\n            public void onSuccess(V2TIMGroupApplication v2TIMGroupApplication) {\n                V2TIMManager.getGroupManager().acceptGroupApplication(v2TIMGroupApplication, reason, new VoidCallBack(result));\n            }\n        });\n    }\n\n\n    /**\n     * 拒绝某一条加群申请。\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void refuseGroupApplication(MethodCall methodCall, final Result result) {\n        final String application = CommonUtil.getParam(methodCall, result, \"application\");\n        final String reason = CommonUtil.getParam(methodCall, result, \"reason\");\n        TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(application, new ValueCallBack<V2TIMGroupApplication>(result) {\n            @Override\n            public void onSuccess(V2TIMGroupApplication v2TIMGroupApplication) {\n                V2TIMManager.getGroupManager().refuseGroupApplication(v2TIMGroupApplication, reason, new VoidCallBack(result));\n            }\n        });\n    }\n\n    /**\n     * 标记申请列表为已读\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setGroupApplicationRead(MethodCall methodCall, final Result result) {\n        V2TIMManager.getGroupManager().setGroupApplicationRead(new VoidCallBack(result));\n    }\n\n    /**\n     * 获得会话列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getConversationList(MethodCall methodCall, final Result result) {\n        Long nextSeq = Long.parseLong(CommonUtil.getParam(methodCall, result, \"nextSeq\").toString());\n        Integer count = CommonUtil.getParam(methodCall, result, \"count\");\n        V2TIMManager.getConversationManager().getConversationList(nextSeq, count, new ValueCallBack<V2TIMConversationResult>(result) {\n            @Override\n            public void onSuccess(V2TIMConversationResult v2TIMConversationResult) {\n                result.success(JsonUtil.toJSONString(new CustomConversationResultEntity(v2TIMConversationResult)));\n            }\n        });\n    }\n\n    /**\n     * 获得指定会话\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getConversation(MethodCall methodCall, final Result result) {\n        String conversationID = CommonUtil.getParam(methodCall, result, \"conversationID\");\n        V2TIMManager.getConversationManager().getConversation(conversationID, new ValueCallBack<V2TIMConversation>(result) {\n            @Override\n            public void onSuccess(V2TIMConversation v2TIMConversation) {\n                result.success(JsonUtil.toJSONString(new CustomConversationEntity(v2TIMConversation)));\n            }\n        });\n    }\n\n    /**\n     * 删除会话\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteConversation(MethodCall methodCall, final Result result) {\n        String conversationID = CommonUtil.getParam(methodCall, result, \"conversationID\");\n        V2TIMManager.getConversationManager().deleteConversation(conversationID, new VoidCallBack(result));\n    }\n\n    /**\n     * 设置会话草稿\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setConversationDraft(MethodCall methodCall, final Result result) {\n        String conversationID = CommonUtil.getParam(methodCall, result, \"conversationID\");\n        String draftText = methodCall.argument(\"draftText\");\n        V2TIMManager.getConversationManager().setConversationDraft(conversationID, draftText, new VoidCallBack(result));\n    }\n\n    /**\n     * 会话置顶\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void pinConversation(MethodCall methodCall, final Result result) {\n        String conversationID = CommonUtil.getParam(methodCall, result, \"conversationID\");\n        boolean isPinned = methodCall.argument(\"isPinned\");\n        V2TIMManager.getConversationManager().pinConversation(conversationID, isPinned, new VoidCallBack(result));\n    }\n\n    /**\n     * 获得未读会话总数\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getTotalUnreadMessageCount(MethodCall methodCall, final Result result) {\n        V2TIMManager.getConversationManager().getTotalUnreadMessageCount(new ValueCallBack<Long>(result));\n    }\n\n    /**\n     * 获得用户信息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getUsersInfo(MethodCall methodCall, final Result result) {\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getInstance().getUsersInfo(Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMUserFullInfo>>(result));\n    }\n\n    /**\n     * 修改个人资料\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setSelfInfo(MethodCall methodCall, final Result result) {\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        V2TIMManager.getInstance().setSelfInfo(JSON.parseObject(info, V2TIMUserFullInfo.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 添加到黑名单\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void addToBlackList(MethodCall methodCall, final Result result) {\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getFriendshipManager().addToBlackList(Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMFriendOperationResult>>(result));\n    }\n\n    /**\n     * 从黑名单中删除\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteFromBlackList(MethodCall methodCall, final Result result) {\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getFriendshipManager().deleteFromBlackList(Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMFriendOperationResult>>(result));\n    }\n\n    /**\n     * 获得黑名单列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getBlackList(MethodCall methodCall, final Result result) {\n        V2TIMManager.getFriendshipManager().getBlackList(new ValueCallBack<List<V2TIMFriendInfo>>(result));\n    }\n\n    /**\n     * 腾讯云 设置离线推送Token\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setOfflinePushConfig(MethodCall methodCall, final Result result) {\n        String token = CommonUtil.getParam(methodCall, result, \"token\");\n        Long bussid = Long.parseLong(CommonUtil.getParam(methodCall, result, \"bussid\").toString());\n        Boolean tpns = CommonUtil.getParam(methodCall, result, \"tpns\");\n        V2TIMManager.getOfflinePushManager().setOfflinePushConfig(new V2TIMOfflinePushConfig(bussid, token, tpns), new VoidCallBack(result));\n    }\n\n\n    /**\n     * 腾讯云 设置未读桌标\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setUnreadBadge(MethodCall methodCall, final Result result) {\n        int number = CommonUtil.getParam(methodCall, result, \"number\");\n        V2TIMManager.getOfflinePushManager().doBackground(number, new VoidCallBack(result));\n    }\n\n    /**\n     * 腾讯云 获得好友列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getFriendList(MethodCall methodCall, final Result result) {\n        V2TIMManager.getFriendshipManager().getFriendList(new ValueCallBack<List<V2TIMFriendInfo>>(result));\n    }\n\n    /**\n     * 获得指定好友信息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getFriendsInfo(MethodCall methodCall, final Result result) {\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getFriendshipManager().getFriendsInfo(Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMFriendInfoResult>>(result));\n    }\n\n    /**\n     * 设置好友资料\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setFriendInfo(MethodCall methodCall, final Result result) {\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        V2TIMManager.getFriendshipManager().setFriendInfo(JSON.parseObject(info, V2TIMFriendInfo.class), new VoidCallBack(result));\n    }\n\n    /**\n     * 添加好友\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void addFriend(MethodCall methodCall, final Result result) {\n        String info = CommonUtil.getParam(methodCall, result, \"info\");\n        V2TIMManager.getFriendshipManager().addFriend(JSON.parseObject(info, CustomFriendAddApplication.class), new ValueCallBack<V2TIMFriendOperationResult>(result));\n    }\n\n    /**\n     * 删除好友\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteFromFriendList(MethodCall methodCall, final Result result) {\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        int deleteType = CommonUtil.getParam(methodCall, result, \"deleteType\");\n        V2TIMManager.getFriendshipManager().deleteFromFriendList(Arrays.asList(userIDList.split(\",\")), deleteType, new ValueCallBack<List<V2TIMFriendOperationResult>>(result));\n    }\n\n    /**\n     * 检查好友关系\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void checkFriend(MethodCall methodCall, final Result result) {\n        String userID = CommonUtil.getParam(methodCall, result, \"userID\");\n        int checkType = CommonUtil.getParam(methodCall, result, \"checkType\");\n        V2TIMManager.getFriendshipManager().checkFriend(Collections.singletonList(userID), checkType, new ValueCallBack<List<V2TIMFriendCheckResult>>(result) {\n            @Override\n            public void onSuccess(List<V2TIMFriendCheckResult> v2TIMFriendCheckResults) {\n                result.success(v2TIMFriendCheckResults.size() == 0 ? null : JsonUtil.toJSONString(v2TIMFriendCheckResults.get(0)));\n            }\n        });\n    }\n\n    /**\n     * 获得好友申请列表\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getFriendApplicationList(MethodCall methodCall, final Result result) {\n        V2TIMManager.getFriendshipManager().getFriendApplicationList(new ValueCallBack<V2TIMFriendApplicationResult>(result));\n    }\n\n    /**\n     * 好友同意申请\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void acceptFriendApplication(MethodCall methodCall, final Result result) {\n        final String application = CommonUtil.getParam(methodCall, result, \"application\");\n        final int responseType = CommonUtil.getParam(methodCall, result, \"responseType\");\n        TencentImUtils.getFriendApplicationByFindGroupApplicationEntity(application, new ValueCallBack<V2TIMFriendApplication>(result) {\n            @Override\n            public void onSuccess(V2TIMFriendApplication v2TIMFriendApplication) {\n                V2TIMManager.getFriendshipManager().acceptFriendApplication(v2TIMFriendApplication, responseType, new ValueCallBack<V2TIMFriendOperationResult>(result));\n            }\n        });\n    }\n\n    /**\n     * 好友拒绝申请\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void refuseFriendApplication(MethodCall methodCall, final Result result) {\n        String application = CommonUtil.getParam(methodCall, result, \"application\");\n        TencentImUtils.getFriendApplicationByFindGroupApplicationEntity(application, new ValueCallBack<V2TIMFriendApplication>(result) {\n            @Override\n            public void onSuccess(V2TIMFriendApplication v2TIMFriendApplication) {\n                V2TIMManager.getFriendshipManager().refuseFriendApplication(v2TIMFriendApplication, new ValueCallBack<V2TIMFriendOperationResult>(result));\n            }\n        });\n    }\n\n    /**\n     * 删除好友申请\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteFriendApplication(MethodCall methodCall, final Result result) {\n        String application = CommonUtil.getParam(methodCall, result, \"application\");\n        TencentImUtils.getFriendApplicationByFindGroupApplicationEntity(application, new ValueCallBack<V2TIMFriendApplication>(result) {\n            @Override\n            public void onSuccess(V2TIMFriendApplication v2TIMFriendApplication) {\n                V2TIMManager.getFriendshipManager().deleteFriendApplication(v2TIMFriendApplication, new VoidCallBack(result));\n            }\n        });\n    }\n\n    /**\n     * 设置好友申请为已读\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void setFriendApplicationRead(MethodCall methodCall, final Result result) {\n        V2TIMManager.getFriendshipManager().setFriendApplicationRead(new VoidCallBack(result));\n    }\n\n    /**\n     * 新建好友分组\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void createFriendGroup(MethodCall methodCall, final Result result) {\n        String groupName = CommonUtil.getParam(methodCall, result, \"groupName\");\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getFriendshipManager().createFriendGroup(groupName, Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMFriendOperationResult>>(result));\n    }\n\n    /**\n     * 获得分组信息\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void getFriendGroups(MethodCall methodCall, final Result result) {\n        String groupNameList = methodCall.argument(\"groupNameList\");\n        V2TIMManager.getFriendshipManager().getFriendGroups(groupNameList == null ? null : Arrays.asList(groupNameList.split(\",\")), new ValueCallBack<List<V2TIMFriendGroup>>(result));\n    }\n\n    /**\n     * 删除好友分组\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteFriendGroup(MethodCall methodCall, final Result result) {\n        String groupNameList = CommonUtil.getParam(methodCall, result, \"groupNameList\");\n        V2TIMManager.getFriendshipManager().deleteFriendGroup(Arrays.asList(groupNameList.split(\",\")), new VoidCallBack(result));\n    }\n\n    /**\n     * 修改分组名称\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void renameFriendGroup(MethodCall methodCall, final Result result) {\n        String oldName = CommonUtil.getParam(methodCall, result, \"oldName\");\n        String newName = CommonUtil.getParam(methodCall, result, \"newName\");\n        V2TIMManager.getFriendshipManager().renameFriendGroup(oldName, newName, new VoidCallBack(result));\n    }\n\n    /**\n     * 添加好友到分组\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void addFriendsToFriendGroup(MethodCall methodCall, final Result result) {\n        String groupName = CommonUtil.getParam(methodCall, result, \"groupName\");\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getFriendshipManager().addFriendsToFriendGroup(groupName, Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMFriendOperationResult>>(result));\n    }\n\n    /**\n     * 从分组中删除好友\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回结果对象\n     */\n    private void deleteFriendsFromFriendGroup(MethodCall methodCall, final Result result) {\n        String groupName = CommonUtil.getParam(methodCall, result, \"groupName\");\n        String userIDList = CommonUtil.getParam(methodCall, result, \"userIDList\");\n        V2TIMManager.getFriendshipManager().deleteFriendsFromFriendGroup(groupName, Arrays.asList(userIDList.split(\",\")), new ValueCallBack<List<V2TIMFriendOperationResult>>(result));\n    }\n\n    /**\n     * 搜索本地消息\n     */\n    private void searchLocalMessages(MethodCall call, final Result result) {\n        V2TIMMessageSearchParam param = new V2TIMMessageSearchParam();\n        param.setConversationID(call.<String>argument(\"conversationId\"));\n        param.setKeywordList(call.<List<String>>argument(\"keyword\"));\n        param.setKeywordListMatchType(call.<Integer>argument(\"keywordMatchType\"));\n        param.setSenderUserIDList(call.<List<String>>argument(\"senderUserIds\"));\n        param.setMessageTypeList(call.<List<Integer>>argument(\"messageTypes\"));\n        param.setSearchTimePosition(call.<Long>argument(\"searchTimePosition\"));\n        param.setSearchTimePeriod(call.<Long>argument(\"searchTimePeriod\"));\n        param.setPageSize(call.<Integer>argument(\"pageSize\"));\n        param.setPageIndex(call.<Integer>argument(\"pageIndex\"));\n        V2TIMManager.getMessageManager().searchLocalMessages(param, new ValueCallBack<V2TIMMessageSearchResult>(result) {\n            @Override\n            public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {\n\n            }\n        });\n    }\n\n    /**\n     * 调用监听器\n     *\n     * @param type   类型\n     * @param params 参数\n     */\n    public static void invokeListener(ListenerTypeEnum type, Object params) {\n        final Map<String, Object> resultParams = new HashMap<>(2, 1);\n        resultParams.put(\"type\", type);\n        resultParams.put(\"params\", params);\n        CommonUtil.runMainThreadMethod(new Runnable() {\n            @Override\n            public void run() {\n                channel.invokeMethod(\"onListener\", JsonUtil.toJSONString(resultParams));\n            }\n        });\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/ValueCallBack.java",
    "content": "package top.huic.tencent_im_plugin;\n\nimport com.tencent.imsdk.v2.V2TIMValueCallback;\n\nimport io.flutter.plugin.common.MethodChannel.Result;\nimport top.huic.tencent_im_plugin.util.JsonUtil;\n\n/**\n * 值改变回调\n *\n * @author 蒋具宏\n */\npublic class ValueCallBack<T> implements V2TIMValueCallback<T> {\n    /**\n     * 回调\n     */\n    private Result result;\n\n    public ValueCallBack(Result result) {\n        this.result = result;\n    }\n\n    /**\n     * 成功事件\n     *\n     * @param t 结果\n     */\n    @Override\n    public void onSuccess(T t) {\n        if (result != null) {\n            if(t instanceof Number || t instanceof String || t instanceof Boolean){\n                result.success(t);\n            }else{\n                result.success(JsonUtil.toJSONString(t));\n            }\n        }\n    }\n\n\n    /**\n     * 失败事件\n     *\n     * @param code 错误码\n     * @param desc 错误描述\n     */\n    @Override\n    public void onError(int code, String desc) {\n        if (this.result != null) {\n            result.error(String.valueOf(code), desc, desc);\n        }\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/VoidCallBack.java",
    "content": "package top.huic.tencent_im_plugin;\n\nimport com.tencent.imsdk.v2.V2TIMCallback;\n\nimport io.flutter.plugin.common.MethodChannel;\n\n/**\n * 操作结果回调\n *\n * @author 蒋具宏\n */\npublic class VoidCallBack implements V2TIMCallback {\n    /**\n     * 回调\n     */\n    private MethodChannel.Result result;\n\n    public VoidCallBack(MethodChannel.Result result) {\n        this.result = result;\n    }\n\n    @Override\n    public void onError(int code, String desc) {\n        if (result != null) {\n            result.error(String.valueOf(code), \"Execution Error\", desc);\n        }\n    }\n\n    @Override\n    public void onSuccess() {\n        if (result != null) {\n            result.success(null);\n        }\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/CustomConversationEntity.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\nimport com.tencent.imsdk.v2.V2TIMConversation;\nimport com.tencent.imsdk.v2.V2TIMGroupAtInfo;\n\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.util.BeanUtils;\n\n/**\n * 自定义会话实体\n */\npublic class CustomConversationEntity {\n\n    /**\n     * 会话ID\n     */\n    String conversationID;\n\n    /**\n     * 会话类型\n     */\n    int type;\n\n    /**\n     * 用户ID\n     */\n    String userID;\n\n    /**\n     * 群ID\n     */\n    String groupID;\n\n    /**\n     * 显示名称\n     */\n    String showName;\n\n    /**\n     * 头像\n     */\n    String faceUrl;\n\n    /**\n     * 接收消息选项（群会话有效）\n     */\n    int recvOpt;\n\n    /**\n     * 群类型\n     */\n    String groupType;\n\n    /**\n     * 未读数量\n     */\n    int unreadCount;\n\n    /**\n     * 最后一条消息\n     */\n    CustomMessageEntity lastMessage;\n\n    /**\n     * 草稿文本\n     */\n    String draftText;\n\n    /**\n     * 草稿时间\n     */\n    Long draftTimestamp;\n\n    /**\n     * 是否置顶\n     */\n    boolean pinned;\n\n    /**\n     * \\@信息列表\n     */\n    List<V2TIMGroupAtInfo> groupAtInfoList;\n\n    public CustomConversationEntity() {\n    }\n\n    public CustomConversationEntity(V2TIMConversation data) {\n        BeanUtils.copyProperties(data, this, \"lastMessage\");\n        if (data.getLastMessage() != null) {\n            this.lastMessage = new CustomMessageEntity(data.getLastMessage());\n        }\n    }\n\n    public String getConversationID() {\n        return conversationID;\n    }\n\n    public void setConversationID(String conversationID) {\n        this.conversationID = conversationID;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public String getUserID() {\n        return userID;\n    }\n\n    public void setUserID(String userID) {\n        this.userID = userID;\n    }\n\n    public String getGroupID() {\n        return groupID;\n    }\n\n    public void setGroupID(String groupID) {\n        this.groupID = groupID;\n    }\n\n    public String getShowName() {\n        return showName;\n    }\n\n    public void setShowName(String showName) {\n        this.showName = showName;\n    }\n\n    public String getFaceUrl() {\n        return faceUrl;\n    }\n\n    public void setFaceUrl(String faceUrl) {\n        this.faceUrl = faceUrl;\n    }\n\n    public int getRecvOpt() {\n        return recvOpt;\n    }\n\n    public void setRecvOpt(int recvOpt) {\n        this.recvOpt = recvOpt;\n    }\n\n    public String getGroupType() {\n        return groupType;\n    }\n\n    public void setGroupType(String groupType) {\n        this.groupType = groupType;\n    }\n\n    public int getUnreadCount() {\n        return unreadCount;\n    }\n\n    public void setUnreadCount(int unreadCount) {\n        this.unreadCount = unreadCount;\n    }\n\n    public CustomMessageEntity getLastMessage() {\n        return lastMessage;\n    }\n\n    public void setLastMessage(CustomMessageEntity lastMessage) {\n        this.lastMessage = lastMessage;\n    }\n\n    public String getDraftText() {\n        return draftText;\n    }\n\n    public void setDraftText(String draftText) {\n        this.draftText = draftText;\n    }\n\n    public Long getDraftTimestamp() {\n        return draftTimestamp;\n    }\n\n    public void setDraftTimestamp(Long draftTimestamp) {\n        this.draftTimestamp = draftTimestamp;\n    }\n\n    public List<V2TIMGroupAtInfo> getGroupAtInfoList() {\n        return groupAtInfoList;\n    }\n\n    public void setGroupAtInfoList(List<V2TIMGroupAtInfo> groupAtInfoList) {\n        this.groupAtInfoList = groupAtInfoList;\n    }\n\n    public boolean isPinned() {\n        return pinned;\n    }\n\n    public void setPinned(boolean pinned) {\n        this.pinned = pinned;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/CustomConversationResultEntity.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\nimport com.tencent.imsdk.v2.V2TIMConversation;\nimport com.tencent.imsdk.v2.V2TIMConversationResult;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.util.BeanUtils;\n\n/**\n * 自定义会话结果实体\n */\npublic class CustomConversationResultEntity {\n\n    /**\n     * 下一次分页拉取的游标\n     */\n    private Long nextSeq;\n\n    /**\n     * 会话列表是否已经拉取完毕\n     */\n    private Boolean finished;\n\n    /**\n     * 会话列表\n     */\n    private List<CustomConversationEntity> conversationList;\n\n    public CustomConversationResultEntity() {\n    }\n\n    public CustomConversationResultEntity(V2TIMConversationResult data) {\n        BeanUtils.copyProperties(data, this, \"conversationList\");\n\n        if (data.getConversationList() != null) {\n            List<CustomConversationEntity> conversationList = new ArrayList<>(data.getConversationList().size());\n            for (V2TIMConversation item : data.getConversationList()) {\n                conversationList.add(new CustomConversationEntity(item));\n            }\n            this.conversationList = conversationList;\n        }\n    }\n\n    public Long getNextSeq() {\n        return nextSeq;\n    }\n\n    public void setNextSeq(Long nextSeq) {\n        this.nextSeq = nextSeq;\n    }\n\n    public Boolean getFinished() {\n        return finished;\n    }\n\n    public void setFinished(Boolean finished) {\n        this.finished = finished;\n    }\n\n    public List<CustomConversationEntity> getConversationList() {\n        return conversationList;\n    }\n\n    public void setConversationList(List<CustomConversationEntity> conversationList) {\n        this.conversationList = conversationList;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/CustomFriendAddApplication.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\nimport com.tencent.imsdk.v2.V2TIMFriendAddApplication;\n\n/**\n * 自定义好友添加申请实体\n */\npublic class CustomFriendAddApplication extends V2TIMFriendAddApplication {\n    public CustomFriendAddApplication() {\n        super(null);\n    }\n\n    public CustomFriendAddApplication(String userID) {\n        super(userID);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/CustomMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\nimport com.tencent.imsdk.v2.V2TIMElem;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMOfflinePushInfo;\n\nimport java.io.Serializable;\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\nimport top.huic.tencent_im_plugin.message.AbstractMessageNode;\nimport top.huic.tencent_im_plugin.message.entity.AbstractMessageEntity;\nimport top.huic.tencent_im_plugin.util.BeanUtils;\n\n/**\n * 自定义消息实体\n *\n * @author 蒋具宏\n */\npublic class CustomMessageEntity implements Serializable {\n\n    /**\n     * 消息 ID\n     */\n    private String msgID;\n\n    /**\n     * 消息时间戳\n     */\n    private Long timestamp;\n\n    /**\n     * 消息发送者 userID\n     */\n    private String sender;\n\n    /**\n     * 消息发送者昵称\n     */\n    private String nickName;\n\n    /**\n     * 好友备注。如果没有拉取过好友信息或者不是好友，返回 null\n     */\n    private String friendRemark;\n\n    /**\n     * 发送者头像 url\n     */\n    private String faceUrl;\n\n    /**\n     * 群组消息，nameCard 为发送者的群名片\n     */\n    private String nameCard;\n\n    /**\n     * 群组消息，groupID 为接收消息的群组 ID，否则为 null\n     */\n    private String groupID;\n\n    /**\n     * 单聊消息，userID 为会话用户 ID，否则为 null。 假设自己和 userA 聊天，无论是自己发给 userA 的消息还是 userA 发给自己的消息，这里的 userID 均为 userA\n     */\n    private String userID;\n\n    /**\n     * 消息发送状态\n     */\n    private Integer status;\n\n    /**\n     * 消息类型\n     */\n    private Integer elemType;\n\n    /**\n     * 消息自定义数据（本地保存，不会发送到对端，程序卸载重装后失效）\n     */\n    private String localCustomData;\n\n    /**\n     * 消息自定义数据（本地保存，不会发送到对端，程序卸载重装后失效）\n     */\n    private Integer localCustomInt;\n\n    /**\n     * 消息发送者是否是自己\n     */\n    private Boolean self;\n\n    /**\n     * 消息自己是否已读\n     */\n    private Boolean read;\n\n    /**\n     * 消息对方是否已读（只有 C2C 消息有效）\n     */\n    private Boolean peerRead;\n\n    /**\n     * 消息优先级\n     */\n    private Integer priority;\n\n    /**\n     * 消息的离线推送信息\n     */\n    private V2TIMOfflinePushInfo offlinePushInfo;\n\n    /**\n     * 群@用户列表\n     */\n    private List<String> groupAtUserList;\n\n    /**\n     * 消息的序列号\n     * 群聊中的消息序列号云端生成，在群里是严格递增且唯一的。 单聊中的序列号是本地生成，不能保证严格递增且唯一。\n     */\n    private Long seq;\n\n    /**\n     * 描述信息\n     */\n    private String note;\n\n    /**\n     * 节点信息\n     */\n    private AbstractMessageEntity node;\n\n    /**\n     * 消息随机码\n     */\n    private long random;\n\n    public CustomMessageEntity() {\n    }\n\n    public CustomMessageEntity(V2TIMMessage message) {\n        BeanUtils.copyProperties(message, this);\n\n        // 解析接口\n        MessageNodeType nodeType = MessageNodeType.getMessageNodeTypeByV2TIMConstant(this.elemType);\n        if (nodeType != MessageNodeType.None) {\n            AbstractMessageNode _node = nodeType.getMessageNodeInterface();\n            V2TIMElem elem = nodeType.getElemByMessage(message);\n            this.note = _node.getNote(elem);\n            this.node = _node.analysis(elem);\n        }\n    }\n\n    public String getMsgID() {\n        return msgID;\n    }\n\n    public void setMsgID(String msgID) {\n        this.msgID = msgID;\n    }\n\n    public Long getTimestamp() {\n        return timestamp;\n    }\n\n    public void setTimestamp(Long timestamp) {\n        this.timestamp = timestamp;\n    }\n\n    public String getSender() {\n        return sender;\n    }\n\n    public void setSender(String sender) {\n        this.sender = sender;\n    }\n\n    public String getNickName() {\n        return nickName;\n    }\n\n    public void setNickName(String nickName) {\n        this.nickName = nickName;\n    }\n\n    public String getFriendRemark() {\n        return friendRemark;\n    }\n\n    public void setFriendRemark(String friendRemark) {\n        this.friendRemark = friendRemark;\n    }\n\n    public String getFaceUrl() {\n        return faceUrl;\n    }\n\n    public void setFaceUrl(String faceUrl) {\n        this.faceUrl = faceUrl;\n    }\n\n    public String getNameCard() {\n        return nameCard;\n    }\n\n    public void setNameCard(String nameCard) {\n        this.nameCard = nameCard;\n    }\n\n    public String getGroupID() {\n        return groupID;\n    }\n\n    public void setGroupID(String groupID) {\n        this.groupID = groupID;\n    }\n\n    public String getUserID() {\n        return userID;\n    }\n\n    public void setUserID(String userID) {\n        this.userID = userID;\n    }\n\n    public Integer getStatus() {\n        return status;\n    }\n\n    public void setStatus(Integer status) {\n        this.status = status;\n    }\n\n    public Integer getElemType() {\n        return elemType;\n    }\n\n    public void setElemType(Integer elemType) {\n        this.elemType = elemType;\n    }\n\n    public String getLocalCustomData() {\n        return localCustomData;\n    }\n\n    public void setLocalCustomData(String localCustomData) {\n        this.localCustomData = localCustomData;\n    }\n\n    public Integer getLocalCustomInt() {\n        return localCustomInt;\n    }\n\n    public void setLocalCustomInt(Integer localCustomInt) {\n        this.localCustomInt = localCustomInt;\n    }\n\n    public Boolean getSelf() {\n        return self;\n    }\n\n    public void setSelf(Boolean self) {\n        this.self = self;\n    }\n\n    public Boolean getRead() {\n        return read;\n    }\n\n    public void setRead(Boolean read) {\n        this.read = read;\n    }\n\n    public Boolean getPeerRead() {\n        return peerRead;\n    }\n\n    public void setPeerRead(Boolean peerRead) {\n        this.peerRead = peerRead;\n    }\n\n    public Integer getPriority() {\n        return priority;\n    }\n\n    public void setPriority(Integer priority) {\n        this.priority = priority;\n    }\n\n    public V2TIMOfflinePushInfo getOfflinePushInfo() {\n        return offlinePushInfo;\n    }\n\n    public void setOfflinePushInfo(V2TIMOfflinePushInfo offlinePushInfo) {\n        this.offlinePushInfo = offlinePushInfo;\n    }\n\n    public List<String> getGroupAtUserList() {\n        return groupAtUserList;\n    }\n\n    public void setGroupAtUserList(List<String> groupAtUserList) {\n        this.groupAtUserList = groupAtUserList;\n    }\n\n    public Long getSeq() {\n        return seq;\n    }\n\n    public void setSeq(Long seq) {\n        this.seq = seq;\n    }\n\n    public String getNote() {\n        return note;\n    }\n\n    public void setNote(String note) {\n        this.note = note;\n    }\n\n    public AbstractMessageEntity getNode() {\n        return node;\n    }\n\n    public void setNode(AbstractMessageEntity node) {\n        this.node = node;\n    }\n\n    public long getRandom() {\n        return random;\n    }\n\n    public void setRandom(long random) {\n        this.random = random;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/FindFriendApplicationEntity.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\n/**\n * 查找好友申请实体\n */\npublic class FindFriendApplicationEntity {\n    /**\n     * 用户ID\n     */\n    String userID;\n\n    /**\n     * 类型\n     */\n    int type;\n\n    public String getUserID() {\n        return userID;\n    }\n\n    public void setUserID(String userID) {\n        this.userID = userID;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/FindGroupApplicationEntity.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\n/**\n * 查找群申请实体\n */\npublic class FindGroupApplicationEntity {\n    /**\n     * 来自用户\n     */\n    String fromUser;\n\n    /**\n     * 群ID\n     */\n    String groupID;\n\n    public String getFromUser() {\n        return fromUser;\n    }\n\n    public void setFromUser(String fromUser) {\n        this.fromUser = fromUser;\n    }\n\n    public String getGroupID() {\n        return groupID;\n    }\n\n    public void setGroupID(String groupID) {\n        this.groupID = groupID;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/entity/FindMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.entity;\n\n/**\n * 查找消息实体\n */\npublic class FindMessageEntity {\n    /**\n     * 消息ID\n     */\n    private String msgId;\n\n    public FindMessageEntity() {\n    }\n\n    public FindMessageEntity(String msgId) {\n        this.msgId = msgId;\n    }\n\n    public String getMsgId() {\n        return msgId;\n    }\n\n    public void setMsgId(String msgId) {\n        this.msgId = msgId;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/enums/ListenerTypeEnum.java",
    "content": "package top.huic.tencent_im_plugin.enums;\n\n/**\n * 监听器类型枚举\n */\npublic enum ListenerTypeEnum {\n\n    /**\n     * 新消息通知\n     */\n    NewMessage,\n\n    /**\n     * C2C已读回执\n     */\n    C2CReadReceipt,\n\n    /**\n     * 消息撤回\n     */\n    MessageRevoked,\n\n    /**\n     * 同步服务开始\n     */\n    SyncServerStart,\n\n    /**\n     * 同步服务完成\n     */\n    SyncServerFinish,\n\n    /**\n     * 同步服务失败\n     */\n    SyncServerFailed,\n\n    /**\n     * 新会话\n     */\n    NewConversation,\n\n    /**\n     * 会话刷新\n     */\n    ConversationChanged,\n\n    /**\n     * 好友申请新增通知\n     */\n    FriendApplicationListAdded,\n\n    /**\n     * 好友申请删除通知\n     */\n    FriendApplicationListDeleted,\n\n    /**\n     * 好友申请已读通知\n     */\n    FriendApplicationListRead,\n\n    /**\n     * 好友新增通知\n     */\n    FriendListAdded,\n\n    /**\n     * 好友删除通知\n     */\n    FriendListDeleted,\n\n    /**\n     * 黑名单新增通知\n     */\n    BlackListAdd,\n\n    /**\n     * 黑名单删除通知\n     */\n    BlackListDeleted,\n\n    /**\n     * 好友资料更新通知\n     */\n    FriendInfoChanged,\n\n    /**\n     * 有用户加入群\n     */\n    MemberEnter,\n\n    /**\n     * 有用户离开群\n     */\n    MemberLeave,\n\n    /**\n     * 有用户被拉入群\n     */\n    MemberInvited,\n\n    /**\n     * 有用户被踢出群\n     */\n    MemberKicked,\n\n    /**\n     * 群成员信息被修改\n     */\n    MemberInfoChanged,\n\n    /**\n     * 创建群\n     */\n    GroupCreated,\n\n    /**\n     * 群被解散\n     */\n    GroupDismissed,\n\n    /**\n     * 群被回收\n     */\n    GroupRecycled,\n\n    /**\n     * 群信息被修改\n     */\n    GroupInfoChanged,\n\n    /**\n     * 有新的加群申请\n     */\n    ReceiveJoinApplication,\n\n    /**\n     * 加群信息已被管理员处理\n     */\n    ApplicationProcessed,\n\n    /**\n     * 指定管理员身份\n     */\n    GrantAdministrator,\n\n    /**\n     * 取消管理员身份\n     */\n    RevokeAdministrator,\n\n    /**\n     * 主动退出群组\n     */\n    QuitFromGroup,\n\n    /**\n     * 收到 RESTAPI 下发的自定义系统消息\n     */\n    ReceiveRESTCustomData,\n\n    /**\n     * 收到群属性更新的回调\n     */\n    GroupAttributeChanged,\n\n    /**\n     * 正在连接到腾讯云服务器\n     */\n    Connecting,\n\n    /**\n     * 网络连接成功\n     */\n    ConnectSuccess,\n\n    /**\n     * 网络连接失败\n     */\n    ConnectFailed,\n\n    /**\n     * 踢下线\n     */\n    KickedOffline,\n\n    /**\n     * 当前用户的资料发生了更新\n     */\n    SelfInfoUpdated,\n\n    /**\n     * 用户登录的 userSig 过期（用户需要重新获取 userSig 后登录）\n     */\n    UserSigExpired,\n\n    /**\n     * 收到信令邀请\n     */\n    ReceiveNewInvitation,\n\n    /**\n     * 信令被邀请者接受邀请\n     */\n    InviteeAccepted,\n\n    /**\n     * 信令被邀请者拒绝邀请\n     */\n    InviteeRejected,\n\n    /**\n     * 信令邀请被取消\n     */\n    InvitationCancelled,\n\n    /**\n     * 信令邀请超时\n     */\n    InvitationTimeout,\n\n    /**\n     * 下载进度\n     */\n    DownloadProgress,\n\n    /**\n     * 消息发送成功\n     */\n    MessageSendSucc,\n\n    /**\n     * 消息发送失败\n     */\n    MessageSendFail,\n\n    /**\n     * 消息发送进度更新\n     */\n    MessageSendProgress,\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/enums/MessageNodeType.java",
    "content": "package top.huic.tencent_im_plugin.enums;\n\nimport com.tencent.imsdk.v2.V2TIMElem;\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.AbstractMessageNode;\nimport top.huic.tencent_im_plugin.message.CustomMessageNode;\nimport top.huic.tencent_im_plugin.message.FaceMessageNode;\nimport top.huic.tencent_im_plugin.message.FileMessageNode;\nimport top.huic.tencent_im_plugin.message.GroupTipsMessageNode;\nimport top.huic.tencent_im_plugin.message.ImageMessageNode;\nimport top.huic.tencent_im_plugin.message.LocationMessageNode;\nimport top.huic.tencent_im_plugin.message.SoundMessageNode;\nimport top.huic.tencent_im_plugin.message.TextMessageNode;\nimport top.huic.tencent_im_plugin.message.VideoMessageNode;\n\n/**\n * 消息节点类型\n *\n * @author 蒋具宏\n */\npublic enum MessageNodeType {\n    /**\n     * 没有元素\n     */\n    None(null) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return null;\n        }\n    },\n\n    /**\n     * 文本\n     */\n    Text(new TextMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getTextElem();\n        }\n    },\n\n    /**\n     * 自定义\n     */\n    Custom(new CustomMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getCustomElem();\n        }\n    },\n\n    /**\n     * 图片\n     */\n    Image(new ImageMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getImageElem();\n        }\n    },\n\n    /**\n     * 语音\n     */\n    Sound(new SoundMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getSoundElem();\n        }\n    },\n\n    /**\n     * 视频\n     */\n    Video(new VideoMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getVideoElem();\n        }\n    },\n\n    /**\n     * 文件\n     */\n    File(new FileMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getFileElem();\n        }\n    },\n\n    /**\n     * 位置\n     */\n    Location(new LocationMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getLocationElem();\n        }\n    },\n\n    /**\n     * 表情\n     */\n    Face(new FaceMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getFaceElem();\n        }\n    },\n\n    /**\n     * 群提示\n     */\n    GroupTips(new GroupTipsMessageNode()) {\n        @Override\n        public V2TIMElem getElemByMessage(V2TIMMessage message) {\n            return message.getGroupTipsElem();\n        }\n    };\n\n    /**\n     * 消息节点接口\n     * 通过枚举的方法反向绑定接口，和业务强关联\n     */\n    private AbstractMessageNode messageNodeInterface;\n\n    MessageNodeType(AbstractMessageNode messageNodeInterface) {\n        this.messageNodeInterface = messageNodeInterface;\n    }\n\n    /**\n     * 获得消息节点接口\n     */\n    public AbstractMessageNode getMessageNodeInterface() {\n        return messageNodeInterface;\n    }\n\n    /**\n     * 根据Message获得节点信息\n     *\n     * @param message 消息对象\n     * @return 节点对象\n     */\n    public abstract V2TIMElem getElemByMessage(V2TIMMessage message);\n\n    /**\n     * 根据TIM V2版本的常量进行获取\n     *\n     * @param constant 常量值\n     * @return 结果\n     */\n    public static MessageNodeType getMessageNodeTypeByV2TIMConstant(int constant) {\n        return MessageNodeType.values()[constant];\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/listener/CustomAdvancedMsgListener.java",
    "content": "package top.huic.tencent_im_plugin.listener;\n\nimport com.tencent.imsdk.v2.V2TIMAdvancedMsgListener;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMMessageReceipt;\n\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.TencentImPlugin;\nimport top.huic.tencent_im_plugin.entity.CustomMessageEntity;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * 消息相关监听器\n */\npublic class CustomAdvancedMsgListener extends V2TIMAdvancedMsgListener {\n    /**\n     * 新消息通知\n     */\n    @Override\n    public void onRecvNewMessage(V2TIMMessage msg) {\n        super.onRecvNewMessage(msg);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.NewMessage, new CustomMessageEntity(msg));\n    }\n\n    /**\n     * C2C已读回执\n     */\n    @Override\n    public void onRecvC2CReadReceipt(List<V2TIMMessageReceipt> receiptList) {\n        super.onRecvC2CReadReceipt(receiptList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.C2CReadReceipt, receiptList);\n    }\n\n    /**\n     * 消息撤回\n     */\n    @Override\n    public void onRecvMessageRevoked(String msgID) {\n        super.onRecvMessageRevoked(msgID);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.MessageRevoked, msgID);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/listener/CustomConversationListener.java",
    "content": "package top.huic.tencent_im_plugin.listener;\n\nimport com.tencent.imsdk.v2.V2TIMConversation;\nimport com.tencent.imsdk.v2.V2TIMConversationListener;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.TencentImPlugin;\nimport top.huic.tencent_im_plugin.entity.CustomConversationEntity;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * 自定义会话监听\n */\npublic class CustomConversationListener extends V2TIMConversationListener {\n    /**\n     * 同步服务开始\n     */\n    @Override\n    public void onSyncServerStart() {\n        super.onSyncServerStart();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.SyncServerStart, null);\n    }\n\n    /**\n     * 同步服务完成\n     */\n    @Override\n    public void onSyncServerFinish() {\n        super.onSyncServerFinish();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.SyncServerFinish, null);\n    }\n\n    /**\n     * 同步服务失败\n     */\n    @Override\n    public void onSyncServerFailed() {\n        super.onSyncServerFailed();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.SyncServerFailed, null);\n    }\n\n    /**\n     * 新会话\n     */\n    @Override\n    public void onNewConversation(List<V2TIMConversation> conversationList) {\n        super.onNewConversation(conversationList);\n        List<CustomConversationEntity> data = new ArrayList<>(conversationList.size());\n        for (V2TIMConversation v2TIMConversation : conversationList) {\n            data.add(new CustomConversationEntity(v2TIMConversation));\n        }\n        TencentImPlugin.invokeListener(ListenerTypeEnum.NewConversation, data);\n    }\n\n    /**\n     * 会话刷新\n     */\n    @Override\n    public void onConversationChanged(List<V2TIMConversation> conversationList) {\n        super.onConversationChanged(conversationList);\n        List<CustomConversationEntity> data = new ArrayList<>(conversationList.size());\n        for (V2TIMConversation v2TIMConversation : conversationList) {\n            data.add(new CustomConversationEntity(v2TIMConversation));\n        }\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ConversationChanged, data);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/listener/CustomFriendshipListener.java",
    "content": "package top.huic.tencent_im_plugin.listener;\n\nimport com.tencent.imsdk.v2.V2TIMFriendApplication;\nimport com.tencent.imsdk.v2.V2TIMFriendInfo;\nimport com.tencent.imsdk.v2.V2TIMFriendshipListener;\n\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.TencentImPlugin;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * 自定义关系链监听器\n */\npublic class CustomFriendshipListener extends V2TIMFriendshipListener {\n    /**\n     * 好友申请新增通知，两种情况会收到这个回调：\n     * <p>\n     * 自己申请加别人好友\n     * 别人申请加自己好友\n     */\n    @Override\n    public void onFriendApplicationListAdded(List<V2TIMFriendApplication> applicationList) {\n        super.onFriendApplicationListAdded(applicationList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.FriendApplicationListAdded, applicationList);\n    }\n\n    /**\n     * 好友申请删除通知，四种情况会收到这个回调\n     * <p>\n     * 调用 deleteFriendApplication 主动删除好友申请\n     * 调用 refuseFriendApplication 拒绝好友申请\n     * 调用 acceptFriendApplication 同意好友申请且同意类型为 V2TIM_FRIEND_ACCEPT_AGREE 时\n     * 申请加别人好友被拒绝\n     */\n    @Override\n    public void onFriendApplicationListDeleted(List<String> userIDList) {\n        super.onFriendApplicationListDeleted(userIDList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.FriendApplicationListDeleted, userIDList);\n    }\n\n    /**\n     * 好友申请已读通知，如果调用 setFriendApplicationRead 设置好友申请列表已读，会收到这个回调（主要用于多端同步）\n     */\n    @Override\n    public void onFriendApplicationListRead() {\n        super.onFriendApplicationListRead();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.FriendApplicationListRead, null);\n    }\n\n    /**\n     * 好友新增通知\n     */\n    @Override\n    public void onFriendListAdded(List<V2TIMFriendInfo> users) {\n        super.onFriendListAdded(users);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.FriendListAdded, users);\n    }\n\n    /**\n     * 好友删除通知，，两种情况会收到这个回调：\n     * <p>\n     * 自己删除好友（单向和双向删除都会收到回调）\n     * 好友把自己删除（双向删除会收到）\n     */\n    @Override\n    public void onFriendListDeleted(List<String> userList) {\n        super.onFriendListDeleted(userList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.FriendListDeleted, userList);\n    }\n\n    /**\n     * 黑名单新增通知\n     */\n    @Override\n    public void onBlackListAdd(List<V2TIMFriendInfo> infoList) {\n        super.onBlackListAdd(infoList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.BlackListAdd, infoList);\n    }\n\n    /**\n     * 黑名单删除通知\n     */\n    @Override\n    public void onBlackListDeleted(List<String> userList) {\n        super.onBlackListDeleted(userList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.BlackListDeleted, userList);\n    }\n\n    /**\n     * 好友资料更新通知\n     */\n    @Override\n    public void onFriendInfoChanged(List<V2TIMFriendInfo> infoList) {\n        super.onFriendInfoChanged(infoList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.FriendInfoChanged, infoList);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/listener/CustomGroupListener.java",
    "content": "package top.huic.tencent_im_plugin.listener;\n\nimport com.tencent.imsdk.v2.V2TIMGroupChangeInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupListener;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberChangeInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberInfo;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport top.huic.tencent_im_plugin.TencentImPlugin;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * 自定义群监听\n */\npublic class CustomGroupListener extends V2TIMGroupListener {\n    /**\n     * 有用户加入群（全员能够收到）\n     */\n    @Override\n    public void onMemberEnter(final String groupID, final List<V2TIMGroupMemberInfo> memberList) {\n        super.onMemberEnter(groupID, memberList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.MemberEnter, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"memberList\", memberList);\n            }\n        });\n    }\n\n    /**\n     * 有用户离开群（全员能够收到）\n     */\n    @Override\n    public void onMemberLeave(final String groupID, final V2TIMGroupMemberInfo member) {\n        super.onMemberLeave(groupID, member);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.MemberLeave, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"member\", member);\n            }\n        });\n    }\n\n    /**\n     * 某些人被拉入某群（全员能够收到）\n     */\n    @Override\n    public void onMemberInvited(final String groupID, final V2TIMGroupMemberInfo opUser, final List<V2TIMGroupMemberInfo> memberList) {\n        super.onMemberInvited(groupID, opUser, memberList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.MemberInvited, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n                put(\"memberList\", memberList);\n            }\n        });\n    }\n\n    /**\n     * 某些人被踢出某群（全员能够收到）\n     */\n    @Override\n    public void onMemberKicked(final String groupID, final V2TIMGroupMemberInfo opUser, final List<V2TIMGroupMemberInfo> memberList) {\n        super.onMemberKicked(groupID, opUser, memberList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.MemberKicked, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n                put(\"memberList\", memberList);\n            }\n        });\n    }\n\n    /**\n     * 群成员信息被修改（全员能收到）\n     */\n    @Override\n    public void onMemberInfoChanged(final String groupID, final List<V2TIMGroupMemberChangeInfo> v2TIMGroupMemberChangeInfoList) {\n        super.onMemberInfoChanged(groupID, v2TIMGroupMemberChangeInfoList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.MemberInfoChanged, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"changInfo\", v2TIMGroupMemberChangeInfoList);\n            }\n        });\n    }\n\n    /**\n     * 创建群（主要用于多端同步）\n     */\n    @Override\n    public void onGroupCreated(String groupID) {\n        super.onGroupCreated(groupID);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.GroupCreated, groupID);\n    }\n\n    /**\n     * 群被解散了（全员能收到）\n     */\n    @Override\n    public void onGroupDismissed(final String groupID, final V2TIMGroupMemberInfo opUser) {\n        super.onGroupDismissed(groupID, opUser);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.GroupDismissed, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n            }\n        });\n    }\n\n    /**\n     * 群被回收（全员能收到）\n     */\n    @Override\n    public void onGroupRecycled(final String groupID, final V2TIMGroupMemberInfo opUser) {\n        super.onGroupRecycled(groupID, opUser);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.GroupRecycled, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n            }\n        });\n    }\n\n    /**\n     * 群信息被修改（全员能收到）\n     */\n    @Override\n    public void onGroupInfoChanged(final String groupID, final List<V2TIMGroupChangeInfo> changeInfos) {\n        super.onGroupInfoChanged(groupID, changeInfos);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.GroupInfoChanged, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"changInfo\", changeInfos);\n            }\n        });\n    }\n\n    /**\n     * 有新的加群请求（只有群主或管理员会收到）\n     */\n    @Override\n    public void onReceiveJoinApplication(final String groupID, final V2TIMGroupMemberInfo member, final String opReason) {\n        super.onReceiveJoinApplication(groupID, member, opReason);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ReceiveJoinApplication, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"member\", member);\n                put(\"opReason\", opReason);\n            }\n        });\n    }\n\n    /**\n     * 加群请求已经被群主或管理员处理了（只有申请人能够收到）\n     */\n    @Override\n    public void onApplicationProcessed(final String groupID, final V2TIMGroupMemberInfo opUser, final boolean isAgreeJoin, final String opReason) {\n        super.onApplicationProcessed(groupID, opUser, isAgreeJoin, opReason);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ApplicationProcessed, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n                put(\"isAgreeJoin\", isAgreeJoin);\n                put(\"opReason\", opReason);\n            }\n        });\n    }\n\n    /**\n     * 指定管理员身份\n     */\n    @Override\n    public void onGrantAdministrator(final String groupID, final V2TIMGroupMemberInfo opUser, final List<V2TIMGroupMemberInfo> memberList) {\n        super.onGrantAdministrator(groupID, opUser, memberList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.GrantAdministrator, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n                put(\"memberList\", memberList);\n            }\n        });\n    }\n\n    /**\n     * 取消管理员身份\n     */\n    @Override\n    public void onRevokeAdministrator(final String groupID, final V2TIMGroupMemberInfo opUser, final List<V2TIMGroupMemberInfo> memberList) {\n        super.onRevokeAdministrator(groupID, opUser, memberList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.RevokeAdministrator, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"opUser\", opUser);\n                put(\"memberList\", memberList);\n            }\n        });\n    }\n\n    /**\n     * 主动退出群组（主要用于多端同步，直播群（AVChatRoom）不支持）\n     */\n    @Override\n    public void onQuitFromGroup(String groupID) {\n        super.onQuitFromGroup(groupID);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.QuitFromGroup, groupID);\n    }\n\n    /**\n     * 收到 RESTAPI 下发的自定义系统消息\n     */\n    @Override\n    public void onReceiveRESTCustomData(final String groupID, final byte[] customData) {\n        super.onReceiveRESTCustomData(groupID, customData);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ReceiveRESTCustomData, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"customData\", new String(customData));\n            }\n        });\n    }\n\n    /**\n     * 收到群属性更新的回调\n     */\n    @Override\n    public void onGroupAttributeChanged(final String groupID, final Map<String, String> groupAttributeMap) {\n        super.onGroupAttributeChanged(groupID, groupAttributeMap);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.GroupAttributeChanged, new HashMap<String, Object>() {\n            {\n                put(\"groupID\", groupID);\n                put(\"attributes\", groupAttributeMap);\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/listener/CustomSDKListener.java",
    "content": "package top.huic.tencent_im_plugin.listener;\n\nimport com.tencent.imsdk.v2.V2TIMSDKListener;\nimport com.tencent.imsdk.v2.V2TIMUserFullInfo;\n\nimport java.util.HashMap;\n\nimport top.huic.tencent_im_plugin.TencentImPlugin;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * SDK基本监听器\n */\npublic class CustomSDKListener extends V2TIMSDKListener {\n    /**\n     * 正在连接到腾讯云服务器\n     */\n    @Override\n    public void onConnecting() {\n        super.onConnecting();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.Connecting, null);\n    }\n\n    /**\n     * 网络连接成功\n     */\n    @Override\n    public void onConnectSuccess() {\n        super.onConnectSuccess();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ConnectSuccess, null);\n    }\n\n    /**\n     * 网络连接失败\n     */\n    @Override\n    public void onConnectFailed(final int code, final String error) {\n        super.onConnectFailed(code, error);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ConnectFailed, new HashMap<String, Object>() {\n            {\n                put(\"code\", code);\n                put(\"error\", error);\n            }\n        });\n    }\n\n    /**\n     * 踢下线通知\n     */\n    @Override\n    public void onKickedOffline() {\n        super.onKickedOffline();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.KickedOffline, null);\n    }\n\n    /**\n     * 当前用户的资料发生了更新\n     */\n    @Override\n    public void onSelfInfoUpdated(V2TIMUserFullInfo info) {\n        super.onSelfInfoUpdated(info);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.SelfInfoUpdated, info);\n    }\n\n    /**\n     * 用户登录的 userSig 过期（用户需要重新获取 userSig 后登录）\n     */\n    @Override\n    public void onUserSigExpired() {\n        super.onUserSigExpired();\n        TencentImPlugin.invokeListener(ListenerTypeEnum.UserSigExpired, null);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/listener/CustomSignalingListener.java",
    "content": "package top.huic.tencent_im_plugin.listener;\n\nimport com.tencent.imsdk.v2.V2TIMSignalingListener;\n\nimport java.util.HashMap;\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.TencentImPlugin;\nimport top.huic.tencent_im_plugin.enums.ListenerTypeEnum;\n\n/**\n * 自定义信令监听器\n */\npublic class CustomSignalingListener extends V2TIMSignalingListener {\n    /**\n     * 收到新邀请时\n     */\n    @Override\n    public void onReceiveNewInvitation(final String inviteID, final String inviter, final String groupID, final List<String> inviteeList, final String data) {\n        super.onReceiveNewInvitation(inviteID, inviter, groupID, inviteeList, data);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.ReceiveNewInvitation, new HashMap<String, Object>() {\n            {\n                put(\"inviteID\", inviteID);\n                put(\"inviter\", inviter);\n                put(\"groupID\", groupID);\n                put(\"inviteeList\", inviteeList);\n                put(\"data\", data);\n            }\n        });\n    }\n\n    /**\n     * 被邀请者接受邀请\n     */\n    @Override\n    public void onInviteeAccepted(final String inviteID, final String invitee, final String data) {\n        super.onInviteeAccepted(inviteID, invitee, data);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.InviteeAccepted, new HashMap<String, Object>() {\n            {\n                put(\"inviteID\", inviteID);\n                put(\"invitee\", invitee);\n                put(\"data\", data);\n            }\n        });\n    }\n\n    /**\n     * 被邀请者拒绝邀请\n     */\n    @Override\n    public void onInviteeRejected(final String inviteID, final String invitee, final String data) {\n        super.onInviteeRejected(inviteID, invitee, data);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.InviteeRejected, new HashMap<String, Object>() {\n            {\n                put(\"inviteID\", inviteID);\n                put(\"invitee\", invitee);\n                put(\"data\", data);\n            }\n        });\n    }\n\n    /**\n     * 邀请被取消\n     */\n    @Override\n    public void onInvitationCancelled(final String inviteID, final String inviter, final String data) {\n        super.onInvitationCancelled(inviteID, inviter, data);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.InvitationCancelled, new HashMap<String, Object>() {\n            {\n                put(\"inviteID\", inviteID);\n                put(\"inviter\", inviter);\n                put(\"data\", data);\n            }\n        });\n    }\n\n    /**\n     * 邀请超时\n     */\n    @Override\n    public void onInvitationTimeout(final String inviteID, final List<String> inviteeList) {\n        super.onInvitationTimeout(inviteID, inviteeList);\n        TencentImPlugin.invokeListener(ListenerTypeEnum.InvitationTimeout, new HashMap<String, Object>() {\n            {\n                put(\"inviteID\", inviteID);\n                put(\"inviteeList\", inviteeList);\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/AbstractMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.entity.AbstractMessageEntity;\n\n/**\n * 消息节点接口\n *\n * @param <N> 节点类型，对应腾讯云 TIMElem\n */\npublic abstract class AbstractMessageNode<N, E extends AbstractMessageEntity> {\n    /**\n     * 获得发送的消息体\n     *\n     * @param entity 消息实体\n     * @return 结果\n     */\n    public V2TIMMessage getV2TIMMessage(E entity) {\n        throw new RuntimeException(\"This node does not support sending\");\n    }\n\n    /**\n     * 根据消息节点获得描述\n     *\n     * @param elem 节点\n     */\n    public abstract String getNote(N elem);\n\n    /**\n     * 将节点解析为实体对象\n     *\n     * @param elem 节点\n     * @return 实体对象\n     */\n    public abstract E analysis(N elem);\n\n    /**\n     * 获得实体类型\n     *\n     * @return 类型\n     */\n    public abstract Class<E> getEntityClass();\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/CustomMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMCustomElem;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.entity.CustomMessageEntity;\n\n/**\n * 自定义消息节点\n */\npublic class CustomMessageNode extends AbstractMessageNode<V2TIMCustomElem, CustomMessageEntity> {\n\n    @Override\n    public V2TIMMessage getV2TIMMessage(CustomMessageEntity entity) {\n        return V2TIMManager.getMessageManager().createCustomMessage(entity.getData().getBytes(), entity.getDesc(), entity.getExt() == null ? null : entity.getExt().getBytes());\n    }\n\n    @Override\n    public String getNote(V2TIMCustomElem elem) {\n        return \"[其它消息]\";\n    }\n\n    @Override\n    public CustomMessageEntity analysis(V2TIMCustomElem elem) {\n        return new CustomMessageEntity(elem);\n    }\n\n    @Override\n    public Class<CustomMessageEntity> getEntityClass() {\n        return CustomMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/FaceMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMFaceElem;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.entity.FaceMessageEntity;\n\n/**\n * 表情消息节点\n */\npublic class FaceMessageNode extends AbstractMessageNode<V2TIMFaceElem, FaceMessageEntity> {\n\n    @Override\n    public V2TIMMessage getV2TIMMessage(FaceMessageEntity entity) {\n        return V2TIMManager.getMessageManager().createFaceMessage(entity.getIndex(), entity.getData().getBytes());\n    }\n\n    @Override\n    public String getNote(V2TIMFaceElem elem) {\n        return \"[表情]\";\n    }\n\n    @Override\n    public FaceMessageEntity analysis(V2TIMFaceElem elem) {\n        return new FaceMessageEntity(elem);\n    }\n\n    @Override\n    public Class<FaceMessageEntity> getEntityClass() {\n        return FaceMessageEntity.class;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/FileMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMFileElem;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.entity.FileMessageEntity;\n\n/**\n * 文件消息节点\n */\npublic class FileMessageNode extends AbstractMessageNode<V2TIMFileElem, FileMessageEntity> {\n    @Override\n    public V2TIMMessage getV2TIMMessage(FileMessageEntity entity) {\n        return V2TIMManager.getMessageManager().createFileMessage(entity.getFilePath(), entity.getFileName());\n    }\n\n    @Override\n    public String getNote(V2TIMFileElem elem) {\n        return \"[文件]\";\n    }\n\n    @Override\n    public FileMessageEntity analysis(V2TIMFileElem elem) {\n        return new FileMessageEntity(elem);\n    }\n\n    @Override\n    public Class<FileMessageEntity> getEntityClass() {\n        return FileMessageEntity.class;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/GroupTipsMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMGroupTipsElem;\n\nimport top.huic.tencent_im_plugin.message.entity.GroupTipsMessageEntity;\n\n/**\n * 群提示消息节点\n */\npublic class GroupTipsMessageNode extends AbstractMessageNode<V2TIMGroupTipsElem, GroupTipsMessageEntity> {\n    @Override\n    public String getNote(V2TIMGroupTipsElem elem) {\n        return \"[群提示]\";\n    }\n\n    @Override\n    public GroupTipsMessageEntity analysis(V2TIMGroupTipsElem elem) {\n        return new GroupTipsMessageEntity(elem);\n    }\n\n    @Override\n    public Class<GroupTipsMessageEntity> getEntityClass() {\n        return GroupTipsMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/ImageMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMImageElem;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.entity.ImageMessageEntity;\n\n/**\n * 图片消息节点\n */\npublic class ImageMessageNode extends AbstractMessageNode<V2TIMImageElem, ImageMessageEntity> {\n    @Override\n    public V2TIMMessage getV2TIMMessage(ImageMessageEntity entity) {\n        return V2TIMManager.getMessageManager().createImageMessage(entity.getPath());\n    }\n\n    @Override\n    public String getNote(V2TIMImageElem elem) {\n        return \"[图片]\";\n    }\n\n    @Override\n    public ImageMessageEntity analysis(V2TIMImageElem elem) {\n        ImageMessageEntity entity = new ImageMessageEntity();\n        entity.setPath(elem.getPath());\n        entity.setImageData(elem.getImageList());\n        return entity;\n    }\n\n    @Override\n    public Class<ImageMessageEntity> getEntityClass() {\n        return ImageMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/LocationMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMLocationElem;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\n\nimport top.huic.tencent_im_plugin.message.entity.LocationMessageEntity;\n\n/**\n * 位置消息节点\n */\npublic class LocationMessageNode extends AbstractMessageNode<V2TIMLocationElem, LocationMessageEntity> {\n    @Override\n    public V2TIMMessage getV2TIMMessage(LocationMessageEntity entity) {\n        return V2TIMManager.getMessageManager().createLocationMessage(entity.getDesc(), entity.getLongitude(), entity.getLatitude());\n    }\n\n    @Override\n    public String getNote(V2TIMLocationElem elem) {\n        return \"[位置消息]\";\n    }\n\n    @Override\n    public LocationMessageEntity analysis(V2TIMLocationElem elem) {\n        return new LocationMessageEntity(elem);\n    }\n\n    @Override\n    public Class<LocationMessageEntity> getEntityClass() {\n        return LocationMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/SoundMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMSoundElem;\n\nimport top.huic.tencent_im_plugin.message.entity.SoundMessageEntity;\n\n/**\n * 语音消息节点\n */\npublic class SoundMessageNode extends AbstractMessageNode<V2TIMSoundElem, SoundMessageEntity> {\n\n    @Override\n    public V2TIMMessage getV2TIMMessage(SoundMessageEntity entity) {\n        return V2TIMManager.getMessageManager().createSoundMessage(entity.getPath(), entity.getDuration());\n    }\n\n    @Override\n    public String getNote(V2TIMSoundElem elem) {\n        return \"[语音]\";\n    }\n\n    @Override\n    public SoundMessageEntity analysis(V2TIMSoundElem elem) {\n        return new SoundMessageEntity(elem);\n    }\n\n    @Override\n    public Class<SoundMessageEntity> getEntityClass() {\n        return SoundMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/TextMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMGroupAtInfo;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMTextElem;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.message.entity.TextMessageEntity;\n\n/**\n * 文本消息节点\n */\npublic class TextMessageNode extends AbstractMessageNode<V2TIMTextElem, TextMessageEntity> {\n    @Override\n    public V2TIMMessage getV2TIMMessage(TextMessageEntity entity) {\n\n        // 有@用户或者@所有人则进入分支\n        if ((entity.getAtUserList() != null && entity.getAtUserList().size() >= 1) || (entity.getAtAll() != null && entity.getAtAll())) {\n            List<String> atList = new ArrayList<>();\n            // @所有人\n            if (entity.getAtAll() != null && entity.getAtAll()) {\n                atList.add(V2TIMGroupAtInfo.AT_ALL_TAG);\n            }\n\n            // @目标用户\n            if (entity.getAtUserList() != null) {\n                atList.addAll(entity.getAtUserList());\n            }\n            return V2TIMManager.getMessageManager().createTextAtMessage(entity.getContent(), atList);\n        }\n        return V2TIMManager.getMessageManager().createTextMessage(entity.getContent());\n    }\n\n    @Override\n    public String getNote(V2TIMTextElem elem) {\n        return elem.getText();\n    }\n\n    @Override\n    public TextMessageEntity analysis(V2TIMTextElem elem) {\n        return new TextMessageEntity(elem);\n    }\n\n    @Override\n    public Class<TextMessageEntity> getEntityClass() {\n        return TextMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/VideoMessageNode.java",
    "content": "package top.huic.tencent_im_plugin.message;\n\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMVideoElem;\n\nimport top.huic.tencent_im_plugin.message.entity.VideoMessageEntity;\n\n/**\n * 视频消息节点\n */\npublic class VideoMessageNode extends AbstractMessageNode<V2TIMVideoElem, VideoMessageEntity> {\n    @Override\n    public V2TIMMessage getV2TIMMessage(VideoMessageEntity entity) {\n        String suffix = null;\n        if (entity.getVideoPath().contains(\".\")) {\n            String[] ss = entity.getVideoPath().split(\"\\\\.\");\n            suffix = ss[ss.length - 1];\n        }\n        return V2TIMManager.getMessageManager().createVideoMessage(entity.getVideoPath(), suffix, entity.getDuration(), entity.getSnapshotPath());\n    }\n\n    @Override\n    public String getNote(V2TIMVideoElem elem) {\n        return \"[视频]\";\n    }\n\n    @Override\n    public VideoMessageEntity analysis(V2TIMVideoElem elem) {\n        return new VideoMessageEntity(elem);\n    }\n\n    @Override\n    public Class<VideoMessageEntity> getEntityClass() {\n        return VideoMessageEntity.class;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/AbstractMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport java.io.Serializable;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 消息实体\n *\n * @author 蒋具宏\n */\npublic class AbstractMessageEntity implements Serializable {\n    private MessageNodeType nodeType;\n\n    public AbstractMessageEntity(MessageNodeType nodeType) {\n        this.nodeType = nodeType;\n    }\n\n    public MessageNodeType getNodeType() {\n        return nodeType;\n    }\n\n    public void setNodeType(MessageNodeType nodeType) {\n        this.nodeType = nodeType;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/CustomMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMCustomElem;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 自定义消息实体\n *\n * @author 蒋具宏\n */\npublic class CustomMessageEntity extends AbstractMessageEntity {\n    /**\n     * 自定义内容\n     */\n    private String data;\n\n    /**\n     * 描述\n     */\n    private String desc;\n\n    /**\n     * 扩展内容\n     */\n    private String ext;\n\n    public CustomMessageEntity() {\n        super(MessageNodeType.Custom);\n    }\n\n    public CustomMessageEntity(V2TIMCustomElem elem) {\n        super(MessageNodeType.Custom);\n        if (elem.getData() == null || elem.getData().length == 0) {\n            this.data = null;\n        } else {\n            this.data = new String(elem.getData());\n        }\n        this.desc = elem.getDescription();\n        if (elem.getExtension() != null && elem.getExtension().length != 0) {\n            this.ext = new String(elem.getExtension());\n        }\n    }\n\n    public String getData() {\n        return data;\n    }\n\n    public void setData(String data) {\n        this.data = data;\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n\n    public String getExt() {\n        return ext;\n    }\n\n    public void setExt(String ext) {\n        this.ext = ext;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/FaceMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMFaceElem;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 表情消息实体\n */\npublic class FaceMessageEntity extends AbstractMessageEntity {\n\n    /**\n     * 索引\n     */\n    private int index;\n\n    /**\n     * 数据\n     */\n    private String data;\n\n\n    public FaceMessageEntity() {\n        super(MessageNodeType.Face);\n    }\n\n    public FaceMessageEntity(V2TIMFaceElem elem) {\n        super(MessageNodeType.Face);\n        this.setIndex(elem.getIndex());\n        this.setData(elem.getData() == null ? null : new String(elem.getData()));\n    }\n\n    public int getIndex() {\n        return index;\n    }\n\n    public void setIndex(int index) {\n        this.index = index;\n    }\n\n    public String getData() {\n        return data;\n    }\n\n    public void setData(String data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/FileMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMFileElem;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 文件消息实体\n */\npublic class FileMessageEntity extends AbstractMessageEntity {\n    /**\n     * 文件路径\n     */\n    private String filePath;\n\n    /**\n     * 文件名\n     */\n    private String fileName;\n\n    /**\n     * 文件UUID\n     */\n    private String uuid;\n\n    /**\n     * 文件大小\n     */\n    private int size;\n\n    public FileMessageEntity() {\n        super(MessageNodeType.File);\n    }\n\n    public FileMessageEntity(V2TIMFileElem elem) {\n        super(MessageNodeType.File);\n        this.setFileName(elem.getFileName());\n        this.setFilePath(elem.getPath());\n        this.setSize(elem.getFileSize());\n        this.setUuid(elem.getUUID());\n    }\n\n    public String getFilePath() {\n        return filePath;\n    }\n\n    public void setFilePath(String filePath) {\n        this.filePath = filePath;\n    }\n\n    public String getFileName() {\n        return fileName;\n    }\n\n    public void setFileName(String fileName) {\n        this.fileName = fileName;\n    }\n\n    public String getUuid() {\n        return uuid;\n    }\n\n    public void setUuid(String uuid) {\n        this.uuid = uuid;\n    }\n\n    public int getSize() {\n        return size;\n    }\n\n    public void setSize(int size) {\n        this.size = size;\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/GroupTipsMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMGroupChangeInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberChangeInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupMemberInfo;\nimport com.tencent.imsdk.v2.V2TIMGroupTipsElem;\n\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 群提示消息实体\n *\n * @author 蒋具宏\n */\npublic class GroupTipsMessageEntity extends AbstractMessageEntity {\n\n    /**\n     * 群ID\n     */\n    private String groupID;\n\n    /**\n     * 群事件通知类型\n     */\n    private int type;\n\n    /**\n     * 操作用户\n     */\n    private V2TIMGroupMemberInfo opMember;\n\n    /**\n     * 被操作人列表\n     */\n    private List<V2TIMGroupMemberInfo> memberList;\n\n    /**\n     * 群资料变更信息列表，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE时有效\n     */\n    private List<V2TIMGroupChangeInfo> groupChangeInfoList\t;\n\n    /**\n     * 获取群成员变更信息列表，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE时有效\n     */\n    private List<V2TIMGroupMemberChangeInfo> memberChangeInfoList;\n\n    /**\n     * 当前群成员数，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_JOIN, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_QUIT, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_KICKED的时候有效\n     */\n    private int memberCount;\n\n    public GroupTipsMessageEntity() {\n        super(MessageNodeType.GroupTips);\n    }\n\n    public GroupTipsMessageEntity(V2TIMGroupTipsElem elem){\n        super(MessageNodeType.GroupTips);\n        this.groupID = elem.getGroupID();\n        this.type = elem.getType();\n        this.opMember = elem.getOpMember();\n        this.memberList = elem.getMemberList();\n        this.groupChangeInfoList = elem.getGroupChangeInfoList();\n        this.memberChangeInfoList = elem.getMemberChangeInfoList();\n        this.memberCount = elem.getMemberCount();\n    }\n\n    public String getGroupID() {\n        return groupID;\n    }\n\n    public void setGroupID(String groupID) {\n        this.groupID = groupID;\n    }\n\n    public int getType() {\n        return type;\n    }\n\n    public void setType(int type) {\n        this.type = type;\n    }\n\n    public V2TIMGroupMemberInfo getOpMember() {\n        return opMember;\n    }\n\n    public void setOpMember(V2TIMGroupMemberInfo opMember) {\n        this.opMember = opMember;\n    }\n\n    public List<V2TIMGroupMemberInfo> getMemberList() {\n        return memberList;\n    }\n\n    public void setMemberList(List<V2TIMGroupMemberInfo> memberList) {\n        this.memberList = memberList;\n    }\n\n    public List<V2TIMGroupChangeInfo> getGroupChangeInfoList() {\n        return groupChangeInfoList;\n    }\n\n    public void setGroupChangeInfoList(List<V2TIMGroupChangeInfo> groupChangeInfoList) {\n        this.groupChangeInfoList = groupChangeInfoList;\n    }\n\n    public List<V2TIMGroupMemberChangeInfo> getMemberChangeInfoList() {\n        return memberChangeInfoList;\n    }\n\n    public void setMemberChangeInfoList(List<V2TIMGroupMemberChangeInfo> memberChangeInfoList) {\n        this.memberChangeInfoList = memberChangeInfoList;\n    }\n\n    public int getMemberCount() {\n        return memberCount;\n    }\n\n    public void setMemberCount(int memberCount) {\n        this.memberCount = memberCount;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/ImageMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMImageElem;\n\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 图片消息实体\n *\n * @author 蒋具宏\n */\npublic class ImageMessageEntity extends AbstractMessageEntity {\n    /**\n     * 原图本地文件路径，发送方有效\n     */\n    private String path;\n\n    /**\n     * 图片列表，根据类型分开\n     */\n    private List<V2TIMImageElem.V2TIMImage> imageData;\n\n    public ImageMessageEntity() {\n        super(MessageNodeType.Image);\n    }\n\n    public ImageMessageEntity(V2TIMImageElem elem) {\n        super(MessageNodeType.Image);\n        this.setPath(elem.getPath());\n        this.setImageData(elem.getImageList());\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public List<V2TIMImageElem.V2TIMImage> getImageData() {\n        return imageData;\n    }\n\n    public void setImageData(List<V2TIMImageElem.V2TIMImage> imageData) {\n        this.imageData = imageData;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/LocationMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMLocationElem;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 位置消息实体\n *\n * @author 蒋具宏\n */\npublic class LocationMessageEntity extends AbstractMessageEntity {\n    /**\n     * 描述\n     */\n    private String desc;\n\n    /**\n     * 经度\n     */\n    private double latitude;\n\n    /**\n     * 纬度\n     */\n    private double longitude;\n\n    public LocationMessageEntity() {\n        super(MessageNodeType.Location);\n    }\n\n    public LocationMessageEntity(V2TIMLocationElem elem) {\n        super(MessageNodeType.Location);\n        this.setDesc(elem.getDesc());\n        this.setLongitude(elem.getLongitude());\n        this.setLatitude(elem.getLatitude());\n    }\n\n    public String getDesc() {\n        return desc;\n    }\n\n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n\n    public double getLatitude() {\n        return latitude;\n    }\n\n    public void setLatitude(double latitude) {\n        this.latitude = latitude;\n    }\n\n    public double getLongitude() {\n        return longitude;\n    }\n\n    public void setLongitude(double longitude) {\n        this.longitude = longitude;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/SoundMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMSoundElem;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 语音消息实体\n *\n * @author 蒋具宏\n */\npublic class SoundMessageEntity extends AbstractMessageEntity {\n\n    /**\n     * 语音ID\n     */\n    private String uuid;\n\n    /**\n     * 路径\n     */\n    private String path;\n\n    /**\n     * 时长\n     */\n    private Integer duration;\n\n    /**\n     * 数据大小\n     */\n    private Integer dataSize;\n\n    public SoundMessageEntity() {\n        super(MessageNodeType.Sound);\n    }\n\n    public SoundMessageEntity(V2TIMSoundElem elem) {\n        super(MessageNodeType.Sound);\n        this.setPath(elem.getPath());\n        this.setDuration(elem.getDuration());\n        this.setDataSize(elem.getDataSize());\n        this.setUuid(elem.getUUID());\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public Integer getDuration() {\n        return duration;\n    }\n\n    public void setDuration(Integer duration) {\n        this.duration = duration;\n    }\n\n    public Integer getDataSize() {\n        return dataSize;\n    }\n\n    public void setDataSize(Integer dataSize) {\n        this.dataSize = dataSize;\n    }\n\n    public String getUuid() {\n        return uuid;\n    }\n\n    public void setUuid(String uuid) {\n        this.uuid = uuid;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/TextMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMTextElem;\n\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 文本消息实体\n *\n * @author 蒋具宏\n */\npublic class TextMessageEntity extends AbstractMessageEntity {\n    /**\n     * 消息内容\n     */\n    private String content;\n\n    /**\n     * \\@的用户列表\n     */\n    private List<String> atUserList;\n\n    /**\n     * 是否@所有人\n     */\n    private Boolean atAll;\n\n    public TextMessageEntity() {\n        super(MessageNodeType.Text);\n    }\n\n    public TextMessageEntity(V2TIMTextElem elem) {\n        super(MessageNodeType.Text);\n        this.content = elem.getText();\n    }\n\n    public String getContent() {\n        return content;\n    }\n\n    public void setContent(String content) {\n        this.content = content;\n    }\n\n    public List<String> getAtUserList() {\n        return atUserList;\n    }\n\n    public void setAtUserList(List<String> atUserList) {\n        this.atUserList = atUserList;\n    }\n\n    public Boolean getAtAll() {\n        return atAll;\n    }\n\n    public void setAtAll(Boolean atAll) {\n        this.atAll = atAll;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/message/entity/VideoMessageEntity.java",
    "content": "package top.huic.tencent_im_plugin.message.entity;\n\nimport com.tencent.imsdk.v2.V2TIMVideoElem;\n\nimport java.io.Serializable;\n\nimport top.huic.tencent_im_plugin.enums.MessageNodeType;\n\n/**\n * 视频消息实体\n *\n * @author 蒋具宏\n */\npublic class VideoMessageEntity extends AbstractMessageEntity implements Serializable {\n    /**\n     * 视频路径\n     */\n    private String videoPath;\n    /**\n     * 视频UUID\n     */\n    private String videoUuid;\n    /**\n     * 视频大小\n     */\n    private int videoSize;\n    /**\n     * 时长\n     */\n    private int duration;\n    /**\n     * 缩略图路径\n     */\n    private String snapshotPath;\n    /**\n     * 缩略图UUID\n     */\n    private String snapshotUuid;\n    /**\n     * 缩略图大小\n     */\n    private int snapshotSize;\n    /**\n     * 缩略图宽度\n     */\n    private int snapshotWidth;\n    /**\n     * 缩略图高度\n     */\n    private int snapshotHeight;\n\n    public VideoMessageEntity() {\n        super(MessageNodeType.Video);\n    }\n\n    public VideoMessageEntity(V2TIMVideoElem elem) {\n        super(MessageNodeType.Video);\n        this.setVideoUuid(elem.getVideoUUID());\n        this.setVideoPath(elem.getVideoPath());\n        this.setVideoSize(elem.getVideoSize());\n        this.setDuration(elem.getDuration());\n        this.setSnapshotUuid(elem.getSnapshotUUID());\n        this.setSnapshotWidth(elem.getSnapshotWidth());\n        this.setSnapshotHeight(elem.getSnapshotHeight());\n        this.setSnapshotPath(elem.getSnapshotPath());\n        this.setSnapshotSize(elem.getSnapshotSize());\n    }\n\n    public String getVideoPath() {\n        return videoPath;\n    }\n\n    public void setVideoPath(String videoPath) {\n        this.videoPath = videoPath;\n    }\n\n    public String getVideoUuid() {\n        return videoUuid;\n    }\n\n    public void setVideoUuid(String videoUuid) {\n        this.videoUuid = videoUuid;\n    }\n\n    public int getVideoSize() {\n        return videoSize;\n    }\n\n    public void setVideoSize(int videoSize) {\n        this.videoSize = videoSize;\n    }\n\n    public int getDuration() {\n        return duration;\n    }\n\n    public void setDuration(int duration) {\n        this.duration = duration;\n    }\n\n    public String getSnapshotPath() {\n        return snapshotPath;\n    }\n\n    public void setSnapshotPath(String snapshotPath) {\n        this.snapshotPath = snapshotPath;\n    }\n\n    public String getSnapshotUuid() {\n        return snapshotUuid;\n    }\n\n    public void setSnapshotUuid(String snapshotUuid) {\n        this.snapshotUuid = snapshotUuid;\n    }\n\n    public int getSnapshotSize() {\n        return snapshotSize;\n    }\n\n    public void setSnapshotSize(int snapshotSize) {\n        this.snapshotSize = snapshotSize;\n    }\n\n    public int getSnapshotWidth() {\n        return snapshotWidth;\n    }\n\n    public void setSnapshotWidth(int snapshotWidth) {\n        this.snapshotWidth = snapshotWidth;\n    }\n\n    public int getSnapshotHeight() {\n        return snapshotHeight;\n    }\n\n    public void setSnapshotHeight(int snapshotHeight) {\n        this.snapshotHeight = snapshotHeight;\n    }\n}"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/util/BeanUtils.java",
    "content": "package top.huic.tencent_im_plugin.util;\n\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Bean工具类\n */\npublic class BeanUtils {\n    /**\n     * 复制属性\n     *\n     * @param source           源对象\n     * @param target           目标对象\n     * @param ignoreProperties 忽略的参数列表\n     */\n    public static void copyProperties(Object source, Object target, String... ignoreProperties) {\n        Class<?> sourceClass = source.getClass();\n        Class<?> targetClass = target.getClass();\n\n        // 填充目标方法列表\n        Map<String, Method> targetMethodMap = new HashMap<>();\n        for (Method method : targetClass.getDeclaredMethods()) {\n            targetMethodMap.put(method.getName(), method);\n        }\n\n        try {\n            for (Method method : sourceClass.getDeclaredMethods()) {\n                String name = method.getName();\n\n                // 验证是否是属性方法(get / is)\n                if (method.getReturnType() != Void.class || method.getParameterTypes().length >= 1 || !(name.startsWith(\"get\") || name.startsWith(\"is\"))) {\n\n                    // 获得方法后缀名(不包含 get is 前缀的内容)\n                    String methodSuffixName = name.replaceFirst(name.startsWith(\"get\") ? \"get\" : \"is\", \"\");\n                    if (methodSuffixName.length() == 0) {\n                        continue;\n                    }\n                    // 获得真实属性名\n                    String fieldName = methodSuffixName.substring(0, 1).toLowerCase() + methodSuffixName.substring(1);\n\n                    // 如果是忽略的属性\n                    if (ignoreProperties != null && Arrays.asList(ignoreProperties).contains(fieldName)) {\n                        continue;\n                    }\n\n                    // 如果不存在设置方法\n                    String setMethodName = \"set\" + methodSuffixName;\n                    if (!targetMethodMap.containsKey(setMethodName)) {\n                        continue;\n                    }\n\n                    // 方法校验(非普通set参数(1个参数)) 或 不是公开方法，则不进行赋值确认\n                    Method targetMethod = targetMethodMap.get(setMethodName);\n                    if (targetMethod.getParameterTypes().length != 1 || targetMethod.getModifiers() != Modifier.PUBLIC) {\n                        continue;\n                    }\n\n                    // 获得值，如果为null则忽略\n                    Object resultValue = method.invoke(source);\n                    if (resultValue == null) {\n                        continue;\n                    }\n\n                    // 赋值\n                    targetMethod.invoke(target, resultValue);\n                }\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/util/CommonUtil.java",
    "content": "package top.huic.tencent_im_plugin.util;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport io.flutter.plugin.common.MethodCall;\nimport io.flutter.plugin.common.MethodChannel;\n\n/**\n * 工具类\n */\npublic class CommonUtil {\n    /**\n     * 主线程处理器\n     */\n    private final static Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());\n\n    /**\n     * 通用方法，获得参数值，如未找到参数，则直接中断\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回对象\n     * @param param      参数名\n     */\n    public static <T> T getParam(MethodCall methodCall, MethodChannel.Result result, String param) {\n        T par = methodCall.argument(param);\n        if (par == null) {\n            result.error(\"Missing parameter\", \"Cannot find parameter `\" + param + \"` or `\" + param + \"` is null!\", 5);\n            throw new RuntimeException(\"Cannot find parameter `\" + param + \"` or `\" + param + \"` is null!\");\n        }\n        return par;\n    }\n\n    /**\n     * 运行主线程返回结果执行\n     *\n     * @param result 返回结果对象\n     * @param param  返回参数\n     */\n    public static void runMainThreadReturn(final MethodChannel.Result result, final Object param) {\n        MAIN_HANDLER.post(new Runnable() {\n            @Override\n            public void run() {\n                result.success(param);\n            }\n        });\n    }\n\n    /**\n     * 运行主线程返回错误结果执行\n     *\n     * @param result       返回结果对象\n     * @param errorCode    错误码\n     * @param errorMessage 错误信息\n     * @param errorDetails 错误内容\n     */\n    public static void runMainThreadReturnError(final MethodChannel.Result result, final String errorCode, final String errorMessage, final Object errorDetails) {\n        MAIN_HANDLER.post(new Runnable() {\n            @Override\n            public void run() {\n                result.error(errorCode, errorMessage, errorDetails);\n            }\n        });\n    }\n\n    /**\n     * 运行主线程方法\n     */\n    public static void runMainThreadMethod(Runnable runnable){\n        MAIN_HANDLER.post(runnable);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/util/JsonUtil.java",
    "content": "package top.huic.tencent_im_plugin.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.alibaba.fastjson.serializer.ValueFilter;\n\n/**\n * JSON工具类\n *\n * @author 蒋具宏\n */\npublic class JsonUtil {\n    /**\n     * 自定义数据过滤器\n     */\n    private static final ValueFilter filter = new ValueFilter() {\n        @Override\n        public Object process(Object object, String name, Object value) {\n            if (value instanceof byte[]) {\n                return new String((byte[]) value);\n            }\n            return value;\n        }\n    };\n\n    /**\n     * 将对象序列化为JSON\n     *\n     * @param data 对象\n     * @return 解析结果\n     */\n    public static String toJSONString(Object data) {\n        if (data instanceof String) return data.toString();\n        return JSON.toJSONString(data, filter);\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/top/huic/tencent_im_plugin/util/TencentImUtils.java",
    "content": "package top.huic.tencent_im_plugin.util;\n\nimport com.alibaba.fastjson.JSON;\nimport com.tencent.imsdk.v2.V2TIMFriendApplication;\nimport com.tencent.imsdk.v2.V2TIMFriendApplicationResult;\nimport com.tencent.imsdk.v2.V2TIMGroupApplication;\nimport com.tencent.imsdk.v2.V2TIMGroupApplicationResult;\nimport com.tencent.imsdk.v2.V2TIMManager;\nimport com.tencent.imsdk.v2.V2TIMMessage;\nimport com.tencent.imsdk.v2.V2TIMValueCallback;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport top.huic.tencent_im_plugin.ValueCallBack;\nimport top.huic.tencent_im_plugin.entity.FindFriendApplicationEntity;\nimport top.huic.tencent_im_plugin.entity.FindGroupApplicationEntity;\nimport top.huic.tencent_im_plugin.entity.FindMessageEntity;\n\n/**\n * 腾讯云IM工具类\n */\npublic class TencentImUtils {\n\n    /**\n     * 获得好友申请对象\n     *\n     * @param json json 字符串\n     * @param call 回调对象\n     */\n    public static void getFriendApplicationByFindGroupApplicationEntity(String json, ValueCallBack<V2TIMFriendApplication> call) {\n        getFriendApplicationByFindGroupApplicationEntity(JSON.parseObject(json, FindFriendApplicationEntity.class), call);\n    }\n\n    /**\n     * 获得好友申请对象\n     *\n     * @param data 实体对象\n     * @param call 回调对象\n     */\n    public static void getFriendApplicationByFindGroupApplicationEntity(final FindFriendApplicationEntity data, final ValueCallBack<V2TIMFriendApplication> call) {\n        V2TIMManager.getFriendshipManager().getFriendApplicationList(new V2TIMValueCallback<V2TIMFriendApplicationResult>() {\n            @Override\n            public void onError(int i, String s) {\n                call.onError(i, s);\n            }\n\n            @Override\n            public void onSuccess(V2TIMFriendApplicationResult v2TIMFriendApplicationResult) {\n                if (v2TIMFriendApplicationResult.getFriendApplicationList() != null) {\n                    for (V2TIMFriendApplication item : v2TIMFriendApplicationResult.getFriendApplicationList()) {\n                        if (item.getUserID().equals(data.getUserID()) && item.getType() == data.getType()) {\n                            call.onSuccess(item);\n                            return;\n                        }\n                    }\n                }\n                call.onSuccess(null);\n            }\n        });\n    }\n\n    /**\n     * 获得群申请对象\n     *\n     * @param json json 字符串\n     * @param call 回调对象\n     */\n    public static void getGroupApplicationByFindGroupApplicationEntity(String json, ValueCallBack<V2TIMGroupApplication> call) {\n        getGroupApplicationByFindGroupApplicationEntity(JSON.parseObject(json, FindGroupApplicationEntity.class), call);\n    }\n\n    /**\n     * 获得群申请对象\n     *\n     * @param data 实体对象\n     * @param call 回调对象\n     */\n    public static void getGroupApplicationByFindGroupApplicationEntity(final FindGroupApplicationEntity data, final ValueCallBack<V2TIMGroupApplication> call) {\n        V2TIMManager.getGroupManager().getGroupApplicationList(new V2TIMValueCallback<V2TIMGroupApplicationResult>() {\n            @Override\n            public void onError(int i, String s) {\n                call.onError(i, s);\n            }\n\n            @Override\n            public void onSuccess(V2TIMGroupApplicationResult v2TIMGroupApplicationResult) {\n                if (v2TIMGroupApplicationResult.getGroupApplicationList() != null) {\n                    for (V2TIMGroupApplication item : v2TIMGroupApplicationResult.getGroupApplicationList()) {\n                        if (item.getGroupID().equals(data.getGroupID()) && item.getFromUser().equals(data.getFromUser())) {\n                            call.onSuccess(item);\n                            return;\n                        }\n                    }\n                }\n                call.onSuccess(null);\n            }\n        });\n    }\n\n    /**\n     * 获得消息对象\n     *\n     * @param json json字符串\n     * @param call 回调对象\n     */\n    public static void getMessageByFindMessageEntity(String json, ValueCallBack<V2TIMMessage> call) {\n        getMessageByFindMessageEntity(JSON.parseObject(json, FindMessageEntity.class), call);\n    }\n\n    /**\n     * 获得消息对象\n     *\n     * @param data 查找消息对象实体\n     * @param call 回调对象\n     */\n    public static void getMessageByFindMessageEntity(final FindMessageEntity data, final ValueCallBack<V2TIMMessage> call) {\n        getMessageByFindMessageEntity(Collections.singletonList(data), new ValueCallBack<List<V2TIMMessage>>(null) {\n            @Override\n            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {\n                if (v2TIMMessages == null || v2TIMMessages.size() == 0) {\n                    call.onError(-1, \"未找到消息对象!消息ID不存在\");\n                    return;\n                }\n                call.onSuccess(v2TIMMessages.get(0));\n            }\n\n            @Override\n            public void onError(int code, String desc) {\n                call.onError(code, desc);\n            }\n        });\n    }\n\n    /**\n     * 获得消息对象\n     *\n     * @param data 查找消息对象实体\n     * @param call 回调对象\n     */\n    public static void getMessageByFindMessageEntity(List<FindMessageEntity> data, final ValueCallBack<List<V2TIMMessage>> call) {\n        List<String> ids = new ArrayList<>();\n        for (FindMessageEntity datum : data) {\n            ids.add(datum.getMsgId());\n        }\n        V2TIMManager.getMessageManager().findMessages(ids, new V2TIMValueCallback<List<V2TIMMessage>>() {\n            @Override\n            public void onError(int i, String s) {\n                call.onError(i, s);\n            }\n\n            @Override\n            public void onSuccess(List<V2TIMMessage> v2TIMMessages) {\n                call.onSuccess(v2TIMMessages);\n            }\n        });\n    }\n}"
  },
  {
    "path": "example/.gitignore",
    "content": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.iws\n.idea/\n\n# The .vscode folder contains launch configuration and tasks you configure in\n# VS Code which you may wish to be included in version control, so this line\n# is commented out by default.\n#.vscode/\n\n# Flutter/Dart/Pub related\n**/doc/api/\n.dart_tool/\n.flutter-plugins\n.flutter-plugins-dependencies\n.packages\n.pub-cache/\n.pub/\n/build/\n\n# Web related\nlib/generated_plugin_registrant.dart\n\n# Exceptions to above rules.\n!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages\n"
  },
  {
    "path": "example/.metadata",
    "content": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrades etc.\n#\n# This file should be version controlled and should not be manually edited.\n\nversion:\n  revision: d345a3b303ce041846ff895eb49a104bef133c4b\n  channel: master\n\nproject_type: app\n"
  },
  {
    "path": "example/README.md",
    "content": "# tencent_im_plugin_example\n\nDemonstrates how to use the tencent_im_plugin plugin.\n\n## Getting Started\n\nThis project is a starting point for a Flutter application.\n\nA few resources to get you started if this is your first Flutter project:\n\n- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)\n- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)\n\nFor help getting started with Flutter, view our\n[online documentation](https://flutter.dev/docs), which offers tutorials,\nsamples, guidance on mobile development, and a full API reference.\n"
  },
  {
    "path": "example/android/.gitignore",
    "content": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n"
  },
  {
    "path": "example/android/app/agconnect-services.json",
    "content": "{\n\t\"agcgw\":{\n\t\t\"backurl\":\"connect-drcn.dbankcloud.cn\",\n\t\t\"url\":\"connect-drcn.hispace.hicloud.com\"\n\t},\n\t\"client\":{\n\t\t\"cp_id\":\"890086000102176873\",\n\t\t\"product_id\":\"736430079244549109\",\n\t\t\"client_id\":\"400572237515588608\",\n\t\t\"client_secret\":\"76A8613ED5A461B6AA74396CAF70DBB0B23690F8B4136A0A66AA202FFEEA890D\",\n\t\t\"app_id\":\"102514829\",\n\t\t\"package_name\":\"top.huic.tencent_im_plugin_example\",\n\t\t\"api_key\":\"CgB6e3x9I8KuPeIag8AT0fhvvrEf57HaQCYqoB91348bgNFNEim2y+8s3/ervtmQDygm6EKiBqCBRdNurhYotfYi\"\n\t},\n\t\"service\":{\n\t\t\"analytics\":{\n\t\t\t\"collector_url\":\"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn\",\n\t\t\t\"resource_id\":\"p1\",\n\t\t\t\"channel_id\":\"\"\n\t\t},\n\t\t\"cloudstorage\":{\n\t\t\t\"storage_url\":\"https://agc-storage-drcn.platform.dbankcloud.cn\"\n\t\t},\n\t\t\"ml\":{\n\t\t\t\"mlservice_url\":\"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn\"\n\t\t}\n\t},\n\t\"region\":\"CN\",\n\t\"configuration_version\":\"1.0\"\n}"
  },
  {
    "path": "example/android/app/build.gradle",
    "content": "def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertiesFile.exists()) {\n    localPropertiesFile.withReader('UTF-8') { reader ->\n        localProperties.load(reader)\n    }\n}\n\ndef flutterRoot = localProperties.getProperty('flutter.sdk')\nif (flutterRoot == null) {\n    throw new GradleException(\"Flutter SDK not found. Define location with flutter.sdk in the local.properties file.\")\n}\n\ndef flutterVersionCode = localProperties.getProperty('flutter.versionCode')\nif (flutterVersionCode == null) {\n    flutterVersionCode = '1'\n}\n\ndef flutterVersionName = localProperties.getProperty('flutter.versionName')\nif (flutterVersionName == null) {\n    flutterVersionName = '1.0'\n}\n\napply plugin: 'com.android.application'\napply from: \"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle\"\n\n//def keystorePropertiesFile = rootProject.file(\"key.properties\")\n//def keystoreProperties = new Properties()\n//keystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n\nandroid {\n    compileSdkVersion 28\n\n    lintOptions {\n        disable 'InvalidPackage'\n    }\n\n    defaultConfig {\n        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).\n        applicationId \"top.huic.tencent_im_plugin_example\"\n        minSdkVersion 17\n        targetSdkVersion 28\n        versionCode flutterVersionCode.toInteger()\n        versionName flutterVersionName\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n    }\n\n    // 证书参数\n    signingConfigs {\n        config {\n            storeFile file('key.jks')\n            storePassword '123456'\n            keyAlias 'key'\n            keyPassword '123456'\n            v1SigningEnabled true\n            v2SigningEnabled true\n        }\n    }\n\n    buildTypes {\n        debug {\n            signingConfig signingConfigs.config\n        }\n\n        release {\n            signingConfig signingConfigs.config\n//            // 开启混淆\n//            minifyEnabled true\n//            useProguard true\n        }\n    }\n    compileOptions {\n        sourceCompatibility = 1.8\n        targetCompatibility = 1.8\n    }\n\n    // 减小应用程序大小的配置\n    aaptOptions {\n        ignoreAssetsPattern \"!x86:!*ffprobe\"\n    }\n}\n\nflutter {\n    source '../..'\n}\n\ndependencies {\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'androidx.test:runner:1.1.1'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'\n}\n\napply plugin: 'com.huawei.agconnect'"
  },
  {
    "path": "example/android/app/src/debug/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"top.huic.tencent_im_plugin_example\">\n    <!-- Flutter needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "example/android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    package=\"top.huic.tencent_im_plugin_example\">\n    <!-- io.flutter.app.FlutterApplication is an android.app.Application that\n         calls FlutterMain.startInitialization(this); in its onCreate method.\n         In most cases you can leave this as-is, but you if you want to provide\n         additional functionality it is fine to subclass or reimplement\n         FlutterApplication and put your custom class here. -->\n\n    <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n    <uses-permission android:name=\"android.permission.GET_TASKS\" />\n    <uses-permission android:name=\"android.permission.VIBRATE\" />\n\n    <permission\n        android:name=\"top.huic.tencent_im_plugin_example.permission.MIPUSH_RECEIVE\"\n        android:protectionLevel=\"signature\" />\n    <uses-permission android:name=\"top.huic.tencent_im_plugin_example.permission.MIPUSH_RECEIVE\" />\n\n\n    <application\n        android:name=\"io.flutter.app.FlutterApplication\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"tencent_im_plugin_example\"\n        tools:replace=\"android:label\">\n        <activity\n            android:name=\".MainActivity\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode\"\n            android:hardwareAccelerated=\"true\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style/LaunchTheme\"\n            android:windowSoftInputMode=\"adjustResize\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <!-- Don't delete the meta-data below.\n             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->\n        <meta-data\n            android:name=\"flutterEmbedding\"\n            android:value=\"2\" />\n    </application>\n</manifest>\n"
  },
  {
    "path": "example/android/app/src/main/java/top/huic/tencent_im_plugin_example/MainActivity.java",
    "content": "package top.huic.tencent_im_plugin_example;\n\nimport android.app.ActivityManager;\nimport android.content.Context;\nimport android.os.Bundle;\nimport java.util.List;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport io.flutter.embedding.android.FlutterActivity;\nimport io.flutter.embedding.engine.FlutterEngine;\nimport io.flutter.plugin.common.MethodChannel;\nimport io.flutter.plugins.GeneratedPluginRegistrant;\n\npublic class MainActivity extends FlutterActivity {\n\n    /**\n     * Flutter 通知器\n     */\n    public static MethodChannel channel;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        channel = new MethodChannel(this.getFlutterEngine().getDartExecutor(), \"tencent_im_plugin_example\");\n    }\n\n    @Override\n    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {\n        GeneratedPluginRegistrant.registerWith(flutterEngine);\n    }\n}\n"
  },
  {
    "path": "example/android/app/src/main/res/drawable/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@android:color/white\" />\n\n    <!-- You can insert your own image assets here -->\n    <!-- <item>\n        <bitmap\n            android:gravity=\"center\"\n            android:src=\"@mipmap/launch_image\" />\n    </item> -->\n</layer-list>\n"
  },
  {
    "path": "example/android/app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             Flutter draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "example/android/app/src/profile/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"top.huic.tencent_im_plugin_example\">\n    <!-- Flutter needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n</manifest>\n"
  },
  {
    "path": "example/android/build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        jcenter()\n        maven {url 'https://developer.huawei.com/repo/'}\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.6.3'\n        classpath 'com.huawei.agconnect:agcp:1.2.1.301'\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n    }\n}\n\nrootProject.buildDir = '../build'\nsubprojects {\n    project.buildDir = \"${rootProject.buildDir}/${project.name}\"\n}\nsubprojects {\n    project.evaluationDependsOn(':app')\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "example/android/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Feb 28 14:11:06 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-5.6.4-all.zip\n"
  },
  {
    "path": "example/android/gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx1536M\nandroid.enableR8=true\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "example/android/settings.gradle",
    "content": "include ':app'\n\ndef flutterProjectRoot = rootProject.projectDir.parentFile.toPath()\n\ndef plugins = new Properties()\ndef pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')\nif (pluginsFile.exists()) {\n    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }\n}\n\nplugins.each { name, path ->\n    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()\n    include \":$name\"\n    project(\":$name\").projectDir = pluginDirectory\n}\n"
  },
  {
    "path": "example/ios/.gitignore",
    "content": "*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/DerivedData/\nIcon?\n**/Pods/\n**/.symlinks/\nprofile\nxcuserdata\n**/.generated/\nFlutter/App.framework\nFlutter/Flutter.framework\nFlutter/Flutter.podspec\nFlutter/Generated.xcconfig\nFlutter/app.flx\nFlutter/app.zip\nFlutter/flutter_assets/\nFlutter/flutter_export_environment.sh\nServiceDefinitions.json\nRunner/GeneratedPluginRegistrant.*\n\n# Exceptions to above rules.\n!default.mode1v3\n!default.mode2v3\n!default.pbxuser\n!default.perspectivev3\n"
  },
  {
    "path": "example/ios/Flutter/AppFrameworkInfo.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>CFBundleDevelopmentRegion</key>\n  <string>$(DEVELOPMENT_LANGUAGE)</string>\n  <key>CFBundleExecutable</key>\n  <string>App</string>\n  <key>CFBundleIdentifier</key>\n  <string>io.flutter.flutter.app</string>\n  <key>CFBundleInfoDictionaryVersion</key>\n  <string>6.0</string>\n  <key>CFBundleName</key>\n  <string>App</string>\n  <key>CFBundlePackageType</key>\n  <string>FMWK</string>\n  <key>CFBundleShortVersionString</key>\n  <string>1.0</string>\n  <key>CFBundleSignature</key>\n  <string>????</string>\n  <key>CFBundleVersion</key>\n  <string>1.0</string>\n  <key>MinimumOSVersion</key>\n  <string>9.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "example/ios/Flutter/Debug.xcconfig",
    "content": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example/ios/Flutter/Release.xcconfig",
    "content": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example/ios/Podfile",
    "content": "# Uncomment this line to define a global platform for your project\nplatform :ios, '8.0'\n\n# CocoaPods analytics sends network stats synchronously affecting flutter build latency.\nENV['COCOAPODS_DISABLE_STATS'] = 'true'\n\nproject 'Runner', {\n  'Debug' => :debug,\n  'Profile' => :release,\n  'Release' => :release,\n}\n\ndef flutter_root\n  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)\n  unless File.exist?(generated_xcode_build_settings_path)\n    raise \"#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first\"\n  end\n\n  File.foreach(generated_xcode_build_settings_path) do |line|\n    matches = line.match(/FLUTTER_ROOT\\=(.*)/)\n    return matches[1].strip if matches\n  end\n  raise \"FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get\"\nend\n\nrequire File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)\n\nflutter_ios_podfile_setup\n\ndef install_plugin_pods(application_path = nil, relative_symlink_dir, platform)\n  # defined_in_file is set by CocoaPods and is a Pathname to the Podfile.\n  application_path ||= File.dirname(defined_in_file.realpath) if self.respond_to?(:defined_in_file)\n  raise 'Could not find application path' unless application_path\n\n  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock\n  # referring to absolute paths on developers' machines.\n\n  symlink_dir = File.expand_path(relative_symlink_dir, application_path)\n  system('rm', '-rf', symlink_dir) # Avoid the complication of dependencies like FileUtils.\n\n  symlink_plugins_dir = File.expand_path('plugins', symlink_dir)\n  system('mkdir', '-p', symlink_plugins_dir)\n\n  plugins_file = File.join(application_path, '..', '.flutter-plugins-dependencies')\n  plugin_pods = flutter_parse_plugins_file(plugins_file, platform)\n  plugin_pods.each do |plugin_hash|\n    plugin_name = plugin_hash['name']\n    plugin_path = plugin_hash['path']\n    if (plugin_name && plugin_path)\n        specPath = \"#{plugin_path}/#{platform}/#{plugin_name}.podspec\"\n        pod plugin_name, :path => specPath\n    end\n  end\nend\n\ntarget 'Runner' do\n  use_frameworks!\n  use_modular_headers!\n\n  flutter_install_ios_engine_pod(File.dirname(File.realpath(__FILE__)))\n  install_plugin_pods(File.dirname(File.realpath(__FILE__)), '.symlinks', 'ios')\nend\n\npost_install do |installer|\n  installer.pods_project.targets.each do |target|\n    flutter_additional_ios_build_settings(target)\n  end\nend"
  },
  {
    "path": "example/ios/Runner/AppDelegate.swift",
    "content": "import UIKit\nimport Flutter\n\n@UIApplicationMain\n@objc class AppDelegate: FlutterAppDelegate {\n  override func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n  ) -> Bool {\n    GeneratedPluginRegistrant.register(with: self)\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n}\n"
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"83.5x83.5\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-83.5x83.5@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"1024x1024\",\n      \"idiom\" : \"ios-marketing\",\n      \"filename\" : \"Icon-App-1024x1024@1x.png\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "content": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in this directory.\n\nYou 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."
  },
  {
    "path": "example/ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"12121\" systemVersion=\"16G29\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"12089\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ydg-fD-yQy\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xbc-2k-c8Z\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" image=\"LaunchImage\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YRO-k0-Ey4\">\n                            </imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerX\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerX\" id=\"1a2-6s-vTC\"/>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerY\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerY\" id=\"4X2-HB-R7a\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"LaunchImage\" width=\"168\" height=\"185\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "example/ios/Runner/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15F34\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10085\"/>\n    </dependencies>\n    <scenes>\n        <!--Flutter View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"FlutterViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "example/ios/Runner/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>tencent_im_plugin_example</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(FLUTTER_BUILD_NAME)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(FLUTTER_BUILD_NUMBER)</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>NSCameraUsageDescription</key>\n\t<string>App需要您的同意,才能访问相册</string>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string>是否允许需要访问位置？</string>\n\t<key>NSMicrophoneUsageDescription</key>\n\t<string>App需要您的同意，才能访问麦克风</string>\n\t<key>NSPhotoLibraryUsageDescription</key>\n\t<string>是否允许访问图片库？</string>\n\t<key>NSPhotoLibraryAddUsageDescription</key>\n\t<string>是否允许保存图片？</string>\n\t<key>Privacy - Calendars Usage Description</key>\n\t<string>是否允许访问日历？</string>\n\t<key>Privacy - Location Always Usage Description</key>\n\t<string>是否允许始终访问位置？</string>\n\t<key>Privacy - Location When In Use Usage Description</key>\n\t<string>是否允许使用期间访问位置？</string>\n\t<key>UIBackgroundModes</key>\n\t<array>\n\t\t<string>audio</string>\n\t</array>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "example/ios/Runner/Runner-Bridging-Header.h",
    "content": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 50;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };\n\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };\n\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };\n\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };\n\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };\n\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };\n\t\tF421BC9C2F4D92DF91A983A8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5951A49241F164BFC879FD8A /* Pods_Runner.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t9705A1C41CF9048500538489 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = \"<group>\"; };\n\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = \"<group>\"; };\n\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = \"<group>\"; };\n\t\t453EE5ABF54A138152CF911D /* 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 = \"<group>\"; };\n\t\t4B436B647E9F79944B465D68 /* 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 = \"<group>\"; };\n\t\t5951A49241F164BFC879FD8A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"Runner-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = \"<group>\"; };\n\t\t97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tE27FEED2BBEF82CCFCE08B08 /* 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 = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t97C146EB1CF9000F007C117D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tF421BC9C2F4D92DF91A983A8 /* Pods_Runner.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t38FEDA953939FFB3CD8B4370 /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t453EE5ABF54A138152CF911D /* Pods-Runner.debug.xcconfig */,\n\t\t\t\tE27FEED2BBEF82CCFCE08B08 /* Pods-Runner.release.xcconfig */,\n\t\t\t\t4B436B647E9F79944B465D68 /* Pods-Runner.profile.xcconfig */,\n\t\t\t);\n\t\t\tpath = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t9740EEB11CF90186004384FC /* Flutter */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,\n\t\t\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */,\n\t\t\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */,\n\t\t\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */,\n\t\t\t);\n\t\t\tname = Flutter;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146E51CF9000F007C117D = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9740EEB11CF90186004384FC /* Flutter */,\n\t\t\t\t97C146F01CF9000F007C117D /* Runner */,\n\t\t\t\t97C146EF1CF9000F007C117D /* Products */,\n\t\t\t\t38FEDA953939FFB3CD8B4370 /* Pods */,\n\t\t\t\tA3BD4893CCA84354F64352B2 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146EF1CF9000F007C117D /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146EE1CF9000F007C117D /* Runner.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F01CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FA1CF9000F007C117D /* Main.storyboard */,\n\t\t\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */,\n\t\t\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,\n\t\t\t\t97C147021CF9000F007C117D /* Info.plist */,\n\t\t\t\t97C146F11CF9000F007C117D /* Supporting Files */,\n\t\t\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,\n\t\t\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,\n\t\t\t\t74858FAE1ED2DC5600515810 /* AppDelegate.swift */,\n\t\t\t\t74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F11CF9000F007C117D /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tA3BD4893CCA84354F64352B2 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5951A49241F164BFC879FD8A /* Pods_Runner.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t97C146ED1CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF39B2611AF028A7ADB261525 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\t9740EEB61CF901F6004384FC /* Run Script */,\n\t\t\t\t97C146EA1CF9000F007C117D /* Sources */,\n\t\t\t\t97C146EB1CF9000F007C117D /* Frameworks */,\n\t\t\t\t97C146EC1CF9000F007C117D /* Resources */,\n\t\t\t\t9705A1C41CF9048500538489 /* Embed Frameworks */,\n\t\t\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */,\n\t\t\t\t5F1A0E9208832B656E3DB0F2 /* [CP] Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Runner;\n\t\t\tproductName = Runner;\n\t\t\tproductReference = 97C146EE1CF9000F007C117D /* Runner.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t97C146E61CF9000F007C117D /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1300;\n\t\t\t\tORGANIZATIONNAME = \"\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t97C146ED1CF9000F007C117D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t\tDevelopmentTeam = ZVZ337XL75;\n\t\t\t\t\t\tLastSwiftMigration = 1100;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 97C146E51CF9000F007C117D;\n\t\t\tproductRefGroup = 97C146EF1CF9000F007C117D /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t97C146ED1CF9000F007C117D /* Runner */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t97C146EC1CF9000F007C117D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,\n\t\t\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,\n\t\t\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Thin Binary\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" embed_and_thin\";\n\t\t};\n\t\t5F1A0E9208832B656E3DB0F2 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/HandyJSON/HandyJSON.framework\",\n\t\t\t\t\"${PODS_ROOT}/TXIMSDK_Plus_iOS_Bitcode/ImSDK_Plus.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/Toast/Toast.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/image_picker/image_picker.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/tencent_im_plugin/tencent_im_plugin.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/video_player/video_player.framework\",\n\t\t\t\t\"${BUILT_PRODUCTS_DIR}/video_thumbnail/video_thumbnail.framework\",\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HandyJSON.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ImSDK_Plus.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/tencent_im_plugin.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_player.framework\",\n\t\t\t\t\"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/video_thumbnail.framework\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t9740EEB61CF901F6004384FC /* Run Script */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" build\";\n\t\t};\n\t\tF39B2611AF028A7ADB261525 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t\t\"${PODS_PODFILE_DIR_PATH}/Podfile.lock\",\n\t\t\t\t\"${PODS_ROOT}/Manifest.lock\",\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"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\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t97C146EA1CF9000F007C117D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,\n\t\t\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t97C146FA1CF9000F007C117D /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FB1CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C147001CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t249021D3217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t249021D4217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Apple Development\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = YYHJZM64K7;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = top.huic.tencentImPluginExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t97C147031CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147041CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSUPPORTED_PLATFORMS = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t97C147061CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = ZVZ337XL75;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = top.huic.tencentImPluginExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147071CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = YYHJZM64K7;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = top.huic.tencentImPluginExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"Runner/Runner-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147031CF9000F007C117D /* Debug */,\n\t\t\t\t97C147041CF9000F007C117D /* Release */,\n\t\t\t\t249021D3217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147061CF9000F007C117D /* Debug */,\n\t\t\t\t97C147071CF9000F007C117D /* Release */,\n\t\t\t\t249021D4217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 97C146E61CF9000F007C117D /* Project object */;\n}\n"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1300\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n               BuildableName = \"Runner.app\"\n               BlueprintName = \"Runner\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Profile\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "example/ios/Runner.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "example/lib/main.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:tencent_im_plugin_example/page/chat.dart';\nimport 'package:tencent_im_plugin_example/page/home.dart';\nimport 'package:tencent_im_plugin_example/page/interfaces_test.dart';\nimport 'package:tencent_im_plugin_example/page/login.dart';\nimport 'package:tencent_im_plugin_example/page/main/main.dart';\n\nvoid main() => runApp(MyApp());\n\nclass MyApp extends StatefulWidget {\n  @override\n  _MyAppState createState() => _MyAppState();\n}\n\nclass _MyAppState extends State<MyApp> {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      debugShowCheckedModeBanner: false,\n      routes: {\n        \"/\": (context) => HomePage(),\n        \"/interfaces_test\": (context) => InterfacesTest(),\n        \"/login\": (context) => Login(),\n        \"/main\": (context) => Main(),\n        \"/chat\": (context) => Chat(),\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/chat.dart",
    "content": "import 'dart:io';\n\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/scheduler.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:flutter/material.dart';\nimport 'package:path_provider/path_provider.dart';\nimport 'package:tencent_im_plugin/entity/conversation_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_entity.dart';\nimport 'package:tencent_im_plugin/entity/user_entity.dart';\nimport 'package:tencent_im_plugin/entity/find_message_entity.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/text_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/custom_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/image_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/video_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/sound_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\nimport 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/image_type_enum.dart';\nimport 'package:image_picker/image_picker.dart';\nimport 'package:video_player/video_player.dart';\nimport 'package:video_thumbnail/video_thumbnail.dart';\nimport 'package:tencent_im_plugin/enums/message_status_enum.dart';\n\n/// 聊天页面\nclass Chat extends StatefulWidget {\n  @override\n  _ChatState createState() => _ChatState();\n}\n\nclass _ChatState extends State<Chat> {\n  /// 文本组件控制器\n  TextEditingController _textEditingController = TextEditingController();\n\n  /// 会话实体\n  ConversationEntity _conversation;\n\n  /// 消息列表\n  List<MessageEntity> _messages = [];\n\n  /// 用户信息\n  UserEntity _selfUser;\n\n  /// 临时目录\n  String _tempPath;\n\n  @override\n  void initState() {\n    super.initState();\n    TencentImPlugin.addListener(_imListener);\n    _loadTempPath();\n    SchedulerBinding.instance.addPostFrameCallback((_) {\n      _conversation = ModalRoute.of(context).settings.arguments;\n      this.setState(() {});\n      _loadUserInfo();\n      _onLoadMessages();\n      _textEditingController.text = _conversation.draftText;\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    TencentImPlugin.removeListener(_imListener);\n    String text = _textEditingController.text.trim();\n    TencentImPlugin.setConversationDraft(\n        conversationID: _conversation.conversationID,\n        draftText: text.trim() != '' ? text : null);\n  }\n\n  /// IM监听器\n  _imListener(type, params) {\n    if (type == TencentImListenerTypeEnum.NewMessage) {\n      this.setState(() {\n        this._messages.insert(0, params);\n      });\n    }\n\n    if (type == TencentImListenerTypeEnum.MessageSendProgress) {\n      print(\"===================\");\n      print(\"消息发送进度更新:${params.msgId}\");\n      print(\"===================\");\n    }\n\n    if (type == TencentImListenerTypeEnum.MessageSendSucc) {\n      print(\"===================\");\n      print(\"消息发送成功\");\n      print(\"===================\");\n    }\n\n    if (type == TencentImListenerTypeEnum.MessageSendFail) {\n      print(\"===================\");\n      print(\"消息发送失败\");\n      print(\"===================\");\n    }\n  }\n\n  /// 加载连目录\n  _loadTempPath() async {\n    _tempPath = (await getTemporaryDirectory()).path;\n    this.setState(() {});\n  }\n\n  /// 加载当前登录用户信息\n  _loadUserInfo() async {\n    this._selfUser = (await TencentImPlugin.getUsersInfo(\n        userIDList: [await TencentImPlugin.getLoginUser()]))[0];\n    this.setState(() {});\n  }\n\n  /// 加载消息\n  _onLoadMessages() async {\n    if (_conversation == null) {\n      return;\n    }\n    List<MessageEntity> messages = await (_conversation.groupID != null\n        ? TencentImPlugin.getGroupHistoryMessageList(\n            groupID: _conversation.groupID, count: 100)\n        : TencentImPlugin.getC2CHistoryMessageList(\n            userID: _conversation.userID, count: 100));\n    this.setState(() {\n      this._messages = messages;\n    });\n\n    // 下载语音、视频缩略图\n    for (var item in messages) {\n      if (item.elemType == MessageElemTypeEnum.Video) {\n        File file = new File(\n            _tempPath + \"/\" + (item.node as VideoMessageNode).snapshotUuid);\n        if (!file.existsSync()) {\n          TencentImPlugin.downloadVideoThumbnail(\n                  message: FindMessageEntity(msgId: item.msgID),\n                  path: file.path)\n              .then((value) {\n            this.setState(() {});\n          });\n        }\n      }\n\n      if (item.elemType == MessageElemTypeEnum.Sound) {\n        File file =\n            new File(_tempPath + \"/\" + (item.node as SoundMessageNode).uuid);\n        if (!file.existsSync()) {\n          TencentImPlugin.downloadSound(\n                  message: FindMessageEntity(msgId: item.msgID),\n                  path: file.path)\n              .then((value) {\n            this.setState(() {});\n          });\n        }\n      }\n    }\n\n    this.setState(() {});\n  }\n\n  /// 发送按钮点击事件\n  _onSend() async {\n    String text = _textEditingController.text;\n    if (text.trim() == '') {\n      return;\n    }\n    this._sendMessage(TextMessageNode(content: text, atUserList: []));\n    _textEditingController.text = \"\";\n  }\n\n  /// 图片选择按钮\n  _onImageSelect() async {\n    int value = await showCupertinoModalPopup<int>(\n      builder: (BuildContext context) => CupertinoActionSheet(\n        actions: <Widget>[\n          CupertinoActionSheetAction(\n            child: Text(\"图片\"),\n            onPressed: () => Navigator.pop(this.context, 0),\n          ),\n          CupertinoActionSheetAction(\n            child: Text(\"视频\"),\n            onPressed: () => Navigator.pop(this.context, 1),\n          ),\n        ],\n        cancelButton: CupertinoActionSheetAction(\n          child: Text(\"取消\"),\n          onPressed: () => Navigator.pop(this.context),\n        ), // 取消按钮\n      ),\n      context: context,\n    );\n\n    if (value == null) {\n      return;\n    }\n\n    // 图片\n    if (value == 0) {\n      final pickedFile =\n          await ImagePicker().getImage(source: ImageSource.gallery);\n      if (pickedFile == null) return;\n      this._sendMessage(ImageMessageNode(path: pickedFile.path));\n    }\n\n    // 视频\n    if (value == 1) {\n      final pickedFile =\n          await ImagePicker().getVideo(source: ImageSource.gallery);\n      if (pickedFile == null) return;\n\n      // 获得视频缩略图\n      String thumb = await VideoThumbnail.thumbnailFile(\n        video: pickedFile.path,\n        thumbnailPath: _tempPath,\n        imageFormat: ImageFormat.JPEG,\n        quality: 25,\n      );\n\n      // 获得控制器并获得视频时长\n      VideoPlayerController playerController =\n          VideoPlayerController.file(File(pickedFile.path));\n      await playerController.initialize();\n      int duration = playerController.value.duration.inSeconds;\n\n      this._sendMessage(VideoMessageNode(\n          duration: duration, snapshotPath: thumb, videoPath: pickedFile.path));\n    }\n  }\n\n  /// 根据消息获得组件\n  _getMessageComponent(MessageEntity message) {\n    // 文本消息\n    if (message.elemType == MessageElemTypeEnum.Text) {\n      return Text((message.node as TextMessageNode).content);\n    }\n\n    // 图片消息\n    if (message.elemType == MessageElemTypeEnum.Image) {\n      ImageMessageNode node = message.node;\n\n      if ((node.path == null || node.path == '') && node.imageData != null) {\n        return Container(\n          constraints: BoxConstraints(\n            maxHeight: 100,\n            maxWidth: 100,\n          ),\n          child: Image.network(node.imageData[ImageTypeEnum.Thumb]?.url),\n        );\n      }\n      return Container(\n        constraints: BoxConstraints(\n          maxHeight: 100,\n          maxWidth: 100,\n        ),\n        child: Image.file(File(node.path)),\n      );\n    }\n\n    // 视频消息\n    if (message.elemType == MessageElemTypeEnum.Video) {\n      VideoMessageNode node = message.node;\n      String path = node.snapshotPath == null || node.snapshotPath == ''\n          ? (_tempPath + \"/\" + node.snapshotUuid)\n          : node.snapshotPath;\n\n      return Container(\n        constraints: BoxConstraints(\n          maxHeight: 100,\n          maxWidth: 100,\n        ),\n        child: Image.file(File(path)),\n      );\n    }\n\n    if (message.elemType == MessageElemTypeEnum.Custom) {\n      CustomMessageNode node = message.node;\n      return Text(\"[自定义消息]data:${node.data}，desc:${node.desc}，ext:${node.ext}\");\n    }\n\n    return Text(\"暂不支持的数据格式\");\n  }\n\n  /// 发送消息\n  _sendMessage(MessageNode node) async {\n    String msgId = await TencentImPlugin.sendMessage(\n      node: node,\n      receiver: _conversation.userID,\n      groupID: _conversation.groupID,\n    );\n\n    this._messages.insert(\n          0,\n          MessageEntity(\n            msgID: msgId,\n            node: node,\n            faceUrl: _selfUser.faceUrl,\n            elemType: node.nodeType,\n            status: MessageStatusEnum.Sending,\n          ),\n        );\n\n    this.setState(() {});\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      backgroundColor: Colors.white,\n      appBar: AppBar(\n        title: Text(_conversation?.showName ?? \"加载中...\"),\n        centerTitle: true,\n        actions: [\n          _conversation == null\n              ? null\n              : IconButton(\n                  icon: Icon(_conversation.groupID != null\n                      ? Icons.supervisor_account\n                      : Icons.settings),\n                  onPressed: () => {},\n                ),\n          Container(width: 8),\n        ]..removeWhere((element) => element == null),\n      ),\n      body: Column(\n        children: [\n          Expanded(\n            child: Column(\n              children: [\n                Flexible(\n                  child: ListView(\n                    reverse: true,\n                    shrinkWrap: true,\n                    children: _messages\n                        .map(\n                          (item) => Padding(\n                            padding: const EdgeInsets.all(8.0),\n                            child: Container(\n                              child: Row(\n                                mainAxisAlignment: item.self\n                                    ? MainAxisAlignment.end\n                                    : MainAxisAlignment.start,\n                                children: [\n                                  Offstage(\n                                    child: Row(\n                                      children: [\n                                        CircleAvatar(\n                                          backgroundImage:\n                                              item.faceUrl == null ||\n                                                      item.faceUrl == ''\n                                                  ? null\n                                                  : NetworkImage(item.faceUrl),\n                                        ),\n                                        Container(width: 10),\n                                      ],\n                                    ),\n                                    offstage: item.self,\n                                  ),\n                                  _getMessageComponent(item),\n                                  Offstage(\n                                    child: Row(\n                                      children: [\n                                        Container(width: 10),\n                                        CircleAvatar(\n                                          backgroundImage:\n                                              item.faceUrl == null ||\n                                                      item.faceUrl == ''\n                                                  ? null\n                                                  : NetworkImage(item.faceUrl),\n                                        ),\n                                      ],\n                                    ),\n                                    offstage: !item.self,\n                                  ),\n                                ],\n                              ),\n                            ),\n                          ),\n                        )\n                        .toList(),\n                  ),\n                ),\n              ],\n            ),\n          ),\n          Container(\n            child: Padding(\n              padding: const EdgeInsets.all(8.0),\n              child: Row(\n                mainAxisAlignment: MainAxisAlignment.center,\n                crossAxisAlignment: CrossAxisAlignment.center,\n                children: [\n                  GestureDetector(\n                    onTap: _onImageSelect,\n                    child: Icon(\n                      Icons.image_outlined,\n                      size: 30,\n                    ),\n                  ),\n                  Container(width: 8),\n                  // GestureDetector(\n                  //   onTap: () {},\n                  //   child: Icon(\n                  //     Icons.mic,\n                  //     size: 30,\n                  //   ),\n                  // ),\n                  // Container(width: 8),\n                  Expanded(\n                    child: Container(\n                      constraints: BoxConstraints(\n                        maxHeight: 40,\n                      ),\n                      decoration: BoxDecoration(\n                        borderRadius: BorderRadius.all(Radius.circular(30)),\n                        color: Color(0xFFEEEEEE),\n                      ),\n                      child: TextField(\n                        controller: _textEditingController,\n                        decoration: InputDecoration(\n                          border: InputBorder.none,\n                          contentPadding: EdgeInsets.only(\n                            left: 15,\n                            top: -8,\n                            bottom: 0,\n                            right: 15,\n                          ),\n                        ),\n                      ),\n                    ),\n                  ),\n                  Container(width: 8),\n                  OutlinedButton(onPressed: _onSend, child: Text(\"发送\"))\n                ],\n              ),\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/home.dart",
    "content": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\n\nclass HomePage extends StatefulWidget {\n  @override\n  _HomePageState createState() => _HomePageState();\n}\n\nclass _HomePageState extends State<HomePage> {\n  @override\n  void initState() {\n    super.initState();\n    TencentImPlugin.initSDK(appid: '1400294314');\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: Text(\"页面导航\")),\n      body: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: [\n            OutlinedButton(\n              onPressed: () => Navigator.pushNamed(context, \"/interfaces_test\"),\n              child: Text(\"接口测试\"),\n            ),\n            OutlinedButton(\n              onPressed: () => Navigator.pushNamed(context, \"/login\"),\n              child: Text(\"进入Demo\"),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/interfaces_test.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin/utils/enum_util.dart';\nimport 'package:tencent_im_plugin/entity/group_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/signaling_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/user_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_add_application_entity.dart';\nimport 'package:tencent_im_plugin/message_node/text_message_node.dart';\nimport 'package:tencent_im_plugin/enums/signaling_action_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_member_role_enum.dart';\nimport 'package:tencent_im_plugin/enums/friend_type_enum.dart';\nimport 'package:logger/logger.dart';\n\ntypedef TestCallback = Future<dynamic> Function();\n\n/// 接口测试页面\nclass InterfacesTest extends StatefulWidget {\n  @override\n  _InterfacesTestState createState() => _InterfacesTestState();\n}\n\nclass _InterfacesTestState extends State<InterfacesTest> {\n  /// 日志输出\n  static Logger _logger = Logger();\n\n  /// 群ID\n  static String _groupId = \"@TGS#2HAKW7YGC\";\n\n  /// 直播群ID\n  static String _avGroupId = \"@TGS#aRXCQ7YGG\";\n\n  /// 好友ID\n  static String _friendId = \"test\";\n\n  /// 接口列表\n  Map<String, TestCallback> _interfaces = {\n    \"getLoginStatus\": () => TencentImPlugin.getLoginStatus(),\n    \"getLoginUser\": () => TencentImPlugin.getLoginUser(),\n    \"invite\": () => TencentImPlugin.invite(data: \"邀请你进行视频通话1\", invitee: _friendId),\n    \"inviteInGroup\": () => TencentImPlugin.inviteInGroup(data: \"邀请你进行视频通话2\", groupID: _groupId, inviteeList: [_friendId]),\n    \"cancel\": () async => TencentImPlugin.cancel(inviteID: await TencentImPlugin.invite(data: \"邀请你进行视频通话3\", invitee: _friendId), data: \"123\"),\n    \"accept\": () async => TencentImPlugin.accept(inviteID: await TencentImPlugin.invite(data: \"邀请你进行视频通话4\", invitee: _friendId), data: \"123\"),\n    \"reject\": () async => TencentImPlugin.reject(inviteID: await TencentImPlugin.invite(data: \"邀请你进行视频通话5\", invitee: _friendId), data: \"123\"),\n    // \"getSignalingInfo\": () async => TencentImPlugin.getSignalingInfo(inviteID: await TencentImPlugin.invite(data: \"邀请你进行视频通话\", invitee: _friendId), data: \"123\"),\n    \"addInvitedSignaling\": () async => TencentImPlugin.addInvitedSignaling(\n          info: SignalingInfoEntity(\n            inviter: _friendId,\n            data: \"test\",\n            actionType: SignalingActionTypeEnum.Invite,\n            inviteeList: [\"dev\"],\n          ),\n        ),\n    \"sendMessage\": () async => TencentImPlugin.sendMessage(receiver: _friendId, node: TextMessageNode(content: \"1433223\")),\n    // \"revokeMessage\": () async => TencentImPlugin.revokeMessage(receiver: \"dev\", node: TextMessageNode(content: \"1433223\")),\n    \"getC2CHistoryMessageList\": () async => TencentImPlugin.getC2CHistoryMessageList(userID: _friendId, count: 100),\n    \"getGroupHistoryMessageList\": () async => TencentImPlugin.getGroupHistoryMessageList(groupID: _groupId, count: 100),\n    \"markC2CMessageAsRead\": () async => TencentImPlugin.markC2CMessageAsRead(userID: _friendId),\n    \"markGroupMessageAsRead\": () async => TencentImPlugin.markGroupMessageAsRead(groupID: _groupId),\n    // \"deleteMessageFromLocalStorage\": () async => TencentImPlugin.deleteMessageFromLocalStorage(groupID: _groupId),\n    // \"deleteMessages\": () async => TencentImPlugin.deleteMessages(groupID: _groupId),\n    \"insertGroupMessageToLocalStorage\": () async => TencentImPlugin.insertGroupMessageToLocalStorage(\n          node: TextMessageNode(content: \"1433223\"),\n          groupID: _groupId,\n          sender: _friendId,\n        ),\n    // \"createGroup\": () async => TencentImPlugin.createGroup(\n    //       info: GroupInfoEntity(\n    //         groupType: GroupTypeEnum.Public,\n    //         groupName: \"测试群聊\",\n    //         notification: \"这是群公告\",\n    //         introduction: \"这是群简介\",\n    //       ),\n    //     ),\n    // \"joinGroup\": () async => TencentImPlugin.joinGroup(message: \"申请入群\", groupID: _groupId),\n    // \"quitGroup\": () async => TencentImPlugin.quitGroup(groupID: _groupId),\n    // \"dismissGroup\": () async => TencentImPlugin.dismissGroup(groupID: _groupId),\n    \"getJoinedGroupList\": () async => TencentImPlugin.getJoinedGroupList(),\n    \"getGroupsInfo\": () async => TencentImPlugin.getGroupsInfo(groupIDList: [_groupId]),\n    \"setGroupInfo\": () async => TencentImPlugin.setGroupInfo(\n          info: GroupInfoEntity(\n            groupID: _groupId,\n            groupName: \"${DateTime.now()}\",\n          ),\n        ),\n    \"searchGroups\": () async => TencentImPlugin.searchGroups(\n          keywordList: [\"1\", \"2\"],\n          isSearchGroupID: true,\n          isSearchGroupName: true,\n        ),\n    \"searchGroupMembers\": () async => TencentImPlugin.searchGroupMembers(\n          keywordList: [\"1\", \"2\"],\n          groupIDList: [_groupId],\n          isSearchMemberNameCard: true,\n          isSearchMemberUserID: true,\n          isSearchMemberRemark: true,\n          isSearchMemberNickName: true,\n        ),\n    \"setGroupReceiveMessageOpt\": () async => TencentImPlugin.setGroupReceiveMessageOpt(\n          groupID: _groupId,\n          opt: ReceiveMessageOptEnum.ReceiveAndNotify,\n        ),\n    \"setC2CReceiveMessageOpt\": () async => TencentImPlugin.setC2CReceiveMessageOpt(\n          ids: [_friendId],\n          opt: ReceiveMessageOptEnum.ReceiveAndNotify,\n        ),\n    \"getC2CReceiveMessageOpt\": () async => await TencentImPlugin.getC2CReceiveMessageOpt(ids: [_friendId]),\n    \"initGroupAttributes\": () async => TencentImPlugin.initGroupAttributes(\n          groupID: _avGroupId,\n          attributes: {\n            \"a\": \"1\",\n            \"b\": \"2\",\n          },\n        ),\n    \"setGroupAttributes\": () async => TencentImPlugin.setGroupAttributes(\n          groupID: _avGroupId,\n          attributes: {\n            \"c\": \"3\",\n            \"d\": \"4\",\n          },\n        ),\n    \"deleteGroupAttributes\": () async => TencentImPlugin.deleteGroupAttributes(groupID: _avGroupId, keys: [\"b\"]),\n    \"getGroupAttributes\": () async => TencentImPlugin.getGroupAttributes(groupID: _avGroupId),\n    \"getGroupMemberList\": () async => TencentImPlugin.getGroupMemberList(groupID: _groupId),\n    \"getGroupMembersInfo\": () async => TencentImPlugin.getGroupMembersInfo(groupID: _groupId, memberList: [_friendId]),\n    \"setGroupMemberInfo\": () async => TencentImPlugin.setGroupMemberInfo(\n          groupID: _groupId,\n          info: GroupMemberEntity(\n            userID: _friendId,\n            nameCard: \"测试群名片\",\n          ),\n        ),\n    \"muteGroupMember\": () async => TencentImPlugin.muteGroupMember(\n          groupID: _groupId,\n          seconds: 60,\n          userID: _friendId,\n        ),\n    // \"inviteUserToGroup\": () async => TencentImPlugin.inviteUserToGroup(\n    //       groupID: _groupId,\n    //       userList: [_friendId],\n    //     ),\n    // \"kickGroupMember\": () async => TencentImPlugin.kickGroupMember(\n    //       groupID: _groupId,\n    //       memberList: [_friendId],\n    //     ),\n    \"setGroupMemberRole\": () async => TencentImPlugin.setGroupMemberRole(\n          groupID: _groupId,\n          userID: _friendId,\n          role: GroupMemberRoleEnum.Admin,\n        ),\n    // \"transferGroupOwner\": () async => TencentImPlugin.transferGroupOwner(\n    //       groupID: _groupId,\n    //       userID: _friendId,\n    //     ),\n    // \"getGroupApplicationList\": () async => TencentImPlugin.getGroupApplicationList(),\n    // \"acceptGroupApplication\": () async => TencentImPlugin.acceptGroupApplication(),\n    // \"refuseGroupApplication\": () async => TencentImPlugin.refuseGroupApplication(),\n    \"setGroupApplicationRead\": () async => TencentImPlugin.setGroupApplicationRead(),\n    \"getConversationList\": () async => TencentImPlugin.getConversationList(),\n    \"getConversation\": () async => TencentImPlugin.getConversation(conversationID: (await TencentImPlugin.getConversationList()).conversationList[0].conversationID),\n    \"deleteConversation\": () async => TencentImPlugin.deleteConversation(conversationID: (await TencentImPlugin.getConversationList()).conversationList[0].conversationID),\n    \"setConversationDraft\": () async => TencentImPlugin.setConversationDraft(\n          conversationID: (await TencentImPlugin.getConversationList()).conversationList[0].conversationID,\n          draftText: \"测试会话草稿\",\n        ),\n    \"getUsersInfo\": () async => TencentImPlugin.getUsersInfo(userIDList: [_friendId]),\n    \"setSelfInfo\": () async => TencentImPlugin.setSelfInfo(info: UserEntity(nickName: \"${DateTime.now()}\")),\n    \"addToBlackList\": () async => TencentImPlugin.addToBlackList(userIDList: [_friendId]),\n    \"getBlackList\": () async => TencentImPlugin.getBlackList(),\n    \"deleteFromBlackList\": () async => TencentImPlugin.deleteFromBlackList(userIDList: [_friendId]),\n    \"setOfflinePushConfig\": () async => TencentImPlugin.setOfflinePushConfig(bussid: 10301, token: \"请输入您的Token\"),\n    \"setUnreadBadge\": () async => TencentImPlugin.setUnreadBadge(number: 10),\n    \"getFriendList\": () async => TencentImPlugin.getFriendList(),\n    \"getFriendsInfo\": () async => TencentImPlugin.getFriendsInfo(userIDList: [_friendId]),\n    \"setFriendInfo\": () async => TencentImPlugin.setFriendInfo(\n          info: FriendInfoEntity(\n            userID: _friendId,\n            friendRemark: \"这是测试备注\",\n          ),\n        ),\n    \"addFriend\": () async => TencentImPlugin.addFriend(\n          info: FriendAddApplicationEntity(\n            userID: _friendId,\n            friendRemark: \"这是测试备注\",\n            addWording: \"申请加为好友\",\n            addSource: \"手动查找\",\n            addType: FriendTypeEnum.Both,\n          ),\n        ),\n    \"deleteFromFriendList\": () async => TencentImPlugin.deleteFromFriendList(deleteType: FriendTypeEnum.Both, userIDList: [_friendId]),\n    \"checkFriend\": () async => TencentImPlugin.checkFriend(userID: _friendId, checkType: FriendTypeEnum.Both),\n    \"getFriendApplicationList\": () async => TencentImPlugin.getFriendApplicationList(),\n    // \"acceptFriendApplication\": () async => TencentImPlugin.acceptFriendApplication(),\n    // \"refuseFriendApplication\": () async => TencentImPlugin.refuseFriendApplication(),\n    // \"deleteFriendApplication\": () async => TencentImPlugin.deleteFriendApplication(),\n    \"setFriendApplicationRead\": () async => TencentImPlugin.setFriendApplicationRead(),\n    \"createFriendGroup\": () async => TencentImPlugin.createFriendGroup(userIDList: [_friendId], groupName: \"测试分组\"),\n    \"getFriendGroups\": () async => TencentImPlugin.getFriendGroups(groupNameList: [\"测试分组\"]),\n    \"renameFriendGroup\": () async => TencentImPlugin.renameFriendGroup(oldName: \"测试分组\", newName: \"test\"),\n    \"addFriendsToFriendGroup\": () async => TencentImPlugin.addFriendsToFriendGroup(groupName: \"test\", userIDList: [_friendId]),\n    \"deleteFriendsFromFriendGroup\": () async => TencentImPlugin.deleteFriendsFromFriendGroup(groupName: \"test\", userIDList: [_friendId]),\n    \"deleteFriendGroup\": () async => TencentImPlugin.deleteFriendGroup(groupNameList: [\"test\"]),\n  };\n\n  /// 当前正在测试的Key\n  String _currentTestKey;\n\n  /// 已测试数量\n  int _finishTestCount = 0;\n\n  /// 未通过接口列表\n  List<String> _failInterfaces = [];\n\n  /// 是否开始测试\n  bool _start = false;\n\n  /// 测试结果描述\n  List<String> _result = [];\n\n  /// 回调描述\n  List<String> _callResult = [];\n\n  @override\n  void initState() {\n    super.initState();\n    TencentImPlugin.addListener(_listener);\n    TencentImPlugin.login(\n      userID: \"dev\",\n      userSig: \"eJwtzEELgjAYxvHvsnPIu7U5EzoEQRDWITWqW7KVr8MaS8Yi*u6Zenx*D-w-pMjyyGtHUsIiILNho9KPDm84sNJ*4pcyV2tRkZRyALbgc8rHRweLTvcuhGAAMGqH7d9iEAKSWMipgve*ulZS1vKoT83uXO6rkAWzaoqtgVAdNpecu9Y-38aXtE6W5PsDr9ExPw__\",\n    );\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    TencentImPlugin.removeListener(_listener);\n    TencentImPlugin.logout();\n  }\n\n  /// 监听器对象\n  _listener(type, params) {\n    _callResult.add(\"${_getDateTime()}-[${EnumUtil.getEnumName(type)}]:$params\");\n    if (this.mounted) {\n      this.setState(() {});\n    }\n  }\n\n  /// 获得时间字符串\n  _getDateTime() {\n    DateTime dateTime = DateTime.now();\n    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}\";\n  }\n\n  /// 开始测试\n  startTest() async {\n    this.setState(() => _start = true);\n\n    for (var key in _interfaces.keys) {\n      this.setState(() => _currentTestKey = key);\n      try {\n        var resultData = await _interfaces[key]();\n        _result.add(\"${_getDateTime()}-[$key]:测试通过；结果:$resultData\");\n      } catch (err) {\n        _failInterfaces.add(\"$key : $err\");\n        _result.add(\"${_getDateTime()}-[$key]:$err\");\n        _logger.e(err, \"[测试结果出错] $key\");\n      }\n      this.setState(() => _finishTestCount += 1);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: Text(\"接口测试列表\")),\n      body: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Column(\n          children: [\n            RichText(\n              text: TextSpan(\n                text: \"接口数量:${_interfaces.length}\",\n                style: TextStyle(color: Colors.black),\n                children: [\n                  TextSpan(text: \"，已通过:\"),\n                  TextSpan(text: \"${_finishTestCount - _failInterfaces.length}\", style: TextStyle(color: Colors.green)),\n                  TextSpan(text: \"，未通过:\"),\n                  TextSpan(text: \"${_failInterfaces.length}\", style: TextStyle(color: Colors.red)),\n                ],\n              ),\n            ),\n            _start\n                ? Text((_finishTestCount == _interfaces.length) ? \"测试完成\" : \"正在测试:$_currentTestKey\")\n                : OutlinedButton(\n                    onPressed: startTest,\n                    child: Text(\"开始测试\"),\n                  ),\n            Divider(),\n            Text(\"日志信息\"),\n            Expanded(\n                child: ListView(\n              children: _result\n                  .map(\n                    (e) => RichText(\n                      text: TextSpan(\n                        text: e,\n                        style: TextStyle(color: e.contains(\"测试通过\") ? Colors.green : Colors.red),\n                      ),\n                    ),\n                  )\n                  .toList(),\n            )),\n            Divider(),\n            Text(\"回调信息\"),\n            Expanded(\n                child: ListView(\n              children: _callResult\n                  .map(\n                    (e) => Text(e),\n                  )\n                  .toList(),\n            )),\n          ],\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/login.dart",
    "content": "import 'package:flutter/widgets.dart';\nimport 'package:flutter/material.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin_example/utils/GenerateTestUserSig.dart';\n\n/// 登录页面\nclass Login extends StatefulWidget {\n  @override\n  _LoginState createState() => _LoginState();\n}\n\nclass _LoginState extends State<Login> {\n  TextEditingController _controller = TextEditingController();\n\n  /// 用户名\n  String _userName = \"dev\";\n\n  @override\n  void initState() {\n    super.initState();\n    _controller.text = _userName;\n  }\n\n  /// 登录按钮点击事件\n  _onLogin() async {\n    String sign = GenerateTestUserSig(\n      sdkappid: 1400294314,\n      key: \"706da51f9280812611bcc80b5182b1c5554db8d053bc00b8a37ae8cba887f6a7\",\n    ).genSig(identifier: _userName, expire: 1 * 60 * 1000);\n\n    await TencentImPlugin.login(\n      userID: _userName,\n      userSig: sign,\n    );\n\n    Navigator.pushNamedAndRemoveUntil(\n        context, \"/main\", (Route<dynamic> route) => false);\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\"登录页面\"),\n      ),\n      body: Padding(\n        padding: const EdgeInsets.all(8.0),\n        child: Center(\n          child: Column(\n            mainAxisAlignment: MainAxisAlignment.center,\n            children: [\n              TextField(\n                decoration: InputDecoration(hintText: \"请输入用户名\"),\n                textAlign: TextAlign.center,\n                onChanged: (value) => this.setState(() => _userName = value),\n                controller: _controller,\n              ),\n              Container(height: 20),\n              OutlinedButton(\n                onPressed: _userName.trim() == '' ? null : _onLogin,\n                child: Text(\"立即登录\"),\n              ),\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/main/components/conversation.dart",
    "content": "import 'package:flutter/scheduler.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:flutter/material.dart';\nimport 'package:tencent_im_plugin/entity/conversation_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/conversation_entity.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart';\n\n/// 会话页面\nclass Conversation extends StatefulWidget {\n  @override\n  _ConversationState createState() => _ConversationState();\n}\n\nclass _ConversationState extends State<Conversation> {\n  /// 刷新指示器Key\n  GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey();\n\n  /// 会话结果对象\n  ConversationResultEntity _data;\n\n  @override\n  void initState() {\n    super.initState();\n    TencentImPlugin.addListener(_imListener);\n\n    SchedulerBinding.instance.addPostFrameCallback((_) {\n      _refreshIndicatorKey.currentState.show();\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    TencentImPlugin.removeListener(_imListener);\n  }\n\n  /// IM监听器\n  _imListener(type, params) {\n    if (type == TencentImListenerTypeEnum.ConversationChanged) {\n      _onRefresh();\n    }\n  }\n\n  /// 刷新事件\n  Future<dynamic> _onRefresh() {\n    return TencentImPlugin.getConversationList().then((value) {\n      this.setState(() => _data = value);\n    });\n  }\n\n  /// 会话点击事件\n  _onConversationClick(ConversationEntity data) {\n    Navigator.pushNamed(context, \"/chat\", arguments: data);\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return RefreshIndicator(\n      key: _refreshIndicatorKey,\n      onRefresh: _onRefresh,\n      child: ListView(\n        children: ListTile.divideTiles(\n          context: context,\n          tiles: _data?.conversationList == null\n              ? []\n              : _data.conversationList\n                  .map(\n                    (item) => ListTile(\n                      onTap: () => _onConversationClick(item),\n                      leading: CircleAvatar(\n                          backgroundImage:\n                              item.faceUrl == null || item.faceUrl == ''\n                                  ? null\n                                  : NetworkImage(item.faceUrl)),\n                      title: RichText(\n                        text: TextSpan(\n                          children: [\n                            TextSpan(\n                                text:\n                                    \"[${item.groupID == null ? \"私聊\" : \"群聊\"}] \",\n                                style: TextStyle(color: Colors.grey)),\n                            TextSpan(text: item.showName),\n                          ],\n                          style: TextStyle(color: Colors.black),\n                        ),\n                      ),\n                      subtitle: RichText(\n                        text: TextSpan(\n                          children: [\n                            TextSpan(\n                                text: item.draftText == null ? \"\" : \"[草稿]\",\n                                style: TextStyle(color: Colors.red)),\n                            TextSpan(\n                              text: item.draftText ??\n                                  item.lastMessage?.note ??\n                                  \"\",\n                            ),\n                          ],\n                          style: TextStyle(color: Colors.black),\n                        ),\n                      ),\n                    ),\n                  )\n                  .toList(),\n        ).toList(),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/main/components/friend.dart",
    "content": "import 'package:flutter/scheduler.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_entity.dart';\nimport 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/friend_application_agree_type_enum.dart';\nimport 'package:tencent_im_plugin/entity/friend_application_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/find_friend_application_entity.dart';\n\n/// 好友页面\nclass Friend extends StatefulWidget {\n  @override\n  _FriendState createState() => _FriendState();\n}\n\nclass _FriendState extends State<Friend> {\n  /// 刷新指示器Key\n  GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey();\n\n  /// 数据结果对象\n  List<FriendInfoEntity> _data = [];\n\n  @override\n  void initState() {\n    super.initState();\n    TencentImPlugin.addListener(_imListener);\n\n    SchedulerBinding.instance.addPostFrameCallback((_) {\n      _refreshIndicatorKey.currentState.show();\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    TencentImPlugin.removeListener(_imListener);\n  }\n\n  /// IM监听器\n  _imListener(type, params) {\n    if (type == TencentImListenerTypeEnum.FriendListAdded) {\n      this.setState(() {});\n    }\n  }\n\n  /// 刷新事件\n  Future<dynamic> _onRefresh() {\n    return TencentImPlugin.getFriendList().then((value) => this.setState(() => _data = value));\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return RefreshIndicator(\n      key: _refreshIndicatorKey,\n      onRefresh: _onRefresh,\n      child: Column(\n        children: [\n          Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text(\"好友申请列表\"))),\n          SingleChildScrollView(\n            child: FutureBuilder(\n              future: TencentImPlugin.getFriendApplicationList(),\n              builder: (BuildContext context, AsyncSnapshot<FriendApplicationResultEntity> snapshot) {\n                if (snapshot.connectionState != ConnectionState.done) return Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text(\"正在拉取好友申请列表\")));\n                if (snapshot.data.friendApplicationList.length == 0) return Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text(\"暂无待处理好友申请\")));\n                return Column(\n                  children: ListTile.divideTiles(\n                    context: context,\n                    tiles: snapshot.data.friendApplicationList\n                        .map(\n                          (item) => ListTile(\n                            title: Row(\n                              children: [\n                                Expanded(\n                                  child: RichText(\n                                    text: TextSpan(\n                                      children: [\n                                        TextSpan(text: item.nickname == null || item.nickname == '' ? item.userID : item.nickname),\n                                      ],\n                                      style: TextStyle(color: Colors.black),\n                                    ),\n                                  ),\n                                ),\n                                Row(\n                                  children: [\n                                    RaisedButton(\n                                      onPressed: () async {\n                                        Future result = TencentImPlugin.acceptFriendApplication(application: FindFriendApplicationEntity.fromFriendApplicationEntity(item), responseType: FriendApplicationAgreeTypeEnum.AgreeAndAdd);\n                                        await result.then((value) => Fluttertoast.showToast(msg: \"处理成功!\")).catchError((e) => Fluttertoast.showToast(msg: \"处理失败!\"));\n                                        if (this.mounted) this.setState(() {});\n                                      },\n                                      child: Text(\"同意\"),\n                                    ),\n                                    RaisedButton(\n                                      onPressed: () async {\n                                        Future result = TencentImPlugin.refuseFriendApplication(application: FindFriendApplicationEntity.fromFriendApplicationEntity(item));\n                                        await result.then((value) => Fluttertoast.showToast(msg: \"处理成功!\")).catchError((e) => Fluttertoast.showToast(msg: \"处理失败!\"));\n                                        if (this.mounted) this.setState(() {});\n                                      },\n                                      child: Text(\"拒绝\"),\n                                    ),\n                                  ],\n                                ),\n                              ],\n                            ),\n                          ),\n                        )\n                        .toList(),\n                  ).toList(),\n                );\n              },\n            ),\n          ),\n          Center(child: Padding(padding: const EdgeInsets.all(20.0), child: Text(\"好友列表\"))),\n          Expanded(\n            child: ListView(\n              children: ListTile.divideTiles(\n                context: context,\n                tiles: _data\n                    .map(\n                      (item) => ListTile(\n                        leading: CircleAvatar(backgroundImage: item.userProfile?.faceUrl == null || item.userProfile.faceUrl == '' ? null : NetworkImage(item.userProfile.faceUrl)),\n                        title: RichText(\n                          text: TextSpan(\n                            children: [\n                              TextSpan(text: item.userProfile.nickName == null || item.userProfile.nickName == '' ? item.userID : item.userProfile.nickName),\n                            ],\n                            style: TextStyle(color: Colors.black),\n                          ),\n                        ),\n                      ),\n                    )\n                    .toList(),\n              ).toList(),\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/main/components/group.dart",
    "content": "import 'package:flutter/scheduler.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:flutter/material.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin/entity/group_info_entity.dart';\n\n/// 群组列表\nclass Group extends StatefulWidget {\n  @override\n  _GroupState createState() => _GroupState();\n}\n\nclass _GroupState extends State<Group> {\n  /// 刷新指示器Key\n  GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey();\n\n  /// 数据结果对象\n  List<GroupInfoEntity> _data = [];\n\n  @override\n  void initState() {\n    super.initState();\n    TencentImPlugin.addListener(_imListener);\n\n    SchedulerBinding.instance.addPostFrameCallback((_) {\n      _refreshIndicatorKey.currentState.show();\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    TencentImPlugin.removeListener(_imListener);\n  }\n\n  /// IM监听器\n  _imListener(type, params) {}\n\n  /// 刷新事件\n  Future<dynamic> _onRefresh() {\n    return TencentImPlugin.getJoinedGroupList()\n        .then((value) => this.setState(() => _data = value));\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return RefreshIndicator(\n      key: _refreshIndicatorKey,\n      onRefresh: _onRefresh,\n      child: ListView(\n        children: ListTile.divideTiles(\n          context: context,\n          tiles: _data\n              .map(\n                (item) => ListTile(\n                  leading: CircleAvatar(\n                      backgroundImage:\n                          item.faceUrl == null || item.faceUrl == ''\n                              ? null\n                              : NetworkImage(item.faceUrl)),\n                  title: RichText(\n                    text: TextSpan(\n                      children: [\n                        TextSpan(text: \"${item.groupName}\"),\n                      ],\n                      style: TextStyle(color: Colors.black),\n                    ),\n                  ),\n                  subtitle: Text(item.introduction ?? \"\"),\n                ),\n              )\n              .toList(),\n        ).toList(),\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/page/main/main.dart",
    "content": "import 'package:flutter/widgets.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:tencent_im_plugin_example/page/main/components/conversation.dart';\nimport 'package:tencent_im_plugin_example/page/main/components/friend.dart';\nimport 'package:tencent_im_plugin_example/page/main/components/group.dart';\nimport 'package:tencent_im_plugin/tencent_im_plugin.dart';\nimport 'package:tencent_im_plugin/entity/group_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_add_application_entity.dart';\nimport 'package:tencent_im_plugin/enums/group_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/friend_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/text_message_node.dart';\n\n/// 用户主页\nclass Main extends StatefulWidget {\n  @override\n  _MainState createState() => _MainState();\n}\n\nclass _MainState extends State<Main> {\n  /// 当前页面下标\n  int _index = 0;\n\n  /// 页面控制器\n  PageController _pageController = PageController();\n\n  @override\n  void initState() {\n    super.initState();\n  }\n\n  /// 页面改变事件\n  _onPageChange(index) {\n    _pageController.jumpToPage(index);\n    this.setState(() {\n      _index = index;\n    });\n  }\n\n  /// 菜单点击事件\n  _onMenuClick(int value) async {\n    if (value == 0) {\n      this._startConversation();\n    } else if (value == 1) {\n      this._startGroupChat();\n    } else if (value == 2) {\n      this._startAddFriend();\n    }\n  }\n\n  /// 发起会话\n  void _startConversation() async {\n    String text = \"\";\n    var result = await this._showDialog(\n      \"发起会话\",\n      TextField(\n        onChanged: (_text) => text = _text,\n        decoration: InputDecoration(hintText: \"请输入用户ID\"),\n      ),\n    );\n\n    // 执行操作\n    if (result && text.trim() != '') {\n      TencentImPlugin.sendMessage(node: TextMessageNode(content: \"发起对话\"), receiver: text);\n    }\n  }\n\n  /// 开启群聊\n  void _startGroupChat() async {\n    String text = \"\";\n    GroupTypeEnum type;\n    var result = await this._showDialog(\n      \"创建群聊\",\n      Column(\n        children: [\n          TextField(\n            onChanged: (_text) => text = _text,\n            decoration: InputDecoration(hintText: \"请输入群名称\"),\n          ),\n          GroupSelect(title: \"群类型\", values: GroupTypeEnum.values, onChanged: (newType) => type = newType),\n        ],\n      ),\n    );\n\n    if (result && text != '' && type != null) {\n      String id = await TencentImPlugin.createGroup(info: GroupInfoEntity.create(groupName: text, groupType: type));\n      Fluttertoast.showToast(msg: \"群聊创建成功，群ID:$id\");\n    }\n  }\n\n  /// 添加好友\n  void _startAddFriend() async {\n    String text = \"\";\n    var result = await this._showDialog(\n      \"添加好友\",\n      TextField(\n        onChanged: (_text) => text = _text,\n        decoration: InputDecoration(hintText: \"请输入用户ID\"),\n      ),\n    );\n\n    // 执行操作\n    if (result && text.trim() != '') {\n      TencentImPlugin.addFriend(info: FriendAddApplicationEntity(userID: text, addType: FriendTypeEnum.Both)).then((res) {\n        Fluttertoast.showToast(msg: \"好友申请发送成功!\");\n      }).catchError((e) {\n        Fluttertoast.showToast(msg: \"好友申请发送失败!\");\n      });\n    }\n  }\n\n  /// 显示对话框\n  /// [title] 标题\n  /// [child] 内容\n  Future<bool> _showDialog(String title, Widget child) {\n    return showDialog(\n      context: context,\n      builder: (BuildContext context) => AlertDialog(\n        title: Text(title),\n        content: child,\n        actions: [\n          OutlinedButton(\n            child: Text(\"取消\"),\n            onPressed: () => Navigator.pop(context, false),\n          ),\n          OutlinedButton(\n            child: Text(\"确定\"),\n            onPressed: () => Navigator.pop(context, true),\n          ),\n        ],\n      ),\n    );\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\"主页\"),\n        actions: [\n          PopupMenuButton<int>(\n            onSelected: _onMenuClick,\n            itemBuilder: (BuildContext context) => <PopupMenuEntry<int>>[\n              PopupMenuItem(\n                child: Row(\n                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n                  children: <Widget>[Text('发起对话')],\n                ),\n                value: 0,\n              ),\n              PopupMenuItem(\n                child: Row(\n                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n                  children: <Widget>[Text('创建群聊')],\n                ),\n                value: 1,\n              ),\n              PopupMenuItem(\n                child: Row(\n                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n                  children: <Widget>[Text('添加好友')],\n                ),\n                value: 2,\n              ),\n            ],\n          ),\n        ],\n      ),\n      body: Column(\n        children: [\n          Expanded(\n            child: PageView(\n              onPageChanged: _onPageChange,\n              controller: _pageController,\n              children: [\n                Conversation(),\n                Group(),\n                Friend(),\n              ],\n            ),\n          ),\n          BottomNavigationBar(\n            currentIndex: _index,\n            items: [\n              BottomNavigationBarItem(icon: Icon(Icons.message), label: \"会话\"),\n              BottomNavigationBarItem(icon: Icon(Icons.supervisor_account), label: \"群组\"),\n              BottomNavigationBarItem(icon: Icon(Icons.account_box), label: \"好友\"),\n            ],\n            onTap: _onPageChange,\n          ),\n        ],\n      ),\n    );\n  }\n}\n\n/// 组选择\nclass GroupSelect<T> extends StatefulWidget {\n  /// 标签\n  final String title;\n\n  /// 值列表\n  final List<T> values;\n\n  /// 改变事件\n  final ValueChanged<T> onChanged;\n\n  const GroupSelect({\n    Key key,\n    @required this.title,\n    @required this.values,\n    @required this.onChanged,\n  }) : super(key: key);\n\n  @override\n  _GroupSelectState createState() => _GroupSelectState<T>();\n}\n\nclass _GroupSelectState<T> extends State<GroupSelect> {\n  /// 当前选择值\n  T _value;\n\n  @override\n  Widget build(BuildContext context) {\n    return DropdownButton(\n      hint: Text(widget.title),\n      items: List.generate(\n        widget.values.length,\n        (index) {\n          T item = widget.values[index];\n          return DropdownMenuItem(\n            value: item,\n            child: Text(\"${item.toString()}\"),\n          );\n        },\n      ),\n      value: _value,\n      elevation: 1,\n      onChanged: (newType) {\n        if (widget.onChanged != null) widget.onChanged(newType);\n        this._value = newType;\n        if (this.mounted) this.setState(() {});\n      },\n    );\n  }\n}\n"
  },
  {
    "path": "example/lib/utils/GenerateTestUserSig.dart",
    "content": "library generate_test_im_usersig;\n\nimport 'dart:convert';\nimport 'dart:io';\n\nimport 'package:crypto/crypto.dart';\nimport 'package:flutter/material.dart';\n\n///生成腾讯云即时通信测试用userSig\n///\nclass GenerateTestUserSig {\n  GenerateTestUserSig({@required this.sdkappid, @required this.key});\n  int sdkappid;\n  String key;\n\n  ///生成UserSig\n  String genSig({\n    @required String identifier,\n    @required int expire,\n    List<int> userBuf,\n  }) {\n    int currTime = _getCurrentTime();\n    String sig = '';\n    Map<String, dynamic> sigDoc = new Map<String, dynamic>();\n    sigDoc.addAll({\n      \"TLS.ver\": \"2.0\",\n      \"TLS.identifier\": identifier,\n      \"TLS.sdkappid\": this.sdkappid,\n      \"TLS.expire\": expire,\n      \"TLS.time\": currTime,\n    });\n\n    sig = _hmacsha256(\n      identifier: identifier,\n      currTime: currTime,\n      expire: expire,\n    );\n    sigDoc['TLS.sig'] = sig;\n    String jsonStr = json.encode(sigDoc);\n    List<int> compress = zlib.encode(utf8.encode(jsonStr));\n    return _escape(content: base64.encode(compress));\n  }\n\n  int _getCurrentTime() {\n    return (new DateTime.now().millisecondsSinceEpoch / 1000).floor();\n  }\n\n  String _hmacsha256({\n    @required String identifier,\n    @required int currTime,\n    @required int expire,\n  }) {\n    int sdkappid = this.sdkappid;\n    String contentToBeSigned =\n        \"TLS.identifier:$identifier\\nTLS.sdkappid:$sdkappid\\nTLS.time:$currTime\\nTLS.expire:$expire\\n\";\n    Hmac hmacSha256 = new Hmac(sha256, utf8.encode(this.key));\n    Digest hmacSha256Digest =\n        hmacSha256.convert(utf8.encode(contentToBeSigned));\n    return base64.encode(hmacSha256Digest.bytes);\n  }\n\n  String _escape({\n    @required String content,\n  }) {\n    return content\n        .replaceAll('\\+', '*')\n        .replaceAll('\\/', '-')\n        .replaceAll('=', '_');\n  }\n}\n"
  },
  {
    "path": "example/pubspec.yaml",
    "content": "name: tencent_im_plugin_example\ndescription: Demonstrates how to use the tencent_im_plugin plugin.\npublish_to: 'none'\n\nenvironment:\n  sdk: \">=2.1.0 <3.0.0\"\n\ndependencies:\n  flutter:\n    sdk: flutter\n\n  # The following adds the Cupertino Icons font to your application.\n  # Use with the CupertinoIcons class for iOS style icons.\n  cupertino_icons: ^1.0.2\n  # 图片选择(https://pub.dev/packages/image_picker)\n  image_picker: ^0.7.4\n  # 视频缩略图获取(https://pub.dev/packages/video_thumbnail)\n  video_thumbnail: ^0.3.3\n  # 路径管理(https://pub.dev/packages/path_provider)\n  path_provider: ^2.0.1\n  # 视频播放器和信息获取(https://pub.flutter-io.cn/packages/video_player)\n  video_player: ^2.1.1\n  # 群提示\n  fluttertoast: ^8.0.7\n\ndev_dependencies:\n  platform: ^3.1.0\n\n  flutter_test:\n    sdk: flutter\n\n  tencent_im_plugin:\n    path: ../\n\n# For information on the generic Dart part of this file, see the\n# following page: https://dart.dev/tools/pub/pubspec\n\n# The following section is specific to Flutter.\nflutter:\n\n  # The following line ensures that the Material Icons font is\n  # included with your application, so that you can use the icons in\n  # the material Icons class.\n  uses-material-design: true\n\n  # To add assets to your application, add an assets section, like this:\n  # assets:\n  #  - images/a_dot_burr.jpeg\n  #  - images/a_dot_ham.jpeg\n\n  # An image asset can refer to one or more resolution-specific \"variants\", see\n  # https://flutter.dev/assets-and-images/#resolution-aware.\n\n  # For details regarding adding assets from package dependencies, see\n  # https://flutter.dev/assets-and-images/#from-packages\n\n  # To add custom fonts to your application, add a fonts section here,\n  # in this \"flutter\" section. Each entry in this list should have a\n  # \"family\" key with the font family name, and a \"fonts\" key with a\n  # list giving the asset and other descriptors for the font. For\n  # example:\n  # fonts:\n  #   - family: Schyler\n  #     fonts:\n  #       - asset: fonts/Schyler-Regular.ttf\n  #       - asset: fonts/Schyler-Italic.ttf\n  #         style: italic\n  #   - family: Trajan Pro\n  #     fonts:\n  #       - asset: fonts/TrajanPro.ttf\n  #       - asset: fonts/TrajanPro_Bold.ttf\n  #         weight: 700\n  #\n  # For details regarding fonts from package dependencies,\n  # see https://flutter.dev/custom-fonts/#from-packages\n"
  },
  {
    "path": "example/test/widget_test.dart",
    "content": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester\n// utility that Flutter provides. For example, you can send tap and scroll\n// gestures. You can also use WidgetTester to find child widgets in the widget\n// tree, read text, and verify that the values of widget properties are correct.\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nimport 'package:tencent_im_plugin_example/main.dart';\n\nvoid main() {\n  testWidgets('Verify Platform version', (WidgetTester tester) async {\n    // Build our app and trigger a frame.\n    await tester.pumpWidget(MyApp());\n\n    // Verify that platform version is retrieved.\n    expect(\n      find.byWidgetPredicate(\n        (Widget widget) =>\n            widget is Text && widget.data.startsWith('Running on:'),\n      ),\n      findsOneWidget,\n    );\n  });\n}\n"
  },
  {
    "path": "ios/.gitignore",
    "content": ".idea/\n.vagrant/\n.sconsign.dblite\n.svn/\n\n.DS_Store\n*.swp\nprofile\n\nDerivedData/\nbuild/\nGeneratedPluginRegistrant.h\nGeneratedPluginRegistrant.m\n\n.generated/\n\n*.pbxuser\n*.mode1v3\n*.mode2v3\n*.perspectivev3\n\n!default.pbxuser\n!default.mode1v3\n!default.mode2v3\n!default.perspectivev3\n\nxcuserdata\n\n*.moved-aside\n\n*.pyc\n*sync/\nIcon?\n.tags*\n\n/Flutter/Generated.xcconfig\n/Flutter/flutter_export_environment.sh"
  },
  {
    "path": "ios/Assets/.gitkeep",
    "content": ""
  },
  {
    "path": "ios/Classes/SwiftTencentImPlugin.swift",
    "content": "import Flutter\nimport UIKit\nimport HandyJSON\nimport ImSDK_Plus\n\npublic class SwiftTencentImPlugin: NSObject, FlutterPlugin {\n    public static var channel: FlutterMethodChannel?;\n\n    /* 下面是监听器列表，由于局部变量的监听器对象不会触发，所以提取为全局对象 */\n    /// SDK 监听器\n    private var customSdkListener = CustomSDKListener();\n\n    /// 消息监听器\n    private var customAdvancedMsgListener = CustomAdvancedMsgListener();\n\n    /// 会话监听器\n    private var customConversationListener = CustomConversationListener();\n\n    /// 群组监听器\n    private var customGroupListener = CustomGroupListener();\n\n    /// 关系链相关监听器\n    private var customFriendshipListener = CustomFriendshipListener();\n\n    /// 信令监听器\n    private var customSignalingListener = CustomSignalingListener();\n\n    /// Apns离线推送监听器\n    private var customAPNSListener = CustomAPNSListener();\n\n    public static func register(with registrar: FlutterPluginRegistrar) {\n        let channel = FlutterMethodChannel(name: \"tencent_im_plugin\", binaryMessenger: registrar.messenger())\n        let instance = SwiftTencentImPlugin()\n        SwiftTencentImPlugin.channel = channel;\n        registrar.addMethodCallDelegate(instance, channel: channel)\n    }\n\n    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {\n        switch call.method {\n        case \"initSDK\":\n            self.`initSDK`(call: call, result: result)\n            break\n        case \"unInitSDK\":\n            self.unInitSDK(call: call, result: result)\n            break\n        case \"getVersion\":\n            self.getVersion(call: call, result: result)\n            break\n        case \"getServerTime\":\n            self.getServerTime(call: call, result: result)\n            break\n        case \"login\":\n            self.login(call: call, result: result)\n            break\n        case \"logout\":\n            self.logout(call: call, result: result)\n            break\n        case \"getLoginStatus\":\n            self.getLoginStatus(call: call, result: result)\n            break\n        case \"getLoginUser\":\n            self.getLoginUser(call: call, result: result)\n            break\n        case \"invite\":\n            self.invite(call: call, result: result)\n            break\n        case \"inviteInGroup\":\n            self.inviteInGroup(call: call, result: result)\n            break\n        case \"cancel\":\n            self.cancel(call: call, result: result)\n            break\n        case \"accept\":\n            self.accept(call: call, result: result)\n            break\n        case \"reject\":\n            self.reject(call: call, result: result)\n            break\n        case \"getSignalingInfo\":\n            self.getSignalingInfo(call: call, result: result)\n            break\n        case \"addInvitedSignaling\":\n            self.addInvitedSignaling(call: call, result: result)\n            break\n        case \"sendMessage\":\n            self.sendMessage(call: call, result: result);\n            break;\n        case \"resendMessage\":\n            self.resendMessage(call: call, result: result);\n            break;\n        case \"revokeMessage\":\n            self.revokeMessage(call: call, result: result);\n            break;\n        case \"getC2CHistoryMessageList\":\n            self.getC2CHistoryMessageList(call: call, result: result);\n            break;\n        case \"getGroupHistoryMessageList\":\n            self.getGroupHistoryMessageList(call: call, result: result);\n            break;\n        case \"getHistoryMessageList\":\n            self.getHistoryMessageList(call: call, result: result);\n            break;\n        case \"markC2CMessageAsRead\":\n            self.markC2CMessageAsRead(call: call, result: result);\n            break;\n        case \"markGroupMessageAsRead\":\n            self.markGroupMessageAsRead(call: call, result: result);\n            break;\n        case \"deleteMessageFromLocalStorage\":\n            self.deleteMessageFromLocalStorage(call: call, result: result);\n            break;\n        case \"deleteMessages\":\n            self.deleteMessages(call: call, result: result);\n            break;\n        case \"insertGroupMessageToLocalStorage\":\n            self.insertGroupMessageToLocalStorage(call: call, result: result);\n            break;\n        case \"insertC2CMessageToLocalStorage\":\n            self.insertC2CMessageToLocalStorage(call: call, result: result);\n            break;\n        case \"downloadVideo\":\n            self.downloadVideo(call: call, result: result);\n            break;\n        case \"downloadVideoThumbnail\":\n            self.downloadVideoThumbnail(call: call, result: result);\n            break;\n        case \"downloadSound\":\n            self.downloadSound(call: call, result: result);\n            break;\n        case \"downloadFile\":\n            self.downloadFile(call: call, result: result);\n            break;\n        case \"setMessageLocalCustomStr\":\n            self.setMessageLocalCustomStr(call: call, result: result);\n            break;\n        case \"setMessageLocalCustomInt\":\n            self.setMessageLocalCustomInt(call: call, result: result);\n            break;\n        case \"findMessages\":\n            self.findMessages(call: call, result: result);\n            break;\n        case \"createGroup\":\n            self.createGroup(call: call, result: result);\n            break;\n        case \"joinGroup\":\n            self.joinGroup(call: call, result: result);\n            break;\n        case \"quitGroup\":\n            self.quitGroup(call: call, result: result);\n            break;\n        case \"dismissGroup\":\n            self.dismissGroup(call: call, result: result);\n            break;\n        case \"getJoinedGroupList\":\n            self.getJoinedGroupList(call: call, result: result);\n            break;\n        case \"getGroupsInfo\":\n            self.getGroupsInfo(call: call, result: result);\n            break;\n        case \"setGroupInfo\":\n            self.setGroupInfo(call: call, result: result);\n            break;\n        case \"searchGroups\":\n            self.searchGroups(call: call, result: result);\n            break;\n        case \"searchGroupMembers\":\n            self.searchGroupMembers(call: call, result: result);\n            break;\n        case \"setGroupReceiveMessageOpt\":\n            self.setGroupReceiveMessageOpt(call: call, result: result);\n            break;\n        case \"setC2CReceiveMessageOpt\":\n            self.setC2CReceiveMessageOpt(call: call, result: result);\n            break;\n        case \"getC2CReceiveMessageOpt\":\n            self.getC2CReceiveMessageOpt(call: call, result: result);\n            break;\n        case \"initGroupAttributes\":\n            self.initGroupAttributes(call: call, result: result);\n            break;\n        case \"setGroupAttributes\":\n            self.setGroupAttributes(call: call, result: result);\n            break;\n        case \"deleteGroupAttributes\":\n            self.deleteGroupAttributes(call: call, result: result);\n            break;\n        case \"getGroupAttributes\":\n            self.getGroupAttributes(call: call, result: result);\n            break;\n        case \"getGroupOnlineMemberCount\":\n            self.getGroupOnlineMemberCount(call: call, result: result);\n            break;\n        case \"getGroupMemberList\":\n            self.getGroupMemberList(call: call, result: result);\n            break;\n        case \"getGroupMembersInfo\":\n            self.getGroupMembersInfo(call: call, result: result);\n            break;\n        case \"setGroupMemberInfo\":\n            self.setGroupMemberInfo(call: call, result: result);\n            break;\n        case \"muteGroupMember\":\n            self.muteGroupMember(call: call, result: result);\n            break;\n        case \"inviteUserToGroup\":\n            self.inviteUserToGroup(call: call, result: result);\n            break;\n        case \"kickGroupMember\":\n            self.kickGroupMember(call: call, result: result);\n            break;\n        case \"setGroupMemberRole\":\n            self.setGroupMemberRole(call: call, result: result);\n            break;\n        case \"transferGroupOwner\":\n            self.transferGroupOwner(call: call, result: result);\n            break;\n        case \"getGroupApplicationList\":\n            self.getGroupApplicationList(call: call, result: result);\n            break;\n        case \"acceptGroupApplication\":\n            self.acceptGroupApplication(call: call, result: result);\n            break;\n        case \"refuseGroupApplication\":\n            self.refuseGroupApplication(call: call, result: result);\n            break;\n        case \"setGroupApplicationRead\":\n            self.setGroupApplicationRead(call: call, result: result);\n            break;\n        case \"getConversationList\":\n            self.getConversationList(call: call, result: result);\n            break;\n        case \"getConversation\":\n            self.getConversation(call: call, result: result);\n            break;\n        case \"deleteConversation\":\n            self.deleteConversation(call: call, result: result);\n            break;\n        case \"setConversationDraft\":\n            self.setConversationDraft(call: call, result: result);\n            break;\n        case \"pinConversation\":\n            self.pinConversation(call: call, result: result);\n            break;\n        case \"getTotalUnreadMessageCount\":\n            self.getTotalUnreadMessageCount(call: call, result: result);\n            break;\n        case \"getUsersInfo\":\n            self.getUsersInfo(call: call, result: result);\n            break;\n        case \"setSelfInfo\":\n            self.setSelfInfo(call: call, result: result);\n            break;\n        case \"addToBlackList\":\n            self.addToBlackList(call: call, result: result);\n            break;\n        case \"deleteFromBlackList\":\n            self.deleteFromBlackList(call: call, result: result);\n            break;\n        case \"getBlackList\":\n            self.getBlackList(call: call, result: result);\n            break;\n        case \"setOfflinePushConfig\":\n            self.setOfflinePushConfig(call: call, result: result);\n            break;\n        case \"setUnreadBadge\":\n            self.setUnreadBadge(call: call, result: result);\n            break;\n        case \"getFriendList\":\n            self.getFriendList(call: call, result: result);\n            break;\n        case \"getFriendsInfo\":\n            self.getFriendsInfo(call: call, result: result);\n            break;\n        case \"setFriendInfo\":\n            self.setFriendInfo(call: call, result: result);\n            break;\n        case \"addFriend\":\n            self.addFriend(call: call, result: result);\n            break;\n        case \"deleteFromFriendList\":\n            self.deleteFromFriendList(call: call, result: result);\n            break;\n        case \"checkFriend\":\n            self.checkFriend(call: call, result: result);\n            break;\n        case \"getFriendApplicationList\":\n            self.getFriendApplicationList(call: call, result: result);\n            break;\n        case \"acceptFriendApplication\":\n            self.acceptFriendApplication(call: call, result: result);\n            break;\n        case \"refuseFriendApplication\":\n            self.refuseFriendApplication(call: call, result: result);\n            break;\n        case \"deleteFriendApplication\":\n            self.deleteFriendApplication(call: call, result: result);\n            break;\n        case \"setFriendApplicationRead\":\n            self.setFriendApplicationRead(call: call, result: result);\n            break;\n        case \"createFriendGroup\":\n            self.createFriendGroup(call: call, result: result);\n            break;\n        case \"getFriendGroups\":\n            self.getFriendGroups(call: call, result: result);\n            break;\n        case \"deleteFriendGroup\":\n            self.deleteFriendGroup(call: call, result: result);\n            break;\n        case \"renameFriendGroup\":\n            self.renameFriendGroup(call: call, result: result);\n            break;\n        case \"addFriendsToFriendGroup\":\n            self.addFriendsToFriendGroup(call: call, result: result);\n            break;\n        case \"deleteFriendsFromFriendGroup\":\n            self.deleteFriendsFromFriendGroup(call: call, result: result);\n            break;\n        default:\n            result(FlutterMethodNotImplemented);\n        }\n    }\n\n    /**\n     * 初始化腾讯云IM\n     */\n    public func `initSDK`(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let logPrintLevel = ((call.arguments as! [String: Any])[\"logPrintLevel\"]) as? Int;\n        if let appid = CommonUtils.getParam(call: call, result: result, param: \"appid\") as? String {\n\n            // 初始化SDK配置\n            let sdkConfig = V2TIMSDKConfig();\n            if logPrintLevel != nil {\n                sdkConfig.logLevel = V2TIMLogLevel.init(rawValue: logPrintLevel!)!;\n            }\n\n            V2TIMManager.sharedInstance().initSDK((appid as NSString).intValue, config: sdkConfig, listener: customSdkListener)\n\n            // 绑定消息监听\n            V2TIMManager.sharedInstance()?.addAdvancedMsgListener(listener: customAdvancedMsgListener)\n\n            // 绑定会话监听\n            V2TIMManager.sharedInstance().setConversationListener(customConversationListener)\n\n            // 绑定群监听\n            V2TIMManager.sharedInstance().setGroupListener(customGroupListener)\n\n            // 绑定关系链监听\n            V2TIMManager.sharedInstance().setFriendListener(customFriendshipListener)\n\n            // 绑定信令监听\n            V2TIMManager.sharedInstance().addSignalingListener(listener: customSignalingListener)\n\n            // 绑定APNS监听\n            V2TIMManager.sharedInstance().setAPNSListener(customAPNSListener)\n\n            result(nil);\n        }\n    }\n\n\n    /// 反初始化\n    public func unInitSDK(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().unInitSDK();\n        V2TIMManager.sharedInstance()?.removeAdvancedMsgListener(listener: customAdvancedMsgListener)\n        V2TIMManager.sharedInstance()?.removeSignalingListener(listener: customSignalingListener)\n        result(nil);\n    }\n\n    /// 获得SDK版本\n    public func getVersion(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        result(V2TIMManager.sharedInstance()?.getVersion()!);\n    }\n\n    /// 获取服务器当前时间\n    public func getServerTime(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        result(V2TIMManager.sharedInstance()?.getServerTime());\n    }\n\n    /// 登录\n    func login(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String,\n           let userSig = CommonUtils.getParam(call: call, result: result, param: \"userSig\") as? String {\n            V2TIMManager.sharedInstance().login(userID, userSig: userSig, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 登出\n    public func logout(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance()?.logout({\n            result(nil);\n        }, fail: TencentImUtils.returnErrorClosures(result: result));\n    }\n\n    /// 获得登录状态\n    public func getLoginStatus(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        result(V2TIMManager.sharedInstance().getLoginStatus().rawValue);\n    }\n\n    /// 获得当前登录用户\n    public func getLoginUser(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        result(V2TIMManager.sharedInstance()?.getLoginUser());\n    }\n\n    /// 邀请某个人\n    public func invite(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let invitee = CommonUtils.getParam(call: call, result: result, param: \"invitee\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? String,\n           let onlineUserOnly = CommonUtils.getParam(call: call, result: result, param: \"onlineUserOnly\") as? Bool,\n           let offlinePushInfo = CommonUtils.getParam(call: call, result: result, param: \"offlinePushInfo\") as? String,\n           let timeout = CommonUtils.getParam(call: call, result: result, param: \"timeout\") as? Int32 {\n            result(V2TIMManager.sharedInstance().invite(invitee, data: data, onlineUserOnly: onlineUserOnly, offlinePushInfo: CustomOfflinePushInfoEntity.init(jsonStr: offlinePushInfo), timeout: timeout, succ: {\n                () -> Void in\n            }, fail: {\n                (code: Int32, desc: Optional<String>) -> Void in\n            }))\n        }\n    }\n\n    /// 邀请群内的某些人\n    public func inviteInGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? String,\n           let inviteeList = CommonUtils.getParam(call: call, result: result, param: \"inviteeList\") as? String,\n           let onlineUserOnly = CommonUtils.getParam(call: call, result: result, param: \"onlineUserOnly\") as? Bool,\n           let timeout = CommonUtils.getParam(call: call, result: result, param: \"timeout\") as? Int32 {\n\n            // 邀请\n            result(V2TIMManager.sharedInstance().invite(inGroup: groupID, inviteeList: inviteeList.split(separator: \",\"), data: data, onlineUserOnly: onlineUserOnly, timeout: timeout, succ: {\n                () -> Void in\n            }, fail: {\n                (code: Int32, desc: Optional<String>) -> Void in\n            }))\n        }\n    }\n\n    /// 邀请方取消邀请\n    public func cancel(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let inviteID = CommonUtils.getParam(call: call, result: result, param: \"inviteID\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? String {\n            V2TIMManager.sharedInstance().cancel(inviteID, data: data, succ: {\n                () -> Void in\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 接收方接收邀请\n    public func accept(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let inviteID = CommonUtils.getParam(call: call, result: result, param: \"inviteID\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? String {\n            V2TIMManager.sharedInstance().accept(inviteID, data: data, succ: {\n                () -> Void in\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 接收方拒绝邀请\n    public func reject(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let inviteID = CommonUtils.getParam(call: call, result: result, param: \"inviteID\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? String {\n            V2TIMManager.sharedInstance().reject(inviteID, data: data, succ: {\n                () -> Void in\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 获得信令信息\n    public func getSignalingInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let messageStr = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: messageStr, succ: {\n                (messages: V2TIMMessage?) in\n                result(JsonUtil.toJson(CustomSignalingInfoEntity.getDict(info: V2TIMManager.sharedInstance().getSignallingInfo(messages!))));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 添加邀请信令（可以用于群离线推送消息触发的邀请信令）\n    public func addInvitedSignaling(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n            V2TIMManager.sharedInstance().addInvitedSignaling(CustomSignalingInfoEntity.init(jsonStr: info), succ: {\n                () -> Void in\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 发送消息\n    private func sendMessage(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let nodeStr = CommonUtils.getParam(call: call, result: result, param: \"node\") as? String {\n            // 将节点信息解析\n            let node = JsonUtil.getDictionaryFromJSONString(jsonString: nodeStr);\n\n            // 获得发送消息体\n            let message: V2TIMMessage = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: node[\"nodeType\"] as! Int).messageNodeInterface().getV2TIMMessage(params: node);\n            self._sendMessage(message: message, call: call, result: result);\n        }\n    }\n\n\n    /// 重发消息\n    public func resendMessage(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let messageStr = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: messageStr, succ: {\n                (message: V2TIMMessage?) in\n                self._sendMessage(message: message!, call: call, result: result);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 发送消息\n    /// - Parameters:\n    ///   - message: 消息对象\n    ///   - call: Flutter 方法调用对象\n    ///   - result: Flutter 返回结果对象\n    private func _sendMessage(message: V2TIMMessage, call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let receiver = ((call.arguments as! [String: Any])[\"receiver\"]) as? String;\n        let groupID = ((call.arguments as! [String: Any])[\"groupID\"]) as? String;\n        let localCustomInt = ((call.arguments as! [String: Any])[\"localCustomInt\"]) as? Int32;\n        let localCustomStr = ((call.arguments as! [String: Any])[\"localCustomStr\"]) as? String;\n        let offlinePushInfo = ((call.arguments as! [String: Any])[\"offlinePushInfo\"]) as? String;\n        if let ol = CommonUtils.getParam(call: call, result: result, param: \"ol\") as? Bool,\n           let priority = CommonUtils.getParam(call: call, result: result, param: \"priority\") as? Int {\n            if localCustomInt != nil {\n                message.localCustomInt = localCustomInt!;\n            }\n            if localCustomStr != nil {\n                message.localCustomData = localCustomStr!.data(using: .utf8);\n            }\n\n            var msgId: [String?] = [nil];\n            // 成功回调\n            let _sendSuccess = {\n                TencentImUtils.getMessageByFindMessageEntity(dict: [\"msgId\": msgId[0]], succ: {\n                    (message: V2TIMMessage?) -> () in\n                    SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageSendSucc, params: MessageEntity.init(message: message!))\n                }, fail: { (int32: Int32, s: String?) -> () in })\n            };\n\n            // 进度回调\n            let _progress = {\n                (p: UInt32) in\n                SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageSendProgress, params: [\n                    \"msgId\": msgId[0]!,\n                    \"progress\": p,\n                ])\n            };\n\n            // 失败回调\n            let _fail = {\n                (code: Int32, desc: Optional<String>) -> Void in\n                SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageSendFail, params: [\n                    \"msgId\": msgId[0]!,\n                    \"code\": code,\n                    \"desc\": desc,\n                ])\n            };\n\n            // 发送消息\n            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)\n            result(msgId[0]);\n        }\n    }\n\n    /// 撤回消息\n    public func revokeMessage(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let messageStr = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: messageStr, succ: {\n                (messages: V2TIMMessage?) in\n                V2TIMManager.sharedInstance().revokeMessage(messages!, succ: {\n                    result(nil);\n                }, fail: TencentImUtils.returnErrorClosures(result: result))\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 获得单聊历史记录\n    public func getC2CHistoryMessageList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let lastMsg = ((call.arguments as! [String: Any])[\"lastMsg\"]) as? String;\n        if let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String,\n           let count = CommonUtils.getParam(call: call, result: result, param: \"count\") as? Int32 {\n\n            // 返回结果对象\n            let resultCallBack = {\n                (messages: [V2TIMMessage]?) in\n                var resultData: [MessageEntity] = [];\n                for item in messages! {\n                    resultData.append(MessageEntity.init(message: item));\n                }\n                result(JsonUtil.toJson(resultData));\n            };\n\n            // 根据消息对象是否为null进行不同的操作\n            if lastMsg == nil {\n                V2TIMManager.sharedInstance().getC2CHistoryMessageList(userID, count: count, lastMsg: nil, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result))\n            } else {\n                TencentImUtils.getMessageByFindMessageEntity(json: lastMsg!, succ: {\n                    (messages: V2TIMMessage?) in\n                    V2TIMManager.sharedInstance().getC2CHistoryMessageList(userID, count: count, lastMsg: messages!, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result))\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }\n        }\n    }\n\n    /// 获得群聊历史记录\n    public func getGroupHistoryMessageList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let lastMsg = ((call.arguments as! [String: Any])[\"lastMsg\"]) as? String;\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let count = CommonUtils.getParam(call: call, result: result, param: \"count\") as? Int32 {\n            // 返回结果对象\n            let resultCallBack = {\n                (messages: [V2TIMMessage]?) in\n                var resultData: [MessageEntity] = [];\n                for item in messages! {\n                    resultData.append(MessageEntity.init(message: item));\n                }\n                result(JsonUtil.toJson(resultData));\n            };\n\n            // 根据消息对象是否为null进行不同的操作\n            if lastMsg == nil {\n                V2TIMManager.sharedInstance().getGroupHistoryMessageList(groupID, count: count, lastMsg: nil, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result))\n            } else {\n                TencentImUtils.getMessageByFindMessageEntity(json: lastMsg!, succ: {\n                    (messages: V2TIMMessage?) in\n                    V2TIMManager.sharedInstance().getGroupHistoryMessageList(groupID, count: count, lastMsg: messages!, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result))\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }\n        }\n    }\n\n    /// 获得历史记录\n    public func getHistoryMessageList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let lastMsg = ((call.arguments as! [String: Any])[\"lastMsg\"]) as? String;\n        let groupID = ((call.arguments as! [String: Any])[\"groupID\"]) as? String;\n        let userID = ((call.arguments as! [String: Any])[\"userID\"]) as? String;\n        if let type = CommonUtils.getParam(call: call, result: result, param: \"type\") as? Int,\n           let count = CommonUtils.getParam(call: call, result: result, param: \"count\") as? Int32 {\n            // 返回结果对象\n            let resultCallBack = {\n                (messages: [V2TIMMessage]?) in\n                var resultData: [MessageEntity] = [];\n                for item in messages! {\n                    resultData.append(MessageEntity.init(message: item));\n                }\n                result(JsonUtil.toJson(resultData));\n            };\n\n            // 根据消息对象是否为null进行不同的操作\n            let opt = V2TIMMessageListGetOption();\n            if let v = userID {\n                opt.userID = v;\n            }\n            if let v = groupID {\n                opt.groupID = v;\n            }\n            opt.count = UInt(count);\n            opt.getType = V2TIMMessageGetType.init(rawValue: type)!;\n            if lastMsg == nil {\n                V2TIMManager.sharedInstance()?.getHistoryMessageList(opt, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result))\n            } else {\n                TencentImUtils.getMessageByFindMessageEntity(json: lastMsg!, succ: {\n                    (messages: V2TIMMessage?) in\n                    if messages != nil {\n                        opt.lastMsg = messages!;\n                    }\n                    V2TIMManager.sharedInstance()?.getHistoryMessageList(opt, succ: resultCallBack, fail: TencentImUtils.returnErrorClosures(result: result))\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }\n        }\n    }\n\n    /// 设置单聊已读\n    public func markC2CMessageAsRead(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String {\n            V2TIMManager.sharedInstance().markC2CMessage(asRead: userID, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 设置群聊已读\n    public func markGroupMessageAsRead(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String {\n            V2TIMManager.sharedInstance().markGroupMessage(asRead: groupID, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 删除本地消息\n    public func deleteMessageFromLocalStorage(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (messages: V2TIMMessage?) in\n                V2TIMManager.sharedInstance().deleteMessage(fromLocalStorage: messages!, succ: {\n                    result(nil);\n                }, fail: TencentImUtils.returnErrorClosures(result: result))\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 删除本地及漫游消息\n    public func deleteMessages(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String {\n            let arr = JsonUtil.getArrayFromJSONString(jsonString: message);\n            TencentImUtils.getMessageByFindMessageEntity(dict: arr as! [[String: Any]], succ: {\n                (messages: [V2TIMMessage]?) in\n                V2TIMManager.sharedInstance().delete(messages!, succ: {\n                    result(nil);\n                }, fail: TencentImUtils.returnErrorClosures(result: result))\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 向群组消息列表中添加一条消息\n    public func insertGroupMessageToLocalStorage(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let sender = CommonUtils.getParam(call: call, result: result, param: \"sender\") as? String,\n           let nodeStr = CommonUtils.getParam(call: call, result: result, param: \"node\") as? String {\n\n            // 将节点信息解析\n            let node = JsonUtil.getDictionaryFromJSONString(jsonString: nodeStr);\n\n            // 获得消息体\n            let message: V2TIMMessage = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: node[\"nodeType\"] as! Int).messageNodeInterface().getV2TIMMessage(params: node);\n\n            // 添加到列表\n            V2TIMManager.sharedInstance().insertGroupMessage(toLocalStorage: message, to: groupID, sender: sender, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 向群组消息列表中添加一条消息\n    public func insertC2CMessageToLocalStorage(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String,\n           let sender = CommonUtils.getParam(call: call, result: result, param: \"sender\") as? String,\n           let nodeStr = CommonUtils.getParam(call: call, result: result, param: \"node\") as? String {\n\n            // 将节点信息解析\n            let node = JsonUtil.getDictionaryFromJSONString(jsonString: nodeStr);\n\n            // 获得消息体\n            let message: V2TIMMessage = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: node[\"nodeType\"] as! Int).messageNodeInterface().getV2TIMMessage(params: node);\n\n            // 添加到列表\n            V2TIMManager.sharedInstance().insertC2CMessage(toLocalStorage: message, to: userID, sender: sender, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 下载视频\n    public func downloadVideo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String,\n           let path = CommonUtils.getParam(call: call, result: result, param: \"path\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (msg: V2TIMMessage?) in\n                msg?.videoElem?.downloadVideo(path, progress: {\n                    curSize, totalSize in\n                    SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [\n                        \"msgId\": msg!.msgID!,\n                        \"currentSize\": curSize,\n                        \"totalSize\": totalSize,\n                        \"type\": DownloadType.Video.rawValue,\n                    ])\n                }, succ: {\n                    result(path);\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 下载视频缩略图\n    public func downloadVideoThumbnail(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String,\n           let path = CommonUtils.getParam(call: call, result: result, param: \"path\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (msg: V2TIMMessage?) in\n                msg?.videoElem?.downloadSnapshot(path, progress: {\n                    curSize, totalSize in\n                    SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [\n                        \"msgId\": msg!.msgID!,\n                        \"currentSize\": curSize,\n                        \"totalSize\": totalSize,\n                        \"type\": DownloadType.VideoThumbnail.rawValue,\n                    ])\n                }, succ: {\n                    result(path);\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 下载语音\n    public func downloadSound(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String,\n           let path = CommonUtils.getParam(call: call, result: result, param: \"path\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (msg: V2TIMMessage?) in\n                msg?.soundElem?.downloadSound(path, progress: {\n                    curSize, totalSize in\n                    SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [\n                        \"msgId\": msg!.msgID!,\n                        \"currentSize\": curSize,\n                        \"totalSize\": totalSize,\n                        \"type\": DownloadType.Sound.rawValue,\n                    ])\n                }, succ: {\n                    result(path);\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 下载文件\n    public func downloadFile(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String,\n           let path = CommonUtils.getParam(call: call, result: result, param: \"path\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (msg: V2TIMMessage?) in\n                msg?.fileElem?.downloadFile(path, progress: {\n                    curSize, totalSize in\n                    SwiftTencentImPlugin.invokeListener(type: ListenerType.DownloadProgress, params: [\n                        \"msgId\": msg!.msgID!,\n                        \"currentSize\": curSize,\n                        \"totalSize\": totalSize,\n                        \"type\": DownloadType.File.rawValue,\n                    ])\n                }, succ: {\n                    result(path);\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 设置消息本地Str\n    public func setMessageLocalCustomStr(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (msg: V2TIMMessage?) in\n                msg!.localCustomData = data.data(using: .utf8)!;\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 设置消息本地Int\n    public func setMessageLocalCustomInt(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String,\n           let data = CommonUtils.getParam(call: call, result: result, param: \"data\") as? Int32 {\n            TencentImUtils.getMessageByFindMessageEntity(json: message, succ: {\n                (msg: V2TIMMessage?) in\n                msg!.localCustomInt = data;\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 查找消息列表\n    public func findMessages(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let messages = CommonUtils.getParam(call: call, result: result, param: \"messages\") as? String {\n            TencentImUtils.getMessageByFindMessageEntity(dict: JsonUtil.getArrayFromJSONString(jsonString: messages) as! [[String: Any]], succ: {\n                (ms: [V2TIMMessage]!) in\n                var res: [MessageEntity] = [];\n                for item in ms! {\n                    res.append(MessageEntity.init(message: item));\n                }\n                result(JsonUtil.toJson(res));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n\n    /// 创建群\n    public func createGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let memberList = ((call.arguments as! [String: Any])[\"memberList\"]) as? String;\n        if let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n\n            // 初始化群创建群成员列表\n            var ms: [CustomCreateGroupMemberEntity]? = nil;\n            if memberList != nil {\n                ms = [];\n                let array = JsonUtil.getArrayFromJSONString(jsonString: memberList!);\n                for index in 0..<array.count {\n                    ms?.append(CustomCreateGroupMemberEntity(dict: array[index] as! [String: Any]));\n                }\n            }\n\n            // 创建群\n            V2TIMManager.sharedInstance().createGroup(CustomGroupInfoEntity(json: info), memberList: ms, succ: {\n                s in\n                result(s);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 加入群\n    public func joinGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let message = CommonUtils.getParam(call: call, result: result, param: \"message\") as? String {\n            V2TIMManager.sharedInstance().joinGroup(groupID, msg: message, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 退出群\n    public func quitGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String {\n            V2TIMManager.sharedInstance().quitGroup(groupID, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n\n    /// 解散群\n    public func dismissGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String {\n            V2TIMManager.sharedInstance().dismissGroup(groupID, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得已加入的群列表\n    public func getJoinedGroupList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getJoinedGroupList({\n            infos in\n            var resultData: [[String: Any]] = [];\n            for item in infos! {\n                resultData.append(CustomGroupInfoEntity.getDict(info: item))\n            }\n            result(JsonUtil.toJson(resultData));\n        }, fail: TencentImUtils.returnErrorClosures(result: result))\n    }\n\n\n    /// 拉取群资料\n    public func getGroupsInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupIDList = CommonUtils.getParam(call: call, result: result, param: \"groupIDList\") as? String {\n            V2TIMManager.sharedInstance().getGroupsInfo(groupIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var resultData: [[String: Any]] = [];\n                for item in infos! {\n                    resultData.append(CustomGroupInfoResultEntity.getDict(info: item))\n                }\n                result(JsonUtil.toJson(resultData));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 修改群资料\n    public func setGroupInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n            V2TIMManager.sharedInstance().setGroupInfo(CustomGroupInfoEntity.init(json: info), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 搜索群\n    public func searchGroups(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let keywordList = CommonUtils.getParam(call: call, result: result, param: \"keywordList\") as? [String],\n           let isSearchGroupID = CommonUtils.getParam(call: call, result: result, param: \"isSearchGroupID\") as? Bool,\n           let isSearchGroupName = CommonUtils.getParam(call: call, result: result, param: \"isSearchGroupName\") as? Bool {\n            let param = V2TIMGroupSearchParam();\n            param.keywordList = keywordList;\n            param.isSearchGroupID = isSearchGroupID;\n            param.isSearchGroupName = isSearchGroupName;\n            V2TIMManager.sharedInstance().searchGroups(param, succ: {\n                infos in\n                var resultData: [[String: Any]] = [];\n                for item in infos! {\n                    resultData.append(CustomGroupInfoEntity.getDict(info: item))\n                }\n                result(JsonUtil.toJson(resultData));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 搜索群成员\n    public func searchGroupMembers(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let keywordList = CommonUtils.getParam(call: call, result: result, param: \"keywordList\") as? [String],\n           let groupIDList = CommonUtils.getParam(call: call, result: result, param: \"groupIDList\") as? [String],\n           let isSearchMemberNameCard = CommonUtils.getParam(call: call, result: result, param: \"isSearchMemberNameCard\") as? Bool,\n           let isSearchMemberUserID = CommonUtils.getParam(call: call, result: result, param: \"isSearchMemberUserID\") as? Bool,\n           let isSearchMemberRemark = CommonUtils.getParam(call: call, result: result, param: \"isSearchMemberRemark\") as? Bool,\n           let isSearchMemberNickName = CommonUtils.getParam(call: call, result: result, param: \"isSearchMemberNickName\") as? Bool {\n            let param = V2TIMGroupMemberSearchParam();\n            param.keywordList = keywordList;\n            param.groupIDList = groupIDList;\n            param.isSearchMemberNameCard = isSearchMemberNameCard;\n            param.isSearchMemberUserID = isSearchMemberUserID;\n            param.isSearchMemberRemark = isSearchMemberRemark;\n            param.isSearchMemberNickName = isSearchMemberNickName;\n            V2TIMManager.sharedInstance().searchGroupMembers(param, succ: {\n                data in\n                var resultData: [String: [V2TIMGroupMemberFullInfo]] = [:];\n                for item in data! {\n                    print(1)\n                }\n                result(JsonUtil.toJson(resultData));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 修改群消息接收选项\n    public func setGroupReceiveMessageOpt(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let opt = CommonUtils.getParam(call: call, result: result, param: \"opt\") as? Int {\n            V2TIMManager.sharedInstance().setGroupReceiveMessageOpt(groupID, opt: V2TIMReceiveMessageOpt.init(rawValue: opt)!, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 修改用户消息接收选项\n    public func setC2CReceiveMessageOpt(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let ids = CommonUtils.getParam(call: call, result: result, param: \"ids\") as? [String],\n           let opt = CommonUtils.getParam(call: call, result: result, param: \"opt\") as? Int {\n            V2TIMManager.sharedInstance().setC2CReceiveMessageOpt(ids, opt: V2TIMReceiveMessageOpt.init(rawValue: opt)!, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得用户消息接收选项\n    public func getC2CReceiveMessageOpt(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getC2CReceiveMessageOpt(call.arguments as? [String], succ: {\n            array in\n            var res: Dictionary<String, Int> = [:]\n            for item in array! {\n                res[item.userID] = item.receiveOpt.rawValue\n            }\n            result(res);\n        }, fail: TencentImUtils.returnErrorClosures(result: result))\n    }\n\n    /// 初始化群属性，会清空原有的群属性列表\n    public func initGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let attributes = CommonUtils.getParam(call: call, result: result, param: \"attributes\") as? String {\n            V2TIMManager.sharedInstance().initGroupAttributes(groupID, attributes: (JsonUtil.getDictionaryFromJSONString(jsonString: attributes) as! [String: String]), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 设置群属性\n    public func setGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let attributes = CommonUtils.getParam(call: call, result: result, param: \"attributes\") as? String {\n            V2TIMManager.sharedInstance().setGroupAttributes(groupID, attributes: (JsonUtil.getDictionaryFromJSONString(jsonString: attributes) as! [String: String]), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 删除群属性\n    public func deleteGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let keys = ((call.arguments as! [String: Any])[\"keys\"]) as? String;\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String {\n            V2TIMManager.sharedInstance().deleteGroupAttributes(groupID, keys: keys?.components(separatedBy: \",\"), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得群属性\n    public func getGroupAttributes(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let keys = ((call.arguments as! [String: Any])[\"keys\"]) as? String;\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String {\n            V2TIMManager.sharedInstance().getGroupAttributes(groupID, keys: keys?.components(separatedBy: \",\"), succ: {\n                dictionary in\n                result(JsonUtil.toJson(dictionary!));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得群在线人数\n    public func getGroupOnlineMemberCount(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String {\n            V2TIMManager.sharedInstance().getGroupOnlineMemberCount(groupID, succ: {\n                num in\n                result(num);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得群成员列表\n    public func getGroupMemberList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let filter = CommonUtils.getParam(call: call, result: result, param: \"filter\") as? UInt32,\n           let nextSeq = CommonUtils.getParam(call: call, result: result, param: \"nextSeq\") as? UInt64 {\n            V2TIMManager.sharedInstance().getGroupMemberList(groupID, filter: filter, nextSeq: nextSeq, succ: {\n                nextSeq, infos in\n                result(JsonUtil.toJson(CustomGroupMemberInfoResultEntity.init(nextSeq: nextSeq, infos: infos!)));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获取指定的群成员资料\n    public func getGroupMembersInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let memberList = CommonUtils.getParam(call: call, result: result, param: \"memberList\") as? String {\n            V2TIMManager.sharedInstance().getGroupMembersInfo(groupID, memberList: memberList.components(separatedBy: \",\"), succ: {\n                infos in\n                var resultData: [[String: Any]] = [];\n                for item in infos! {\n                    resultData.append(CustomGroupMemberFullInfoEntity.getDict(info: item))\n                }\n                result(JsonUtil.toJson(resultData));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获取指定的群成员资料\n    public func setGroupMemberInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n            V2TIMManager.sharedInstance().setGroupMemberInfo(groupID, info: CustomGroupMemberFullInfoEntity.init(json: info), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 禁言\n    public func muteGroupMember(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String,\n           let seconds = CommonUtils.getParam(call: call, result: result, param: \"seconds\") as? UInt32 {\n            V2TIMManager.sharedInstance().muteGroupMember(groupID, member: userID, muteTime: seconds, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 邀请他人进群\n    public func inviteUserToGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let userList = CommonUtils.getParam(call: call, result: result, param: \"userList\") as? String {\n            V2TIMManager.sharedInstance().inviteUser(toGroup: groupID, userList: userList.components(separatedBy: \",\"), succ: {\n                infos in\n                var resultData: [[String: Any]] = [];\n                for item in infos! {\n                    resultData.append(CustomGroupMemberOperationResultEntity.getDict(info: item))\n                }\n                result(JsonUtil.toJson(resultData));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 踢人\n    public func kickGroupMember(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let memberList = CommonUtils.getParam(call: call, result: result, param: \"memberList\") as? String,\n           let reason = CommonUtils.getParam(call: call, result: result, param: \"reason\") as? String {\n            V2TIMManager.sharedInstance().kickGroupMember(groupID, memberList: memberList.components(separatedBy: \",\"), reason: reason, succ: {\n                infos in\n                var resultData: [[String: Any]] = [];\n                for item in infos! {\n                    resultData.append(CustomGroupMemberOperationResultEntity.getDict(info: item))\n                }\n                result(JsonUtil.toJson(resultData));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 切换群成员角色\n    public func setGroupMemberRole(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String,\n           let role = CommonUtils.getParam(call: call, result: result, param: \"role\") as? UInt32 {\n            V2TIMManager.sharedInstance().setGroupMemberRole(groupID, member: userID, newRole: role, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 转让群主\n    public func transferGroupOwner(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupID = CommonUtils.getParam(call: call, result: result, param: \"groupID\") as? String,\n           let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String {\n            V2TIMManager.sharedInstance().transferGroupOwner(groupID, member: userID, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获取加群的申请列表\n    public func getGroupApplicationList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getGroupApplicationList({\n            info in\n            result(JsonUtil.toJson(CustomGroupApplicationResultEntity.getDict(info: info!)));\n        }, fail: TencentImUtils.returnErrorClosures(result: result))\n    }\n\n    /// 同意某一条加群申请\n    public func acceptGroupApplication(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let application = CommonUtils.getParam(call: call, result: result, param: \"application\") as? String,\n           let reason = CommonUtils.getParam(call: call, result: result, param: \"reason\") as? String {\n            TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(json: application, succ: {\n                (application: V2TIMGroupApplication?) -> () in\n                V2TIMManager.sharedInstance().accept(application!, reason: reason, succ: {\n                    result(nil);\n                }, fail: TencentImUtils.returnErrorClosures(result: result))\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 拒绝某一条加群申请\n    public func refuseGroupApplication(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let application = CommonUtils.getParam(call: call, result: result, param: \"application\") as? String,\n           let reason = CommonUtils.getParam(call: call, result: result, param: \"reason\") as? String {\n            TencentImUtils.getGroupApplicationByFindGroupApplicationEntity(json: application, succ: {\n                (application: V2TIMGroupApplication?) -> () in\n                V2TIMManager.sharedInstance().refuse(application!, reason: reason, succ: {\n                    result(nil);\n                }, fail: TencentImUtils.returnErrorClosures(result: result))\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 标记申请列表为已读\n    public func setGroupApplicationRead(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().setGroupApplicationRead({\n            result(nil);\n        }, fail: TencentImUtils.returnErrorClosures(result: result))\n    }\n\n    /// 获得会话列表\n    public func getConversationList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let nextSeq = CommonUtils.getParam(call: call, result: result, param: \"nextSeq\") as? UInt64,\n           let count = CommonUtils.getParam(call: call, result: result, param: \"count\") as? Int32 {\n            V2TIMManager.sharedInstance().getConversationList(nextSeq, count: count, succ: {\n                conversations, nextSeq, finished in\n                result(JsonUtil.toJson(CustomConversationResultEntity.init(conversations: conversations!, nextSeq: nextSeq, finished: finished)));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得会话\n    public func getConversation(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let conversationID = CommonUtils.getParam(call: call, result: result, param: \"conversationID\") as? String {\n            V2TIMManager.sharedInstance().getConversation(conversationID, succ: {\n                conversation in\n                result(JsonUtil.toJson(CustomConversationEntity.getDict(info: conversation!)));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 删除会话\n    public func deleteConversation(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let conversationID = CommonUtils.getParam(call: call, result: result, param: \"conversationID\") as? String {\n            V2TIMManager.sharedInstance().deleteConversation(conversationID, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n\n    /// 设置会话草稿\n    public func setConversationDraft(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let draftText = ((call.arguments as! [String: Any])[\"draftText\"]) as? String;\n        if let conversationID = CommonUtils.getParam(call: call, result: result, param: \"conversationID\") as? String {\n            V2TIMManager.sharedInstance().setConversationDraft(conversationID, draftText: draftText, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 会话置顶\n    public func pinConversation(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let conversationID = CommonUtils.getParam(call: call, result: result, param: \"conversationID\") as? String,\n           let isPinned = CommonUtils.getParam(call: call, result: result, param: \"isPinned\") as? Bool {\n            V2TIMManager.sharedInstance().pinConversation(conversationID, isPinned: isPinned, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得会话总未读数\n    public func getTotalUnreadMessageCount(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getTotalUnreadMessageCount({ number in\n            result(number);\n        }, fail: TencentImUtils.returnErrorClosures(result: result))\n    }\n\n    /// 获得用户资料\n    public func getUsersInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().getUsersInfo(userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomUserEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 修改自己的资料\n    public func setSelfInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n            V2TIMManager.sharedInstance().setSelfInfo(CustomUserEntity.init(json: info), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 添加用户到黑名单\n    public func addToBlackList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().add(toBlackList: userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendOperationResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 从黑名单中删除\n    public func deleteFromBlackList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().delete(fromBlackList: userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendOperationResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 获得黑名单列表\n    public func getBlackList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getBlackList({\n            infos in\n            var data: [[String: Any]] = [];\n            for item in infos! {\n                data.append(CustomFriendInfoEntity.getDict(info: item));\n            }\n            result(JsonUtil.toJson(data));\n        }, fail: TencentImUtils.returnErrorClosures(result: result))\n    }\n\n    /// 设置离线推送\n    public func setOfflinePushConfig(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let token = CommonUtils.getParam(call: call, result: result, param: \"token\") as? String,\n           let bussid = CommonUtils.getParam(call: call, result: result, param: \"bussid\") as? Int32,\n           let tpns = CommonUtils.getParam(call: call, result: result, param: \"tpns\") as? Bool {\n\n            let config = V2TIMAPNSConfig();\n            config.token = token.data(using: .utf8);\n            config.businessID = bussid;\n            config.isTPNSToken = tpns;\n\n            V2TIMManager.sharedInstance().setAPNS(config, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result))\n        }\n    }\n\n    /// 设置未读桌标\n    public func setUnreadBadge(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let number = CommonUtils.getParam(call: call, result: result, param: \"number\") as? UInt32 {\n            CustomAPNSListener.number = number;\n            result(nil);\n        }\n    }\n\n    /// 获得好友列表\n    public func getFriendList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getFriendList({\n            infos in\n            var data: [[String: Any]] = [];\n            for item in infos! {\n                data.append(CustomFriendInfoEntity.getDict(info: item));\n            }\n            result(JsonUtil.toJson(data));\n        }, fail: TencentImUtils.returnErrorClosures(result: result));\n    }\n\n    /// 获得指定好友信息\n    public func getFriendsInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().getFriendsInfo(userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendInfoResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 设置好友资料\n    public func setFriendInfo(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n            V2TIMManager.sharedInstance().setFriendInfo(CustomFriendInfoEntity.init(json: info), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 添加好友\n    public func addFriend(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let info = CommonUtils.getParam(call: call, result: result, param: \"info\") as? String {\n            V2TIMManager.sharedInstance().addFriend(CustomFriendAddApplicationEntity.init(json: info), succ: {\n                info in\n                result(JsonUtil.toJson(CustomFriendOperationResultEntity.getDict(info: info!)));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 删除好友\n    public func deleteFromFriendList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String,\n           let deleteType = CommonUtils.getParam(call: call, result: result, param: \"deleteType\") as? Int {\n            V2TIMManager.sharedInstance().delete(fromFriendList: userIDList.components(separatedBy: \",\"), delete: V2TIMFriendType.init(rawValue: deleteType)!, succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendOperationResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 检查好友关系\n    public func checkFriend(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let userID = CommonUtils.getParam(call: call, result: result, param: \"userID\") as? String,\n           let checkType = CommonUtils.getParam(call: call, result: result, param: \"checkType\") as? Int {\n            V2TIMManager.sharedInstance().checkFriend([userID], check: V2TIMFriendType.init(rawValue: checkType)!, succ: {\n                info in\n                if info == nil || info?.count == 0 {\n                    result(nil)\n                    return;\n                }\n                result(JsonUtil.toJson(CustomFriendCheckResultEntity.getDict(info: info!.first!)));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 获得好友申请列表\n    public func getFriendApplicationList(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().getFriendApplicationList({\n            info in\n            result(JsonUtil.toJson(CustomFriendApplicationResultEntity.getDict(info: info!)));\n        }, fail: TencentImUtils.returnErrorClosures(result: result));\n    }\n\n    /// 同意建立好友申请关系\n    public func acceptFriendApplication(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let application = CommonUtils.getParam(call: call, result: result, param: \"application\") as? String,\n           let responseType = CommonUtils.getParam(call: call, result: result, param: \"responseType\") as? Int {\n            TencentImUtils.getFriendApplicationByFindFriendApplicationEntity(json: application, succ: {\n                (v2TIMFriendApplication: V2TIMFriendApplication?) -> () in\n                V2TIMManager.sharedInstance().accept(v2TIMFriendApplication!, type: V2TIMFriendAcceptType.init(rawValue: responseType)!, succ: {\n                    info in\n                    result(JsonUtil.toJson(CustomFriendOperationResultEntity.getDict(info: info!)));\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 拒绝建立好友申请关系\n    public func refuseFriendApplication(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let application = CommonUtils.getParam(call: call, result: result, param: \"application\") as? String {\n            TencentImUtils.getFriendApplicationByFindFriendApplicationEntity(json: application, succ: {\n                (v2TIMFriendApplication: V2TIMFriendApplication?) -> () in\n                V2TIMManager.sharedInstance().refuse(v2TIMFriendApplication!, succ: {\n                    info in\n                    result(JsonUtil.toJson(CustomFriendOperationResultEntity.getDict(info: info!)));\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 删除好友申请\n    public func deleteFriendApplication(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let application = CommonUtils.getParam(call: call, result: result, param: \"application\") as? String {\n            TencentImUtils.getFriendApplicationByFindFriendApplicationEntity(json: application, succ: {\n                (v2TIMFriendApplication: V2TIMFriendApplication?) -> () in\n                V2TIMManager.sharedInstance().delete(v2TIMFriendApplication!, succ: {\n                    result(nil);\n                }, fail: TencentImUtils.returnErrorClosures(result: result));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 设置好友申请为已读\n    public func setFriendApplicationRead(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        V2TIMManager.sharedInstance().setFriendApplicationRead({\n            result(nil);\n        }, fail: TencentImUtils.returnErrorClosures(result: result));\n    }\n\n    /// 新建好友分组\n    public func createFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupName = CommonUtils.getParam(call: call, result: result, param: \"groupName\") as? String,\n           let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().createFriendGroup(groupName, userIDList: userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendOperationResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 获得分组信息\n    public func getFriendGroups(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        let groupNameList = ((call.arguments as! [String: Any])[\"groupNameList\"]) as? String;\n        V2TIMManager.sharedInstance().getFriendGroupList(groupNameList?.components(separatedBy: \",\"), succ: {\n            infos in\n            var data: [[String: Any]] = [];\n            for item in infos! {\n                data.append(CustomFriendGroupEntity.getDict(info: item));\n            }\n            result(JsonUtil.toJson(data));\n        }, fail: TencentImUtils.returnErrorClosures(result: result));\n    }\n\n    /// 删除分组\n    public func deleteFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupNameList = CommonUtils.getParam(call: call, result: result, param: \"groupNameList\") as? String {\n            V2TIMManager.sharedInstance().deleteFriendGroup(groupNameList.components(separatedBy: \",\"), succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 修改分组名称\n    public func renameFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let oldName = CommonUtils.getParam(call: call, result: result, param: \"oldName\") as? String,\n           let newName = CommonUtils.getParam(call: call, result: result, param: \"newName\") as? String {\n            V2TIMManager.sharedInstance().renameFriendGroup(oldName, newName: newName, succ: {\n                result(nil);\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 添加好友到分组\n    public func addFriendsToFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupName = CommonUtils.getParam(call: call, result: result, param: \"groupName\") as? String,\n           let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().addFriends(toFriendGroup: groupName, userIDList: userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendOperationResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /// 从分组中删除好友\n    public func deleteFriendsFromFriendGroup(call: FlutterMethodCall, result: @escaping FlutterResult) {\n        if let groupName = CommonUtils.getParam(call: call, result: result, param: \"groupName\") as? String,\n           let userIDList = CommonUtils.getParam(call: call, result: result, param: \"userIDList\") as? String {\n            V2TIMManager.sharedInstance().deleteFriends(fromFriendGroup: groupName, userIDList: userIDList.components(separatedBy: \",\"), succ: {\n                infos in\n                var data: [[String: Any]] = [];\n                for item in infos! {\n                    data.append(CustomFriendOperationResultEntity.getDict(info: item));\n                }\n                result(JsonUtil.toJson(data));\n            }, fail: TencentImUtils.returnErrorClosures(result: result));\n        }\n    }\n\n    /**\n     * 调用监听器\n     *\n     * @param type   类型\n     * @param params 参数\n     */\n    public static func invokeListener(type: ListenerType, params: Any?) {\n        var resultParams: [String: Any] = [:];\n        resultParams[\"type\"] = type;\n        if let p = params {\n            resultParams[\"params\"] = p;\n        }\n        SwiftTencentImPlugin.channel!.invokeMethod(\"onListener\", arguments: JsonUtil.toJson(resultParams));\n    }\n}\n"
  },
  {
    "path": "ios/Classes/TencentImPlugin.h",
    "content": "#import <Flutter/Flutter.h>\n\n@interface TencentImPlugin : NSObject<FlutterPlugin>\n@end\n"
  },
  {
    "path": "ios/Classes/TencentImPlugin.m",
    "content": "#import \"TencentImPlugin.h\"\n#if __has_include(<tencent_im_plugin/tencent_im_plugin-Swift.h>)\n#import <tencent_im_plugin/tencent_im_plugin-Swift.h>\n#else\n// Support project import fallback if the generated compatibility header\n// is not copied when this plugin is created as a library.\n// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816\n#import \"tencent_im_plugin-Swift.h\"\n#endif\n\n@implementation TencentImPlugin\n+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {\n  [SwiftTencentImPlugin registerWithRegistrar:registrar];\n}\n@end\n"
  },
  {
    "path": "ios/Classes/entity/CustomConversationEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义会话实体\nclass CustomConversationEntity: V2TIMConversation {\n\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMConversation) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"conversationID\"] = info.conversationID;\n        result[\"type\"] = info.type.rawValue;\n        result[\"userID\"] = info.userID;\n        result[\"groupID\"] = info.groupID;\n        result[\"showName\"] = info.showName;\n        result[\"faceUrl\"] = info.faceUrl;\n        result[\"recvOpt\"] = info.recvOpt.rawValue;\n        result[\"groupType\"] = info.groupType;\n        result[\"unreadCount\"] = info.unreadCount;\n        result[\"lastMessage\"] = info.lastMessage == nil ? nil : MessageEntity.init(message: info.lastMessage);\n        result[\"draftText\"] = info.draftText;\n        result[\"draftText\"] = info.draftText;\n        result[\"draftTimestamp\"] = info.draftTimestamp;\n        result[\"pinned\"] = info.isPinned;\n        result[\"test\"] = nil;\n        if info.groupAtInfolist != nil {\n            var groupAtInfoList: [[String: Any]] = [];\n            for item in info.groupAtInfolist {\n                groupAtInfoList.append(CustomGroupAtInfoEntity.getDict(info: item));\n            }\n            result[\"groupAtInfoList\"] = groupAtInfoList;\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomConversationResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义会话结果实体\nclass CustomConversationResultEntity: NSObject {\n    /// 下一次分页拉取的游标\n    var nextSeq: UInt64?;\n\n    /// 是否拉取完毕\n    var finished: Bool?;\n\n    /// 会话列表\n    var conversationList: [[String: Any]]?;\n\n    required public override init() {\n    }\n\n    init(conversations: [V2TIMConversation], nextSeq: UInt64, finished: Bool) {\n        super.init();\n        self.nextSeq = nextSeq;\n        self.finished = finished;\n        conversationList = [];\n        for item in conversations {\n            conversationList!.append(CustomConversationEntity.getDict(info: item));\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomCreateGroupMemberEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群创建群成员实体\nclass CustomCreateGroupMemberEntity: V2TIMCreateGroupMemberInfo {\n    required public override init() {\n    }\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.userID = (dict[\"userID\"] as? String);\n        if dict[\"role\"] != nil {\n            self.role = (dict[\"role\"] as! UInt32);\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendAddApplicationEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 好友申请实体\nclass CustomFriendAddApplicationEntity: V2TIMFriendAddApplication {\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.userID = (dict[\"userID\"] as? String);\n        self.friendRemark = (dict[\"friendRemark\"] as? String);\n        self.addWording = (dict[\"addWording\"] as? String);\n        self.addSource = (dict[\"addSource\"] as? String);\n        if dict[\"addType\"] != nil {\n            self.addType = V2TIMFriendType.init(rawValue: (dict[\"addType\"] as! Int))!\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendApplicationEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 好友申请实体\nclass CustomFriendApplicationEntity: V2TIMFriendApplication {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendApplication) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"nickname\"] = info.nickName;\n        result[\"faceUrl\"] = info.faceUrl;\n        result[\"addTime\"] = info.addTime;\n        result[\"addSource\"] = info.addSource;\n        result[\"addWording\"] = info.addWording;\n        result[\"type\"] = info.type.rawValue;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendApplicationResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 好友申请结果实体\nclass CustomFriendApplicationResultEntity: V2TIMFriendApplicationResult {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendApplicationResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"unreadCount\"] = info.unreadCount;\n\n        var friendApplicationList: [[String: Any]] = [];\n        for item in info.applicationList {\n            friendApplicationList.append(CustomFriendApplicationEntity.getDict(info: item as! V2TIMFriendApplication))\n        }\n        result[\"friendApplicationList\"] = friendApplicationList;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendCheckResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义好友检查结果实体\nclass CustomFriendCheckResultEntity : V2TIMFriendCheckResult{\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendCheckResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"resultCode\"] = info.resultCode;\n        result[\"resultInfo\"] = info.resultInfo;\n        result[\"resultType\"] = info.relationType.rawValue;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendGroupEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义好友分组实体\nclass CustomFriendGroupEntity: V2TIMFriendGroup {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendGroup) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"name\"] = info.groupName;\n        result[\"friendCount\"] = info.userCount;\n        result[\"friendIDList\"] = info.friendList;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义好友信息实体\nclass CustomFriendInfoEntity: V2TIMFriendInfo {\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.userID = (dict[\"userID\"] as? String);\n        self.friendRemark = (dict[\"friendRemark\"] as? String);\n        if dict[\"friendCustomInfo\"] != nil {\n            self.friendCustomInfo = [:];\n            for (k, v) in (dict[\"friendCustomInfo\"] as! [String: String]) {\n                self.friendCustomInfo[k] = v.data(using: .utf8)\n            }\n        }\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"friendRemark\"] = info.friendRemark;\n        result[\"friendGroups\"] = info.friendGroups;\n        result[\"friendCustomInfo\"] = info.friendCustomInfo;\n        result[\"userProfile\"] = CustomUserEntity.getDict(info: info.userFullInfo);\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendInfoResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\nclass CustomFriendInfoResultEntity: V2TIMFriendInfoResult {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendInfoResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"resultCode\"] = info.resultCode;\n        result[\"resultInfo\"] = info.resultInfo;\n        result[\"relation\"] = info.relation.rawValue;\n        result[\"friendInfo\"] = CustomFriendInfoEntity.getDict(info: info.friendInfo);\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomFriendOperationResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 好友操作结果实体\nclass CustomFriendOperationResultEntity: V2TIMFriendOperationResult {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMFriendOperationResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"resultCode\"] = info.resultCode;\n        result[\"resultInfo\"] = info.resultInfo;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupApplicationEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群申请实体\nclass CustomGroupApplicationEntity: V2TIMGroupApplication {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupApplication) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"groupID\"] = info.groupID;\n        result[\"fromUser\"] = info.fromUser;\n        result[\"fromUserNickName\"] = info.fromUserNickName;\n        result[\"fromUserFaceUrl\"] = info.fromUserFaceUrl;\n        result[\"toUser\"] = info.toUser;\n        result[\"addTime\"] = info.addTime;\n        result[\"requestMsg\"] = info.requestMsg;\n        result[\"handledMsg\"] = info.handledMsg;\n        result[\"type\"] = info.getType.rawValue;\n        result[\"handleStatus\"] = info.handleStatus.rawValue;\n        result[\"handleResult\"] = info.handleResult.rawValue;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupApplicationResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 群申请结果实体\nclass CustomGroupApplicationResultEntity: V2TIMGroupApplicationResult {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupApplicationResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"unreadCount\"] = info.unreadCount;\n        var groupApplicationList: [[String: Any]] = [];\n        for item in info.applicationList! {\n            groupApplicationList.append(CustomGroupApplicationEntity.getDict(info: item as! V2TIMGroupApplication))\n        }\n        result[\"groupApplicationList\"] = groupApplicationList;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupAtInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群@信息实体\nclass CustomGroupAtInfoEntity: V2TIMGroupAtInfo {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupAtInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"seq\"] = info.seq;\n        result[\"atType\"] = info.atType.rawValue;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupChangeInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/4.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群改变信息\nclass CustomGroupChangeInfoEntity: V2TIMGroupChangeInfo {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupChangeInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"type\"] = info.type.rawValue;\n        result[\"key\"] = info.key;\n        result[\"value\"] = info.value;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群信息实体\nclass CustomGroupInfoEntity: V2TIMGroupInfo {\n\n    required public override init() {\n    }\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        if dict[\"groupID\"] != nil {\n            self.groupID = (dict[\"groupID\"] as? String);\n        }\n        if dict[\"groupType\"] != nil {\n            self.groupType = (dict[\"groupType\"] as? String);\n        }\n        if dict[\"groupName\"] != nil {\n            self.groupName = (dict[\"groupName\"] as? String);\n        }\n        if dict[\"notification\"] != nil {\n            self.notification = (dict[\"notification\"] as? String);\n        }\n        if dict[\"introduction\"] != nil {\n            self.introduction = (dict[\"introduction\"] as? String);\n        }\n        if dict[\"faceURL\"] != nil {\n            self.faceURL = (dict[\"faceURL\"] as? String);\n        }\n        if dict[\"allMuted\"] != nil {\n            self.allMuted = (dict[\"allMuted\"] as! Bool);\n        }\n        if dict[\"groupAddOpt\"] != nil {\n            self.groupAddOpt = V2TIMGroupAddOpt.init(rawValue: (dict[\"groupAddOpt\"] as! Int))!;\n        }\n        if dict[\"customInfo\"] != nil {\n            self.customInfo = [:];\n            for (k, v) in (dict[\"customInfo\"] as! [String: String]) {\n                self.customInfo[k] = v.data(using: .utf8)\n            }\n        }\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"groupID\"] = info.groupID;\n        result[\"groupType\"] = info.groupType;\n        result[\"groupName\"] = info.groupName;\n        result[\"notification\"] = info.notification;\n        result[\"introduction\"] = info.introduction;\n        result[\"faceUrl\"] = info.faceURL;\n        result[\"allMuted\"] = info.allMuted;\n        result[\"owner\"] = info.owner;\n        result[\"createTime\"] = info.createTime;\n        result[\"groupAddOpt\"] = info.groupAddOpt.rawValue;\n        result[\"lastInfoTime\"] = info.lastInfoTime;\n        result[\"lastMessageTime\"] = info.lastMessageTime;\n        result[\"memberCount\"] = info.memberCount;\n        result[\"onlineCount\"] = info.onlineCount;\n        result[\"role\"] = info.role;\n        result[\"recvOpt\"] = info.recvOpt.rawValue;\n        result[\"joinTime\"] = info.joinTime;\n        result[\"customInfo\"] = info.customInfo;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupInfoResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群信息结果实体\nclass CustomGroupInfoResultEntity: V2TIMGroupInfoResult {\n    required public override init() {\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupInfoResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"resultCode\"] = info.resultCode;\n        result[\"resultMessage\"] = info.resultMsg;\n        result[\"groupInfo\"] = CustomGroupInfoEntity.getDict(info: info.info);\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupMemberChangeInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/4.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群信息实体\nclass CustomGroupMemberChangeInfoEntity: V2TIMGroupMemberChangeInfo {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupMemberChangeInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"muteTime\"] = info.muteTime;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupMemberFullInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群成员信息实体\nclass CustomGroupMemberFullInfoEntity: V2TIMGroupMemberFullInfo {\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.userID = (dict[\"userID\"] as? String);\n\n        if dict[\"customInfo\"] != nil {\n            self.customInfo = [:];\n            for (k, v) in (dict[\"customInfo\"] as! [String: String]) {\n                self.customInfo[k] = v.data(using: .utf8)\n            }\n        }\n\n        self.nameCard = (dict[\"nameCard\"] as? String);\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupMemberFullInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"nickName\"] = info.nickName;\n        result[\"friendRemark\"] = info.friendRemark;\n        result[\"faceUrl\"] = info.faceURL;\n        result[\"role\"] = info.role;\n        result[\"muteUntil\"] = info.muteUntil;\n        result[\"joinTime\"] = info.joinTime;\n        result[\"customInfo\"] = info.customInfo;\n        result[\"nameCard\"] = info.nameCard;\n        return result;\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(simpleInfo: V2TIMGroupMemberInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = simpleInfo.userID;\n        result[\"nickName\"] = simpleInfo.nickName;\n        result[\"friendRemark\"] = simpleInfo.friendRemark;\n        result[\"faceUrl\"] = simpleInfo.faceURL;\n        result[\"nameCard\"] = simpleInfo.nameCard;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupMemberInfoResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\nclass CustomGroupMemberInfoResultEntity: NSObject {\n    /// 获取分页拉取的 seq。如果为 0 表示拉取结束。\n    var nextSeq: UInt64?;\n\n    /// 群成员信息\n    var memberInfoList: [[String: Any]]?;\n\n    override init() {\n    }\n\n    init(nextSeq: UInt64, infos: [V2TIMGroupMemberFullInfo]) {\n        super.init();\n        self.nextSeq = nextSeq;\n        self.memberInfoList = [];\n        for info in infos {\n            self.memberInfoList!.append(CustomGroupMemberFullInfoEntity.getDict(info: info))\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomGroupMemberOperationResultEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义群成员操作结果\nclass CustomGroupMemberOperationResultEntity: V2TIMGroupMemberOperationResult {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMGroupMemberOperationResult) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"result\"] = info.result.rawValue;\n        result[\"memberID\"] = info.userID;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomMessageReceiptEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义消息响应实体\nclass CustomMessageReceiptEntity: V2TIMMessageReceipt {\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMMessageReceipt) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"timestamp\"] = info.timestamp;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomOfflinePushInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义离线推送数据实体\nclass CustomOfflinePushInfoEntity: V2TIMOfflinePushInfo {\n    required public override init() {\n    }\n\n    init(jsonStr: String?) {\n        super.init();\n\n        if jsonStr == nil {\n            return;\n        }\n\n        let dict = JsonUtil.getDictionaryFromJSONString(jsonString: jsonStr!);\n        self.title = (dict[\"title\"] as? String);\n        self.desc = (dict[\"desc\"] as? String);\n        self.ext = (dict[\"ext\"] as? String);\n        self.iOSSound = (dict[\"iOSSound\"] as? String);\n        if dict[\"ignoreIOSBadge\"] != nil {\n            self.ignoreIOSBadge = (dict[\"ignoreIOSBadge\"] as! Bool);\n        }\n        self.androidOPPOChannelID = (dict[\"androidOPPOChannelID\"] as? String);\n        if dict[\"disablePush\"] != nil {\n            self.disablePush = (dict[\"disablePush\"] as! Bool);\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomSignalingInfoEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/6.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义信令信息实体\nclass CustomSignalingInfoEntity: V2TIMSignalingInfo {\n    required public override init() {\n    }\n\n    init(jsonStr: String?) {\n        super.init();\n\n        if jsonStr == nil {\n            return;\n        }\n        let dict = JsonUtil.getDictionaryFromJSONString(jsonString: jsonStr!);\n        self.inviteID = (dict[\"inviteID\"] as? String);\n        self.groupID = (dict[\"groupID\"] as? String);\n        self.inviter = (dict[\"inviter\"] as? String);\n        self.inviteeList = (dict[\"inviteeList\"] as? NSMutableArray);\n        self.data = (dict[\"data\"] as? String);\n        if dict[\"timeout\"] != nil {\n            self.timeout = (dict[\"timeout\"] as! UInt32);\n        }\n        if dict[\"actionType\"] != nil {\n            self.actionType = SignalingActionType.init(rawValue: (dict[\"actionType\"] as! Int))!;\n        }\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMSignalingInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"inviteID\"] = info.inviteID;\n        result[\"groupID\"] = info.groupID;\n        result[\"inviter\"] = info.inviter;\n        result[\"inviteeList\"] = info.inviteeList;\n        result[\"data\"] = info.data;\n        result[\"timeout\"] = info.timeout;\n        result[\"actionType\"] = info.actionType.rawValue;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/CustomUserEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义用户实体\nclass CustomUserEntity: V2TIMUserFullInfo {\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        if dict[\"nickName\"] != nil{\n            self.nickName = (dict[\"nickName\"] as? String);\n        }\n        if dict[\"faceURL\"] != nil{\n            self.faceURL = (dict[\"faceURL\"] as? String);\n        }\n        if dict[\"selfSignature\"] != nil{\n            self.selfSignature = (dict[\"selfSignature\"] as? String);\n        }\n        if dict[\"gender\"] != nil {\n            self.gender = V2TIMGender.init(rawValue: (dict[\"gender\"] as! Int))!;\n        }\n        if dict[\"role\"] != nil {\n            self.role = (dict[\"role\"] as! UInt32);\n        }\n        if dict[\"level\"] != nil {\n            self.level = (dict[\"level\"] as! UInt32);\n        }\n        if dict[\"birthday\"] != nil {\n            self.birthday = (dict[\"birthday\"] as! UInt32);\n        }\n        if dict[\"allowType\"] != nil {\n            self.allowType = V2TIMFriendAllowType.init(rawValue: (dict[\"allowType\"] as! Int))!;\n        }\n        if dict[\"customInfo\"] != nil {\n            self.customInfo = [:];\n            for (k, v) in (dict[\"customInfo\"] as! [String: String]) {\n                self.customInfo[k] = v.data(using: .utf8)\n            }\n        }\n    }\n\n    /// 根据对象获得字典对象\n    public static func getDict(info: V2TIMUserFullInfo) -> [String: Any] {\n        var result: [String: Any] = [:];\n        result[\"userID\"] = info.userID;\n        result[\"nickName\"] = info.nickName;\n        result[\"faceUrl\"] = info.faceURL;\n        result[\"selfSignature\"] = info.selfSignature;\n        result[\"gender\"] = info.gender.rawValue;\n        result[\"role\"] = info.role;\n        result[\"level\"] = info.level;\n        result[\"birthday\"] = info.birthday;\n        result[\"allowType\"] = info.allowType.rawValue;\n        result[\"customInfo\"] = info.customInfo;\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/FindFriendApplicationEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/11/3.\n//\n\nimport Foundation\n\n/// 查找好友申请实体\nclass FindFriendApplicationEntity: NSObject {\n\n    /// 用户ID\n    var userID: String?;\n\n    /// 类型\n    var type: Int?;\n\n    required public override init() {\n    }\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.userID = dict[\"userID\"] as! String;\n        self.type = dict[\"type\"] as! Int;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/FindGroupApplicationEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/28.\n//\n\nimport Foundation\n\n/// 查找群申请信息实体\nclass FindGroupApplicationEntity: NSObject {\n\n    /// 来自用户\n    var fromUser: String?;\n\n    /// 群ID\n    var groupID: String?;\n\n    required public override init() {\n    }\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.fromUser = (dict[\"fromUser\"] as! String);\n        self.groupID = (dict[\"groupID\"] as! String);\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/FindMessageEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 查找消息实体\nclass FindMessageEntity: NSObject {\n\n    /// 消息ID\n    var msgId: String?;\n\n    required public override init() {\n    }\n\n    convenience init(json: String) {\n        self.init(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json))\n    }\n\n    init(dict: [String: Any]) {\n        super.init();\n        self.msgId = dict[\"msgId\"] as! String;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/entity/MessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//\n//  MessageEntity.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/2/10.\n//\npublic class MessageEntity: NSObject {\n\n    /**\n     * 消息 ID\n     */\n    var msgID: String?;\n\n    /**\n     * 消息时间戳\n     */\n    var timestamp: Date?;\n\n    /**\n     * 消息发送者 userID\n     */\n    var sender: String?;\n\n    /**\n     * 消息发送者昵称\n     */\n    var nickName: String?;\n\n    /**\n     * 好友备注。如果没有拉取过好友信息或者不是好友，返回 null\n     */\n    var friendRemark: String?;\n\n    /**\n     * 发送者头像 url\n     */\n    var faceUrl: String?;\n\n    /**\n     * 群组消息，nameCard 为发送者的群名片\n     */\n    var nameCard: String?;\n\n    /**\n     * 群组消息，groupID 为接收消息的群组 ID，否则为 null\n     */\n    var groupID: String?;\n\n    /**\n     * 单聊消息，userID 为会话用户 ID，否则为 null。 假设自己和 userA 聊天，无论是自己发给 userA 的消息还是 userA 发给自己的消息，这里的 userID 均为 userA\n     */\n    var userID: String?;\n\n    /**\n     * 消息发送状态\n     */\n    var status: Int?;\n\n    /**\n     * 消息类型\n     */\n    var elemType: Int?;\n\n    /**\n     * 消息自定义数据（本地保存，不会发送到对端，程序卸载重装后失效）\n     */\n    var localCustomData: Data?;\n\n    /**\n     * 消息自定义数据（本地保存，不会发送到对端，程序卸载重装后失效）\n     */\n    var localCustomInt: Int32?;\n\n    /**\n     * 消息发送者是否是自己\n     */\n    var `self`: Bool?;\n\n    /**\n     * 消息自己是否已读\n     */\n    var read: Bool?;\n\n    /**\n     * 消息对方是否已读（只有 C2C 消息有效）\n     */\n    var peerRead: Bool?;\n\n    /**\n     * 消息优先级\n     */\n    var priority: Int?;\n\n    /**\n     * 消息的离线推送信息\n     */\n    var offlinePushInfo: V2TIMOfflinePushInfo?;\n\n    /**\n     * 群@用户列表\n     */\n    var groupAtUserList: [String]?;\n\n    /**\n     * 消息的序列号\n     * 群聊中的消息序列号云端生成，在群里是严格递增且唯一的。 单聊中的序列号是本地生成，不能保证严格递增且唯一。\n     */\n    var seq: UInt64?;\n\n    /**\n     * 描述信息\n     */\n    var note: String?;\n\n    /**\n     * 节点信息\n     */\n    var node: AbstractMessageEntity?;\n\n    /// 消息随机码\n    var random: UInt64?;\n\n    override init() {\n    }\n\n    init(message: V2TIMMessage) {\n        super.init();\n        // 设置基本信息\n        self.msgID = message.msgID;\n        self.timestamp = message.timestamp;\n        self.sender = message.sender;\n        self.nickName = message.nickName;\n        self.friendRemark = message.friendRemark;\n        self.faceUrl = message.faceURL;\n        self.nameCard = message.nameCard;\n        self.groupID = message.groupID;\n        self.userID = message.userID;\n        self.status = message.status.rawValue;\n        self.elemType = message.elemType.rawValue;\n        self.localCustomData = message.localCustomData;\n        self.localCustomInt = message.localCustomInt;\n        self.`self` = message.isSelf;\n        self.read = message.isRead;\n        self.peerRead = message.isPeerRead;\n//        self.priority\n//        self.offlinePushInfo\n        self.groupAtUserList = (message.groupAtUserList as? [String]);\n        self.seq = message.seq;\n        self.random = message.random;\n\n        // 解析接口\n        let nodeType = MessageNodeType.getMessageNodeTypeByV2TIMConstant(constant: self.elemType!);\n        if nodeType != MessageNodeType.None {\n            let messageNodeInterface = nodeType.messageNodeInterface();\n            let elem = MessageNodeType.getElemByMessage(message: message)!;\n            self.note = messageNodeInterface.getNote(elem: elem);\n            self.node = messageNodeInterface.analysis(elem: elem);\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/enums/DownloadType.swift",
    "content": "//\n// Created by 蒋具宏 on 2021/1/5.\n//\n\nimport Foundation\n\n/// 下载类型\nenum DownloadType: Int {\n    /// 语音\n    case Sound = 0\n\n    /// 视频\n    case Video = 1\n\n    /// 视频缩略图\n    case VideoThumbnail = 2\n\n    /// 文件\n    case File = 3\n}\n"
  },
  {
    "path": "ios/Classes/enums/ListenerType.swift",
    "content": "//  Created by 蒋具宏 on 2020/2/15.\n//  监听器类型\npublic enum ListenerType {\n    /// 新消息通知\n    case NewMessage\n\n    /// C2C已读回执\n    case C2CReadReceipt\n\n    /// 消息撤回\n    case MessageRevoked\n\n    /// 同步服务开始\n    case SyncServerStart\n\n    /// 同步服务完成\n    case SyncServerFinish\n\n    /// 同步服务失败\n    case SyncServerFailed\n\n    /// 新会话\n    case NewConversation\n\n    /// 会话刷新\n    case ConversationChanged\n\n    /// 好友申请新增通知\n    case FriendApplicationListAdded\n\n    /// 好友申请删除通知\n    case FriendApplicationListDeleted\n\n    /// 好友申请已读通知\n    case FriendApplicationListRead\n\n    /// 好友新增通知\n    case FriendListAdded\n\n    /// 好友删除通知\n    case FriendListDeleted\n\n    /// 黑名单新增通知\n    case BlackListAdd\n\n    /// 黑名单删除通知\n    case BlackListDeleted\n\n    /// 好友资料更新通知\n    case FriendInfoChanged\n\n    /// 有用户加入群\n    case MemberEnter\n\n    /// 有用户离开群\n    case MemberLeave\n\n    /// 有用户被拉入群\n    case MemberInvited\n\n    /// 有用户被踢出群\n    case MemberKicked\n\n    /// 群成员信息被修改\n    case MemberInfoChanged\n\n    /// 创建群\n    case GroupCreated\n\n    /// 群被解散\n    case GroupDismissed\n\n    /// 群被回收\n    case GroupRecycled\n\n    /// 群信息被修改\n    case GroupInfoChanged\n\n    /// 有新的加群申请\n    case ReceiveJoinApplication\n\n    /// 加群信息已被管理员处理\n    case ApplicationProcessed\n\n    /// 指定管理员身份\n    case GrantAdministrator\n\n    /// 取消管理员身份\n    case RevokeAdministrator\n\n    /// 主动退出群组\n    case QuitFromGroup\n\n    /// 收到 RESTAPI 下发的自定义系统消息\n    case ReceiveRESTCustomData\n\n    /// 收到群属性更新的回调\n    case GroupAttributeChanged\n\n    /// 正在连接到腾讯云服务器\n    case Connecting\n\n    /// 网络连接成功\n    case ConnectSuccess\n\n    /// 网络连接失败\n    case ConnectFailed\n\n    /// 踢下线\n    case KickedOffline\n\n    /// 当前用户的资料发生了更新\n    case SelfInfoUpdated\n\n    /// 用户登录的 userSig 过期（用户需要重新获取 userSig 后登录）\n    case UserSigExpired\n\n    /// 收到信令邀请\n    case ReceiveNewInvitation\n\n    /// 信令被邀请者接受邀请\n    case InviteeAccepted\n\n    /// 信令被邀请者拒绝邀请\n    case InviteeRejected\n\n    /// 信令邀请被取消\n    case InvitationCancelled\n\n    /// 信令邀请超时\n    case InvitationTimeout\n\n    /// 下载进度\n    case DownloadProgress\n\n    /// 消息发送成功\n    case MessageSendSucc\n\n    /// 消息发送失败\n    case MessageSendFail\n\n    /// 消息发送进度更新\n    case MessageSendProgress\n}\n"
  },
  {
    "path": "ios/Classes/enums/MessageNodeType.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/3/13.\n//  消息节点类型\nenum MessageNodeType: Int {\n    // 没有元素\n    case None\n\n    // 文本\n    case Text\n\n    // 自定义\n    case Custom\n\n    // 图片\n    case Image\n\n    // 语音\n    case Sound\n\n    // 视频\n    case Video\n\n    // 文件\n    case File\n\n    // 位置\n    case Location\n\n    // 表情\n    case Face\n\n    // 群提示\n    case GroupTips\n\n\n    /// 获得消息节点接口\n    func messageNodeInterface() -> AbstractMessageNode {\n        switch self {\n        case .None:\n            return AbstractMessageNode();\n        case .Text:\n            return TextMessageNode()\n        case .Custom:\n            return CustomMessageNode();\n        case .Image:\n            return ImageMessageNode();\n        case .Sound:\n            return SoundMessageNode();\n        case .Video:\n            return VideoMessageNode();\n        case .File:\n            return FileMessageNode();\n        case .Location:\n            return LocationMessageNode();\n        case .Face:\n            return FaceMessageNode();\n        case .GroupTips:\n            return GroupTipsMessageNode();\n        }\n    }\n\n    /// 根据腾讯云节点获得枚举对象\n    public static func getMessageNodeTypeByV2TIMConstant(constant: Int) -> MessageNodeType {\n        MessageNodeType.init(rawValue: constant)!\n    }\n\n    /// 根据Message获得节点信息\n    public static func getElemByMessage(message: V2TIMMessage) -> V2TIMElem? {\n        let messageType = getMessageNodeTypeByV2TIMConstant(constant: message.elemType.rawValue);\n        switch messageType {\n        case .None:\n            return nil;\n        case .Text:\n            return message.textElem;\n        case .Custom:\n            return message.customElem;\n        case .Image:\n            return message.imageElem;\n        case .Sound:\n            return message.soundElem;\n        case .Video:\n            return message.videoElem;\n        case .File:\n            return message.fileElem;\n        case .Location:\n            return message.locationElem;\n        case .Face:\n            return message.faceElem;\n        case .GroupTips:\n            return message.groupTipsElem;\n        }\n    }\n\n}\n"
  },
  {
    "path": "ios/Classes/listener/CustomAPNSListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/29.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义APNS监听器\nclass CustomAPNSListener: NSObject, V2TIMAPNSListener {\n    public static var number: UInt32 = 0;\n\n\n    /// 程序进后台后，自定义 APP 的未读数，如果不处理，APP 未读数默认为所有会话未读数之和\n    func onSetAPPUnreadCount() -> UInt32 {\n        return CustomAPNSListener.number;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/listener/CustomAdvancedMsgListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 消息相关监听器\nclass CustomAdvancedMsgListener: NSObject, V2TIMAdvancedMsgListener {\n    /// 新消息通知\n    func onRecvNewMessage(_ msg: V2TIMMessage!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.NewMessage, params: MessageEntity.init(message: msg!))\n    }\n\n    /// C2C已读回执\n    func onRecvC2CReadReceipt(_ receiptList: [V2TIMMessageReceipt]!) {\n        var data: [[String: Any]] = [];\n        for item in receiptList! {\n            data.append(CustomMessageReceiptEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.C2CReadReceipt, params: data)\n    }\n\n    /// 消息撤回\n    func onRecvMessageRevoked(_ msgID: String!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.MessageRevoked, params: msgID!)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/listener/CustomConversationListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义会话监听\nclass CustomConversationListener: NSObject, V2TIMConversationListener {\n    /// 同步服务开始\n    func onSyncServerStart() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.SyncServerStart, params: nil)\n    }\n\n    /// 同步服务完成\n    func onSyncServerFinish() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.SyncServerFinish, params: nil)\n    }\n\n    /// 同步服务失败\n    func onSyncServerFailed() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.SyncServerFailed, params: nil)\n    }\n\n    /// 新会话\n    func onNewConversation(_ conversationList: [V2TIMConversation]!) {\n        var cs: [[String: Any]] = [];\n        for item in conversationList! {\n            cs.append(CustomConversationEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.NewConversation, params: cs)\n    }\n\n    /// 会话刷新\n    func onConversationChanged(_ conversationList: [V2TIMConversation]!) {\n        var cs: [[String: Any]] = [];\n        for item in conversationList! {\n            cs.append(CustomConversationEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ConversationChanged, params: cs)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/listener/CustomFriendshipListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 关系链相关监听器\nclass CustomFriendshipListener: NSObject, V2TIMFriendshipListener {\n    /**\n     * 好友申请新增通知，两种情况会收到这个回调：\n     * <p>\n     * 自己申请加别人好友\n     * 别人申请加自己好友\n     */\n    func onFriendApplicationListAdded(_ applicationList: [V2TIMFriendApplication]!) {\n        var data: [[String: Any]] = [];\n        for item in applicationList! {\n            data.append(CustomFriendApplicationEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendApplicationListAdded, params: data)\n    }\n\n    /**\n     * 好友申请删除通知，四种情况会收到这个回调\n     * <p>\n     * 调用 deleteFriendApplication 主动删除好友申请\n     * 调用 refuseFriendApplication 拒绝好友申请\n     * 调用 acceptFriendApplication 同意好友申请且同意类型为 V2TIM_FRIEND_ACCEPT_AGREE 时\n     * 申请加别人好友被拒绝\n     */\n    func onFriendApplicationListDeleted(_ userIDList: [Any]!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendApplicationListDeleted, params: userIDList!)\n    }\n\n\n    /**\n     * 好友申请已读通知，如果调用 setFriendApplicationRead 设置好友申请列表已读，会收到这个回调（主要用于多端同步）\n     */\n    func onFriendApplicationListRead() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendApplicationListRead, params: nil)\n    }\n\n    /**\n     * 好友新增通知\n     */\n    func onFriendListAdded(_ infoList: [V2TIMFriendInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in infoList! {\n            data.append(CustomFriendInfoEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendListAdded, params: data)\n    }\n\n    /**\n     * 好友删除通知，，两种情况会收到这个回调：\n     * <p>\n     * 自己删除好友（单向和双向删除都会收到回调）\n     * 好友把自己删除（双向删除会收到）\n     */\n    func onFriendListDeleted(_ userIDList: [Any]!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendListDeleted, params: userIDList!)\n    }\n\n    /**\n     * 黑名单新增通知\n     */\n    func onBlackListAdded(_ infoList: [V2TIMFriendInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in infoList! {\n            data.append(CustomFriendInfoEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.BlackListAdd, params: data)\n    }\n\n\n    /**\n     * 黑名单删除通知\n     */\n    func onBlackListDeleted(_ userIDList: [Any]!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.BlackListDeleted, params: userIDList!)\n    }\n\n\n    /**\n     * 好友资料更新通知\n     */\n    func onFriendProfileChanged(_ infoList: [V2TIMFriendInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in infoList! {\n            data.append(CustomFriendInfoEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.FriendInfoChanged, params: data)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/listener/CustomGroupListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 群监听器\nclass CustomGroupListener: NSObject, V2TIMGroupListener {\n    /// 有用户加入群（全员能够收到）\n    func onMemberEnter(_ groupID: String!, memberList: [V2TIMGroupMemberInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in memberList! {\n            data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberEnter, params: [\n            \"groupID\": groupID!,\n            \"memberList\": data,\n        ])\n    }\n\n    /// 有用户离开群（全员能够收到）\n    func onMemberLeave(_ groupID: String!, member: V2TIMGroupMemberInfo!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberLeave, params: [\n            \"groupID\": groupID!,\n            \"member\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: member!),\n        ])\n    }\n\n\n    /// 某些人被拉入某群（全员能够收到）\n    func onMemberInvited(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in memberList! {\n            data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberInvited, params: [\n            \"groupID\": groupID!,\n            \"memberList\": data,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n        ])\n    }\n\n    /// 某些人被踢出某群（全员能够收到）\n    func onMemberKicked(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in memberList! {\n            data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberKicked, params: [\n            \"groupID\": groupID!,\n            \"memberList\": data,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n        ])\n    }\n\n    /// 群成员信息被修改（全员能收到）\n    func onMemberInfoChanged(_ groupID: String!, changeInfoList: [V2TIMGroupMemberChangeInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in changeInfoList! {\n            data.append(CustomGroupMemberChangeInfoEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.MemberInfoChanged, params: [\n            \"groupID\": groupID!,\n            \"changInfo\": data,\n        ])\n    }\n\n    /// 创建群（主要用于多端同步）\n    func onGroupCreated(_ groupID: String!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupCreated, params: groupID!)\n    }\n\n    /// 群被解散了（全员能收到）\n    func onGroupDismissed(_ groupID: String!, opUser: V2TIMGroupMemberInfo!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupDismissed, params: [\n            \"groupID\": groupID!,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n        ])\n    }\n\n    /// 群被回收（全员能收到）\n    func onGroupRecycled(_ groupID: String!, opUser: V2TIMGroupMemberInfo!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupRecycled, params: [\n            \"groupID\": groupID!,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n        ])\n    }\n\n    /// 群信息被修改（全员能收到）\n    func onGroupInfoChanged(_ groupID: String!, changeInfoList: [V2TIMGroupChangeInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in changeInfoList! {\n            data.append(CustomGroupChangeInfoEntity.getDict(info: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupInfoChanged, params: [\n            \"groupID\": groupID!,\n            \"changInfo\": data,\n        ])\n    }\n\n    /// 有新的加群请求（只有群主或管理员会收到）\n    func onReceiveJoinApplication(_ groupID: String!, member: V2TIMGroupMemberInfo!, opReason: String!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ReceiveJoinApplication, params: [\n            \"groupID\": groupID!,\n            \"member\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: member!),\n            \"opReason\": opReason!,\n        ])\n    }\n\n    /// 加群请求已经被群主或管理员处理了（只有申请人能够收到）\n    func onApplicationProcessed(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, opResult isAgreeJoin: Bool, opReason: String!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ApplicationProcessed, params: [\n            \"groupID\": groupID!,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n            \"isAgreeJoin\": isAgreeJoin,\n            \"opReason\": opReason,\n        ])\n    }\n\n    /// 指定管理员身份\n    func onGrantAdministrator(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in memberList! {\n            data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.GrantAdministrator, params: [\n            \"groupID\": groupID!,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n            \"memberList\": data,\n        ])\n    }\n\n    /// 取消管理员身份\n    func onRevokeAdministrator(_ groupID: String!, opUser: V2TIMGroupMemberInfo!, memberList: [V2TIMGroupMemberInfo]!) {\n        var data: [[String: Any]] = [];\n        for item in memberList! {\n            data.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item));\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.RevokeAdministrator, params: [\n            \"groupID\": groupID!,\n            \"opUser\": CustomGroupMemberFullInfoEntity.getDict(simpleInfo: opUser!),\n            \"memberList\": data,\n        ])\n    }\n\n    /// 主动退出群组（主要用于多端同步，直播群（AVChatRoom）不支持）\n    func onQuit(fromGroup groupID: String!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.QuitFromGroup, params: groupID!)\n    }\n\n    /// 收到 RESTAPI 下发的自定义系统消息\n    func onReceiveRESTCustomData(_ groupID: String!, data: Data!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ReceiveRESTCustomData, params: [\n            \"groupID\": groupID!,\n            \"customData\": data!,\n        ])\n    }\n\n    /// 收到群属性更新的回调\n    func onGroupAttributeChanged(_ groupID: String!, attributes: NSMutableDictionary!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.GroupAttributeChanged, params: [\n            \"groupID\": groupID!,\n            \"attributes\": attributes!,\n        ])\n    }\n}"
  },
  {
    "path": "ios/Classes/listener/CustomSDKListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义SDK监听器\nclass CustomSDKListener: NSObject, V2TIMSDKListener {\n    /// 连接中\n    public func onConnecting() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.Connecting, params: nil)\n    }\n\n    /// 网络连接成功\n    public func onConnectSuccess() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ConnectSuccess, params: nil)\n    }\n\n    /// 网络连接失败\n    public func onConnectFailed(_ code: Int32, err: String!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ConnectFailed, params: [\n            \"code\": code,\n            \"err\": err!,\n        ])\n    }\n\n    /// 踢下线通知\n    public func onKickedOffline() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.KickedOffline, params: nil)\n    }\n\n    /// 用户登录的 userSig 过期（用户需要重新获取 userSig 后登录）\n    public func onUserSigExpired() {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.UserSigExpired, params: nil)\n    }\n\n    /// 当前用户的资料发生了更新\n    public func onSelfInfoUpdated(_ Info: V2TIMUserFullInfo!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.SelfInfoUpdated, params: CustomUserEntity.getDict(info: Info!))\n    }\n}\n"
  },
  {
    "path": "ios/Classes/listener/CustomSignalingListener.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 自定义信令监听\nclass CustomSignalingListener: NSObject, V2TIMSignalingListener {\n    ///收到新邀请时\n    func onReceiveNewInvitation(_ inviteID: String!, inviter: String!, groupID: String!, inviteeList: [String]!, data: String?) {\n        var params: [String: Any] = [\"inviteID\": inviteID!];\n        if let temp = inviter {\n            params[\"inviter\"] = temp;\n        }\n        if let temp = groupID {\n            params[\"groupID\"] = temp;\n        }\n        if let temp = inviteeList {\n            params[\"inviteeList\"] = temp;\n        }\n        if let temp = data {\n            params[\"data\"] = temp;\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.ReceiveNewInvitation, params: params)\n    }\n\n    /// 被邀请者接受邀请\n    func onInviteeAccepted(_ inviteID: String!, invitee: String!, data: String?) {\n        var params: [String: Any] = [\"inviteID\": inviteID!,\"invitee\": invitee!];\n        if let temp = data {\n            params[\"data\"] = temp;\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.InviteeAccepted, params: params)\n    }\n\n    /// 被邀请者拒绝邀请\n    func onInviteeRejected(_ inviteID: String!, invitee: String!, data: String?) {\n        var params: [String: Any] = [\"inviteID\": inviteID!,\"invitee\": invitee!];\n        if let temp = data {\n            params[\"data\"] = temp;\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.InviteeRejected, params: params)\n    }\n\n    /// 邀请被取消\n    func onInvitationCancelled(_ inviteID: String!, inviter: String!, data: String?) {\n        var params: [String: Any] = [\"inviteID\": inviteID!,\"inviter\": inviter!];\n        if let temp = data {\n            params[\"data\"] = temp;\n        }\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.InvitationCancelled, params: params)\n    }\n\n    /// 邀请超时\n    func onInvitationTimeout(_ inviteID: String!, inviteeList: [String]!) {\n        SwiftTencentImPlugin.invokeListener(type: ListenerType.InvitationTimeout, params: [\n            \"inviteID\": inviteID!,\n            \"inviteeList\": inviteeList!,\n        ])\n    }\n}"
  },
  {
    "path": "ios/Classes/message/AbstractMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  AbstractMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  消息节点抽象\npublic class AbstractMessageNode {\n\n    /**\n     * 获得发送的消息体\n     * @param params 参数\n     */\n    func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        return V2TIMMessage();\n    }\n\n    /**\n     * 根据消息节点获得描述\n     *\n     * @param elem 节点\n     */\n    func getNote(elem: V2TIMElem) -> String? {\n        return nil;\n    }\n\n    /// 根据节点解析为实体对象\n    func analysis(elem: V2TIMElem) -> AbstractMessageEntity? {\n        return nil;\n    }\n\n    /// 获得参数\n    func getParam<T>(params: [AnyHashable: Any], paramKey: AnyHashable) -> T? {\n        if let value = params[paramKey] {\n            return (value as? T);\n        }\n        return nil;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/CustomMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  自定义消息节点\npublic class CustomMessageNode: AbstractMessageNode {\n\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let data: String = getParam(params: params, paramKey: \"data\")!;\n        let desc: String? = getParam(params: params, paramKey: \"desc\");\n        let ext: String? = getParam(params: params, paramKey: \"ext\");\n        return V2TIMManager.sharedInstance().createCustomMessage(data.data(using: String.Encoding.utf8), desc: desc, extension: ext)\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[其它消息]\"\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        CustomMessageEntity(elem: elem as! V2TIMCustomElem)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/FaceMessageNode.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 表情消息实体\nclass FaceMessageNode: AbstractMessageNode {\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let index: Int32 = getParam(params: params, paramKey: \"index\")!;\n        let data: String = getParam(params: params, paramKey: \"data\")!;\n        return V2TIMManager.sharedInstance().createFaceMessage(index, data: data.data(using: String.Encoding.utf8))\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[表情]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        FaceMessageEntity(elem: elem as! V2TIMFaceElem)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/FileMessageNode.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\nclass FileMessageNode: AbstractMessageNode {\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let filePath: String = getParam(params: params, paramKey: \"filePath\")!;\n        let fileName: String = getParam(params: params, paramKey: \"fileName\")!;\n        return V2TIMManager.sharedInstance().createFileMessage(filePath, fileName: fileName)\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[文件]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        FileMessageEntity(elem: elem as! V2TIMFileElem)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/GroupTipsMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  GroupTipsMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/21.\n//  群提示消息节点\npublic class GroupTipsMessageNode: AbstractMessageNode {\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[群提示]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        GroupTipsMessageEntity(elem: elem as! V2TIMGroupTipsElem);\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/ImageMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  图片消息节点\npublic class ImageMessageNode: AbstractMessageNode {\n\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let path: String = getParam(params: params, paramKey: \"path\")!;\n        return V2TIMManager.sharedInstance().createImageMessage(path)\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[图片]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        ImageMessageEntity(elem: elem as! V2TIMImageElem)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/LocationMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  位置消息节点\npublic class LocationMessageNode: AbstractMessageNode {\n\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let desc: String = getParam(params: params, paramKey: \"desc\")!;\n        let longitude: Double = getParam(params: params, paramKey: \"longitude\")!;\n        let latitude: Double = getParam(params: params, paramKey: \"latitude\")!;\n        return V2TIMManager.sharedInstance().createLocationMessage(desc, longitude: longitude, latitude: latitude)\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[位置消息]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        LocationMessageEntity(elem: elem as! V2TIMLocationElem);\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/SoundMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  语音消息节点\npublic class SoundMessageNode: AbstractMessageNode {\n\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let path: String = getParam(params: params, paramKey: \"path\")!;\n        let duration: Int32 = getParam(params: params, paramKey: \"duration\")!;\n        return V2TIMManager.sharedInstance().createSoundMessage(path, duration: duration)\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[语音]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        SoundMessageEntity(elem: elem as! V2TIMSoundElem);\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/TextMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  文本消息节点\npublic class TextMessageNode: AbstractMessageNode {\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let text: String = getParam(params: params, paramKey: \"content\")!;\n        let atUserList: Any? = getParam(params: params, paramKey: \"atUserList\");\n        let atAll: Any? = getParam(params: params, paramKey: \"atAll\");\n\n        // 有@用户或者@所有人则进入分支\n        if (atUserList != nil && !(atUserList is NSNull)) || (atAll != nil && atAll is NSNull && atAll as! Bool) {\n            var atList: [String] = [];\n\n            // 追加@的目标\n            if atUserList != nil && !(atUserList is NSNull) {\n                for item in atUserList as! [String] {\n                    atList.append(item);\n                }\n            }\n\n            // @所有人\n            if atAll != nil && !(atAll is NSNull) && (atAll as! Bool) {\n                atList.append(kImSDK_MesssageAtALL);\n            }\n\n            // @有内容则直接返回\n            if atList.count >= 1 {\n                return V2TIMManager.sharedInstance().createText(atMessage: text, atUserList: (atList as AnyObject as! NSArray).mutableCopy() as! NSMutableArray)\n            }\n        }\n        return V2TIMManager.sharedInstance().createTextMessage(text);\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        (elem as! V2TIMTextElem).text ?? \"\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        TextMessageEntity(elem: elem as! V2TIMTextElem)\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/VideoMessageNode.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageNode.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/13.\n//  视频消息节点\npublic class VideoMessageNode: AbstractMessageNode {\n\n    override func getV2TIMMessage(params: [String: Any]) -> V2TIMMessage {\n        let videoPath: String = getParam(params: params, paramKey: \"videoPath\")!;\n        let duration: Int32 = getParam(params: params, paramKey: \"duration\")!;\n        let snapshotPath: String = getParam(params: params, paramKey: \"snapshotPath\")!;\n\n        var suffix: String = \"\";\n        if videoPath.contains(\".\") {\n            let ss = videoPath.split(separator: \".\");\n            suffix = String(ss[ss.count - 1]);\n        }\n        return V2TIMManager.sharedInstance().createVideoMessage(videoPath, type: suffix, duration: duration, snapshotPath: snapshotPath)\n    }\n\n    override func getNote(elem: V2TIMElem) -> String {\n        \"[视频]\";\n    }\n\n    override func analysis(elem: V2TIMElem) -> AbstractMessageEntity {\n        VideoMessageEntity(elem: elem as! V2TIMVideoElem);\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/AbstractMessageEntity.swift",
    "content": "//\n//  AbstractMessageEntity.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/15.\n//  抽象消息实体\npublic class AbstractMessageEntity : NSObject{\n    var nodeType : MessageNodeType?;\n    \n    override init() {\n    }\n    \n    init(_ type : MessageNodeType) {\n        nodeType = type;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/CustomMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/3/15.\n//  自定义消息实体\npublic class CustomMessageEntity: AbstractMessageEntity {\n    /// 自定义内容\n    var data: String?;\n\n    /// 描述\n    var desc: String?;\n\n    /// 扩展\n    var ext: String?;\n\n    override init() {\n        super.init(MessageNodeType.Custom);\n    }\n\n    init(elem: V2TIMCustomElem) {\n        super.init(MessageNodeType.Custom);\n        self.data = String(data: elem.data, encoding: String.Encoding.utf8)!;\n        if let v = elem.desc {\n            self.desc = v;\n        }\n        if let v = elem.`extension` {\n            self.ext = v;\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/FaceMessageEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 表情消息实体\nclass FaceMessageEntity: AbstractMessageEntity {\n    /**\n    * 下标\n    */\n    var index: Int32?;\n\n    /**\n     * 文件名\n     */\n    var data: Data?;\n\n    override init() {\n        super.init(MessageNodeType.Face);\n    }\n\n    init(elem: V2TIMFaceElem) {\n        super.init(MessageNodeType.Face);\n        self.index = elem.index;\n        self.data = elem.data;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/FileMessageEntity.swift",
    "content": "//\n// Created by 蒋具宏 on 2020/10/27.\n//\n\nimport Foundation\nimport ImSDK_Plus\n\n/// 文件消息实体\nclass FileMessageEntity: AbstractMessageEntity {\n    /**\n     * 文件路径\n     */\n    var filePath: String?;\n\n    /**\n     * 文件名\n     */\n    var fileName: String?;\n\n    /**\n     * 文件UUID\n     */\n    var uuid: String?;\n\n    /**\n     * 文件大小\n     */\n    var size: Int32?;\n\n    override init() {\n        super.init(MessageNodeType.File);\n    }\n\n    init(elem: V2TIMFileElem) {\n        super.init(MessageNodeType.File);\n        self.uuid = elem.uuid;\n        self.fileName = elem.filename;\n        self.filePath = elem.path;\n        self.size = elem.fileSize;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/LocationMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/3/15.\n//  位置消息实体\npublic class LocationMessageEntity: AbstractMessageEntity {\n\n    /// 描述\n    var desc: String?;\n\n    /// 经度\n    var latitude: Double?;\n\n    /// 纬度\n    var longitude: Double?;\n\n    override init() {\n        super.init(MessageNodeType.Location)\n    }\n\n    init(elem: V2TIMLocationElem) {\n        super.init(MessageNodeType.Location)\n        self.desc = elem.desc;\n        self.longitude = elem.longitude;\n        self.latitude = elem.latitude;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/SoundMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/3/15.\n//  语音消息实体\npublic class SoundMessageEntity: AbstractMessageEntity {\n\n    /// 语音ID\n    var uuid: String?;\n\n    /// 路径\n    var path: String?;\n\n    /// 时长\n    var duration: Int32?;\n\n    /// 数据大小\n    var dataSize: Int32?;\n\n    override init() {\n        super.init(MessageNodeType.Sound);\n    }\n\n    init(elem: V2TIMSoundElem) {\n        super.init(MessageNodeType.Sound);\n        self.path = elem.path;\n        self.dataSize = elem.dataSize;\n        self.duration = elem.duration;\n        self.uuid = elem.uuid;\n    }\n}"
  },
  {
    "path": "ios/Classes/message/entity/TextMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//\n//  TextMessageEntity.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/15.\n//  文本消息实体\npublic class TextMessageEntity: AbstractMessageEntity {\n    /// 消息内容\n    var content: String?;\n\n    override init() {\n        super.init(MessageNodeType.Text);\n    }\n\n    init(elem: V2TIMTextElem) {\n        super.init(MessageNodeType.Text);\n        self.content = elem.text;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/VideoMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/3/15.\n//  视频消息实体\npublic class VideoMessageEntity: AbstractMessageEntity {\n\n    /**\n    * 视频路径\n    */\n    var videoPath: String?;\n    /**\n     * 视频UUID\n     */\n    var videoUuid: String?;\n    /**\n     * 视频大小\n     */\n    var videoSize: Int32?;\n    /**\n     * 时长\n     */\n    var duration: Int32?;\n    /**\n     * 缩略图路径\n     */\n    var snapshotPath: String?;\n    /**\n     * 缩略图UUID\n     */\n    var snapshotUuid: String?;\n    /**\n     * 缩略图大小\n     */\n    var snapshotSize: Int32?;\n    /**\n     * 缩略图宽度\n     */\n    var snapshotWidth: Int32?;\n    /**\n     * 缩略图高度\n     */\n    var snapshotHeight: Int32?;\n\n    override init() {\n        super.init(MessageNodeType.Video);\n    }\n\n    init(elem: V2TIMVideoElem) {\n        super.init(MessageNodeType.Video);\n        self.videoUuid = elem.videoUUID;\n        self.videoPath = elem.videoPath;\n        self.videoSize = elem.videoSize;\n        self.duration = elem.duration;\n        self.snapshotUuid = elem.snapshotUUID;\n        self.snapshotWidth = elem.snapshotWidth;\n        self.snapshotHeight = elem.snapshotHeight;\n        self.snapshotPath = elem.snapshotPath;\n        self.snapshotSize = elem.snapshotSize;\n    }\n}"
  },
  {
    "path": "ios/Classes/message/entity/group_tips/GroupTipsMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//\n//  GroupTipsMessageself.swift\n//  tencent_im_plugin\n//\n//  Created by 蒋具宏 on 2020/3/21.\n//  群体是消息实体\npublic class GroupTipsMessageEntity: AbstractMessageEntity {\n    /// 群ID\n    var groupID: String?;\n\n    /// 操作类型\n    var type: Int?;\n\n    /// 操作者\n    var opMember: [String: Any]?;\n\n    /// 被操作人列表\n    var memberList: [[String: Any]]?;\n\n    /// 群资料变更信息列表，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE时有效\n    var groupChangeInfoList: [[String: Any]]?;\n\n    /// 群成员变更信息列表，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE时有效\n    var memberChangeInfoList: [[String: Any]]?;\n\n    /// 当前群成员数，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_JOIN, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_QUIT, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_KICKED的时候有效\n    var memberCount : UInt32?;\n\n    override init() {\n        super.init(MessageNodeType.GroupTips);\n    }\n\n    init(elem: V2TIMGroupTipsElem) {\n        super.init(MessageNodeType.GroupTips);\n        self.groupID = elem.groupID;\n        self.type = elem.type.rawValue;\n        self.opMember = CustomGroupMemberFullInfoEntity.getDict(simpleInfo: elem.opMember);\n        var memberList : [[String: Any]] = [];\n        for var item in elem.memberList{\n            memberList.append(CustomGroupMemberFullInfoEntity.getDict(simpleInfo: item));\n        }\n        self.memberList = memberList;\n\n        var groupChangeInfoList : [[String: Any]] = [];\n        for var item in elem.groupChangeInfoList{\n            groupChangeInfoList.append(CustomGroupChangeInfoEntity.getDict(info: item));\n        }\n        self.groupChangeInfoList = groupChangeInfoList;\n\n        var memberChangeInfoList : [[String: Any]] = [];\n        for var item in elem.memberChangeInfoList{\n            memberChangeInfoList.append(CustomGroupMemberChangeInfoEntity.getDict(info: item));\n        }\n        self.memberChangeInfoList = groupChangeInfoList;\n\n        self.memberCount = elem.memberCount;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/image/ImageEntity.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/2/10.\n//  图片实体\npublic class ImageEntity: NSObject {\n\n    /**\n     * 大小\n     */\n    var size: Int32?;\n\n    /**\n     * 宽度\n     */\n    var width: Int32?;\n\n    /**\n     * 类型\n     */\n    var type: Int?;\n\n    /**\n     * url\n     */\n    var url: String?;\n\n    /**\n     * 高度\n     */\n    var height: Int32?;\n\n    /// ID\n    var uUID: String?;\n\n    override init() {\n    }\n\n    init(image: V2TIMImage) {\n        super.init();\n        self.size = image.size;\n        self.width = image.width;\n        self.type = image.type.rawValue;\n        self.url = image.url;\n        self.height = image.height;\n        self.uUID = image.uuid;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/message/entity/image/ImageMessageEntity.swift",
    "content": "import ImSDK_Plus\n\n//  Created by 蒋具宏 on 2020/3/15.\n//  图片消息实体\npublic class ImageMessageEntity: AbstractMessageEntity {\n\n    /// 路径\n    var path: String?;\n\n    /// 图片数据\n    var imageData: [ImageEntity]?;\n\n    override init() {\n        super.init(MessageNodeType.Image);\n    }\n\n    init(elem: V2TIMImageElem) {\n        super.init(MessageNodeType.Image);\n        self.path = elem.path;\n        self.imageData = [];\n        for item in elem.imageList {\n            self.imageData!.append(ImageEntity(image: item));\n        }\n    }\n}\n"
  },
  {
    "path": "ios/Classes/utils/CommonUtils.swift",
    "content": "import Flutter\n\n//  通用工具类\n//  Created by 蒋具宏 on 2020/2/10.\npublic class CommonUtils {\n    /**\n     * 通用方法，获得参数值，如未找到参数，则直接中断\n     *\n     * @param methodCall 方法调用对象\n     * @param result     返回对象\n     * @param param      参数名\n     */\n    public static func getParam(call: FlutterMethodCall, result: @escaping FlutterResult, param: String) -> Any? {\n        let value = (call.arguments as! [String: Any])[param];\n        if value == nil {\n            result(\n                    FlutterError(code: \"5\", message: \"Missing parameter\", details: \"Cannot find parameter `\\(param)` or `\\(param)` is null!\")\n            );\n        }\n        return value\n    }\n\n    /// 将hex string 转为Data\n    public static func dataWithHexString(hex: String) -> Data {\n        var hex = hex\n        var data = Data()\n        while (hex.count > 0) {\n            let index1 = hex.index(hex.startIndex, offsetBy: 2)\n            let index2 = hex.index(hex.endIndex, offsetBy: 0)\n            let c: String = String(hex[hex.startIndex..<index1])\n            hex = String(hex[index1..<index2])\n            var ch: UInt32 = 0\n            Scanner(string: c).scanHexInt32(&ch)\n            var char = UInt8(ch)\n            data.append(&char, count: 1)\n        }\n        return data\n    }\n}\n"
  },
  {
    "path": "ios/Classes/utils/JsonUtil.swift",
    "content": "import Foundation\n\n//  Json工具类\n//  Created by 蒋具宏 on 2020/2/11.\npublic class JsonUtil {\n\n    /**\n     *  字典转模型\n     */\n    public static func toModel<T>(_ type: T.Type, value: Any?) -> T? where T: Decodable {\n        guard let value = value else {\n            return nil\n        }\n        return toModel(type, value: value)\n    }\n\n    /**\n     *  字典转模型\n     */\n    public static func toModel<T>(_ type: T.Type, value: Any) -> T? where T: Decodable {\n        guard let data = try? JSONSerialization.data(withJSONObject: value) else {\n            return nil\n        }\n        let decoder = JSONDecoder()\n        decoder.nonConformingFloatDecodingStrategy = .convertFromString(positiveInfinity: \"+Infinity\", negativeInfinity: \"-Infinity\", nan: \"NaN\")\n        return try? decoder.decode(type, from: data)\n    }\n\n    /**\n     * 将json字符串转换为字典\n     */\n    public static func getDictionaryFromJSONString(jsonString: String) -> [String: Any] {\n\n        let jsonData: Data = jsonString.data(using: .utf8)!\n\n        let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)\n        if dict != nil {\n            return (dict as! NSDictionary) as! [String: Any]\n        }\n        return NSDictionary() as! [String: Any]\n    }\n\n    /// 将json字符串转换为数组\n    public static func getArrayFromJSONString(jsonString: String) -> NSArray {\n        let jsonData: Data = jsonString.data(using: .utf8)!\n        let array = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)\n        if array != nil {\n            return array as! NSArray\n        }\n        return array as! NSArray\n    }\n\n    /**\n     * 将对象转换为JSON字符串(数组/对象)\n     */\n    public static func toJson(_ object: Any) -> Any {\n        // 解析数组\n        if let array = object as? [Any] {\n            let isStringArray = object is [String];\n            var result = \"[\";\n            for item in array {\n                let data = isStringArray ? \"\\\"\\(toJsonByObj(item))\\\"\" : toJsonByObj(item);\n                result += \"\\(data),\";\n            }\n            // 删除末尾逗号\n            if result.hasSuffix(\",\") {\n                result = String(result.dropLast());\n            }\n            return result + \"]\";\n        }\n\n        // 解析单个对象\n        return toJsonByObj(object);\n    }\n\n    /**\n     * 将对象转换为JSON字符串(单个对象)\n     */\n    private static func toJsonByObj(_ object: Any) -> Any {\n\n        if object is String {\n            return \"\\(object)\";\n        }\n\n        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<AnyHashable, Any> {\n            return vHandler(object);\n        }\n\n        var result = \"{\";\n        // 反射当前类及父类反射对象\n        let morror = Mirror.init(reflecting: object)\n        let superMorror = morror.superclassMirror\n        // 键值对字典\n        var dict: Dictionary<String?, Any> = [:];\n\n        // 遍历父类和子类属性集合，添加到键值对字典\n        if superMorror != nil {\n            for (name, value) in (superMorror?.children)! {\n                dict[name!] = value;\n            }\n        }\n\n        for (name, value) in morror.children {\n            dict[name!] = value;\n        }\n\n        // 组装json对象\n        for (name, value) in dict {\n            // 解码值，根据不同类型设置不同封装，nil不进行封装\n            if let n = name {\n                let v = unwrap(value);\n                // 未解码成功的值，则是nil\n                if !(\"\\(type(of: v))\".hasPrefix(\"Optional\")) {\n                    result += kv(n, v);\n                    result += \",\";\n                }\n            }\n        }\n\n        // 删除末尾逗号\n        if result.hasSuffix(\",\") {\n            result = String(result.dropLast());\n        }\n\n        return result + \"}\";\n    }\n\n    /**\n     * 解码值，optional 将会被自动解码\n     */\n    private static func unwrap<T>(_ any: T) -> Any {\n        let mirror = Mirror(reflecting: any)\n        guard mirror.displayStyle == .optional, let first = mirror.children.first else {\n            return any\n        }\n        return first.value\n    }\n\n    /**\n     * 根据K和V拼装键值对\n     */\n    private static func kv(_ k: Any, _ v: Any) -> String {\n        return \"\\\"\\(k)\\\":\\(vHandler(v))\";\n    }\n\n    /**\n     *  值处理，根据不同类型的值，返回不同的结果\n     */\n    private static func vHandler(_ v: Any) -> Any {\n        // 根据类型赋值不同的值\n        // 如果是字符串，将会进行转移 \" to \\\"\n        // 如果是Data，将会解析为字符串并且进行转移\n        if v is String {\n            return \"\\\"\\(stringReplace(source: \"\\(v)\"))\\\"\";\n        } else if v is Int32 || v is Int || v is UInt32 || v is UInt64 || v is Bool || v is Double || v is time_t {\n            return v;\n        } else if v is Date {\n            return Int((v as! Date).timeIntervalSince1970);\n        } else if v is Data {\n            return \"\\\"\\(stringReplace(source: String(data: v as! Data, encoding: String.Encoding.utf8)!))\\\"\";\n        } else if v is Dictionary<AnyHashable, Any> {\n            var result = \"{\";\n            // 解析键值对\n            for (key, value) in v as! Dictionary<AnyHashable, Any> {\n                result += \"\\(kv(key, value)),\";\n            }\n            // 删除末尾逗号\n            if result.hasSuffix(\",\") {\n                result = String(result.dropLast());\n            }\n            return result + \"}\";\n        } else if v is NSObject {\n            return toJson(v);\n        } else {\n            return \"\\\"\\(v)\\\"\";\n        }\n    }\n\n    /**\n     *  字符串替换\n     */\n    private static func stringReplace(source: String) -> String {\n        var result = source;\n\n        // 内容替换\n        result = result.replacingOccurrences(of: \"\\\\\", with: \"\\\\\\\\\");\n        result = result.replacingOccurrences(of: \"\\\"\", with: \"\\\\\\\"\");\n        result = result.replacingOccurrences(of: \"/\", with: \"\\\\/\");\n        result = result.replacingOccurrences(of: \"\\\\\\\\b\", with: \"\\\\b\");\n        result = result.replacingOccurrences(of: \"\\\\\\\\f\", with: \"\\\\f\");\n        result = result.replacingOccurrences(of: \"\\n\", with: \"\\\\n\");\n        result = result.replacingOccurrences(of: \"\\r\", with: \"\\\\r\");\n        result = result.replacingOccurrences(of: \"\\t\", with: \"\\\\t\");\n        result = result.replacingOccurrences(of: \"\\0\", with: \"\");\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "ios/Classes/utils/TencentImUtil.swift",
    "content": "import ImSDK_Plus\n\n//  腾讯云工具类\n//  Created by 蒋具宏 on 2020/2/10.\npublic class TencentImUtils {\n    /**\n     * 返回[错误返回闭包]，腾讯云IM通用格式\n     */\n    public static func returnErrorClosures(result: @escaping FlutterResult) -> V2TIMFail {\n        return {\n            (code: Int32, desc: Optional<String>) -> Void in\n            result(\n                    FlutterError(code: \"\\(code)\", message: desc ?? \"\", details: desc ?? \"\")\n            );\n        };\n    }\n\n    /// 获得消息对象\n    public static func getMessageByFindMessageEntity(json: String, succ: @escaping GetInfoSuc<V2TIMMessage?>, fail: @escaping V2TIMFail) {\n        getMessageByFindMessageEntity(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json), succ: succ, fail: fail);\n    }\n\n    /// 获得消息对象\n    public static func getMessageByFindMessageEntity(dict: [String: Any], succ: @escaping GetInfoSuc<V2TIMMessage?>, fail: @escaping V2TIMFail) {\n        getMessageByFindMessageEntity(dict: [dict], succ: {\n            (messages: [V2TIMMessage]?) in\n\n            // 消息不存在\n            if messages == nil || messages!.count == 0{\n                fail(-1,\"未找到消息对象!消息ID不存在\");\n                return;\n            }\n\n            succ(messages![0]);\n        }, fail: fail);\n    }\n\n    /// 获得消息对象\n    public static func getMessageByFindMessageEntity(dict: [[String: Any]], succ: @escaping GetInfoSuc<[V2TIMMessage]?>, fail: @escaping V2TIMFail) {\n        var ids: [String] = [];\n        for item in dict {\n            let obj = FindMessageEntity.init(dict: item);\n            ids.append(obj.msgId!);\n        }\n\n        V2TIMManager.sharedInstance()?.findMessages(ids, succ: {\n            (messages: [V2TIMMessage]?) in\n            succ(messages);\n        }, fail: fail)\n    }\n\n    /// 获得群申请对象\n    public static func getGroupApplicationByFindGroupApplicationEntity(json: String, succ: @escaping GetInfoSuc<V2TIMGroupApplication?>, fail: @escaping V2TIMFail) {\n        getGroupApplicationByFindGroupApplicationEntity(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json), succ: succ, fail: fail);\n    }\n\n    /// 获得群申请对象\n    public static func getGroupApplicationByFindGroupApplicationEntity(dict: [String: Any], succ: @escaping GetInfoSuc<V2TIMGroupApplication?>, fail: @escaping V2TIMFail) {\n        let data = FindGroupApplicationEntity.init(dict: dict);\n        V2TIMManager.sharedInstance().getGroupApplicationList({\n            result in\n            if result?.applicationList != nil {\n                for item in result!.applicationList! {\n                    let itemEntity = item as! V2TIMGroupApplication;\n                    if itemEntity.groupID == data.groupID && itemEntity.fromUser == data.fromUser {\n                        succ(itemEntity);\n                        return;\n                    }\n                }\n            }\n            succ(nil);\n        }, fail: fail)\n    }\n\n    /// 获得好友申请对象\n    public static func getFriendApplicationByFindFriendApplicationEntity(json: String, succ: @escaping GetInfoSuc<V2TIMFriendApplication?>, fail: @escaping V2TIMFail) {\n        getFriendApplicationByFindFriendApplicationEntity(dict: JsonUtil.getDictionaryFromJSONString(jsonString: json), succ: succ, fail: fail);\n    }\n\n    /// 获得好友申请对象\n    public static func getFriendApplicationByFindFriendApplicationEntity(dict: [String: Any], succ: @escaping GetInfoSuc<V2TIMFriendApplication?>, fail: @escaping V2TIMFail) {\n        let data = FindFriendApplicationEntity.init(dict: dict);\n        V2TIMManager.sharedInstance().getFriendApplicationList({\n            result in\n            if result?.applicationList != nil {\n                for item in result!.applicationList! {\n                    let itemEntity = item as! V2TIMFriendApplication;\n                    if itemEntity.userID == data.userID && itemEntity.type.rawValue == data.type {\n                        succ(itemEntity);\n                        return;\n                    }\n                }\n            }\n            succ(nil);\n        }, fail: fail)\n    }\n}\n\n/**\n *  获取信息成功回调\n */\npublic typealias GetInfoSuc<T> = (_ array: T) -> Void;\n"
  },
  {
    "path": "ios/tencent_im_plugin.podspec",
    "content": "#\n# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.\n# Run `pod lib lint tencent_im_plugin.podspec' to validate before publishing.\n#\nPod::Spec.new do |s|\n  s.name             = 'tencent_im_plugin'\n  s.version          = '0.0.1'\n  s.summary          = '腾讯云IM插件'\n  s.description      = <<-DESC\n腾讯云IM插件\n                       DESC\n  s.homepage         = 'https://github.com/JiangJuHong/FlutterTencentImPlugin'\n  s.license          = { :file => '../LICENSE' }\n  s.author           = { 'JiangJuHong' => '690717394@qq.com' }\n  s.source           = { :path => '.' }\n  s.source_files = 'Classes/**/*'\n  s.dependency 'Flutter'\n  s.platform = :ios, '8.0'\n\n  # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.\n#   s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }\n  s.swift_version = '5.0'\n\n  # 解决 for architecture arm64 问题\n  s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }\n  s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }\n\n  # 资源导入\n  s.vendored_frameworks = '**/*.framework'\n\n  # SDK 依赖\n  s.dependency 'TXIMSDK_Plus_iOS_Bitcode', '6.1.2155'\n\n  # alibaba json 序列化库(https://github.com/alibaba/HandyJSON)\n  s.dependency 'HandyJSON'\nend\n"
  },
  {
    "path": "lib/entity/conversation_entity.dart",
    "content": "import 'package:tencent_im_plugin/entity/group_at_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_entity.dart';\nimport 'package:tencent_im_plugin/enums/conversation_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_type_enum.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\nimport 'dart:convert';\n\n/// 会话实体\nclass ConversationEntity {\n  /// 会话ID\n  late String conversationID;\n\n  /// 会话类型\n  late ConversationTypeEnum type;\n\n  /// 用户ID\n  String? userID;\n\n  /// 群ID\n  String? groupID;\n\n  /// 显示名称\n  String? showName;\n\n  /// 头像\n  String? faceUrl;\n\n  /// 接收消息选项（群会话有效）\n  ReceiveMessageOptEnum? recvOpt;\n\n  /// 群类型\n  GroupTypeEnum? groupType;\n\n  /// 未读数量\n  int? unreadCount;\n\n  /// 最后一条消息\n  MessageEntity? lastMessage;\n\n  /// 草稿文本\n  String? draftText;\n\n  /// 草稿时间\n  int? draftTimestamp;\n\n  /// 是否置顶\n  bool? pinned;\n\n  /// @信息列表\n  List<GroupAtInfoEntity>? groupAtInfoList;\n\n  ConversationEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['conversationID'] != null) conversationID = json['conversationID'];\n    if (json['type'] != null) type = ConversationTypeTool.getByInt(json['type']);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['showName'] != null) showName = json['showName'];\n    if (json['faceUrl'] != null) faceUrl = json['faceUrl'];\n    if (json['recvOpt'] != null) recvOpt = ReceiveMessageOptTool.getByInt(json['recvOpt']);\n    if (json['groupType'] != null) groupType = GroupTypeTool.getByString(json['groupType']);\n    if (json['unreadCount'] != null) unreadCount = json['unreadCount'];\n    if (json['lastMessage'] != null) lastMessage = MessageEntity.fromJson(json[\"lastMessage\"]);\n    if (json['draftText'] != null) draftText = json['draftText'];\n    if (json['draftTimestamp'] != null) draftTimestamp = json['draftTimestamp'];\n    if (json['pinned'] != null) pinned = json['pinned'];\n    if (json['groupAtInfoList'] != null) groupAtInfoList = ListUtil.generateOBJList<GroupAtInfoEntity>(json[\"groupAtInfoList\"]);\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is ConversationEntity && runtimeType == other.runtimeType && conversationID == other.conversationID;\n\n  @override\n  int get hashCode => conversationID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/conversation_result_entity.dart",
    "content": "import 'dart:convert';\n\nimport 'package:tencent_im_plugin/entity/conversation_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 会话结果实体\nclass ConversationResultEntity {\n  /// 下一次分页拉取的游标\n  late int nextSeq;\n\n  /// 会话列表是否已经拉取完毕\n  late bool finished;\n\n  /// 会话列表\n  late List<ConversationEntity> conversationList;\n\n  ConversationResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['nextSeq'] != null) nextSeq = json['nextSeq'];\n    if (json['finished'] != null) finished = json['finished'];\n    if (json['conversationList'] != null)\n      conversationList = ListUtil.generateOBJList<ConversationEntity>(\n          json[\"conversationList\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/download_progress_entity.dart",
    "content": "import 'dart:convert';\n\nimport 'package:tencent_im_plugin/enums/download_type_enum.dart';\n\n/// 下载进度实体\nclass DownloadProgressEntity {\n  /// 消息ID\n  late String msgId;\n\n  /// 当前下载大小\n  late int currentSize;\n\n  /// 总大小\n  late int totalSize;\n\n  /// 下载类型\n  late DownloadTypeEnum type;\n\n  DownloadProgressEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['msgId'] != null) msgId = json[\"msgId\"];\n    if (json['currentSize'] != null) currentSize = json[\"currentSize\"];\n    if (json['totalSize'] != null) totalSize = json[\"totalSize\"];\n    if (json['type'] != null) type = DownloadTypeTool.getByInt(json[\"type\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/error_entity.dart",
    "content": "import 'dart:convert';\n\n/// 错误实体\nclass ErrorEntity {\n  /// 错误码\n  late int code;\n\n  /// 错误描述\n  String? error;\n\n  ErrorEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['code'] != null) code = json['code'];\n    if (json['error'] != null) error = json['error'];\n  }\n}\n"
  },
  {
    "path": "lib/entity/find_friend_application_entity.dart",
    "content": "import 'package:tencent_im_plugin/entity/friend_application_entity.dart';\nimport 'package:tencent_im_plugin/enums/friend_application_type_enum.dart';\n\n/// 查找好友申请实体\nclass FindFriendApplicationEntity {\n  /// 用户ID\n  String userID;\n\n  /// 类型\n  FriendApplicationTypeEnum type;\n\n  FindFriendApplicationEntity({\n    required this.userID,\n    required this.type,\n  });\n\n  /// 根据[data]对象快速转换为查找好友申请实体\n  factory FindFriendApplicationEntity.fromFriendApplicationEntity(FriendApplicationEntity data) {\n    return FindFriendApplicationEntity(userID: data.userID, type: data.type);\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data[\"userID\"] = userID;\n    data[\"type\"] = FriendApplicationTypeTool.toInt(type);\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/entity/find_group_application_entity.dart",
    "content": "/// 查找群申请实体\nclass FindGroupApplicationEntity {\n  /// 来自用户\n  String fromUser;\n\n  /// 群ID\n  String groupID;\n\n  FindGroupApplicationEntity({\n    required this.fromUser,\n    required this.groupID,\n  });\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data[\"fromUser\"] = fromUser;\n    data[\"groupID\"] = groupID;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/entity/find_message_entity.dart",
    "content": "/// 查找消息实体\nclass FindMessageEntity {\n  /// 消息ID\n  String msgId;\n\n  FindMessageEntity({\n    required this.msgId,\n  });\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data[\"msgId\"] = this.msgId;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_add_application_entity.dart",
    "content": "import 'package:tencent_im_plugin/enums/friend_type_enum.dart';\n\n/// 好友添加申请实体\nclass FriendAddApplicationEntity {\n  /// 用户ID\n  String userID;\n\n  /// 好友备注\n  String? friendRemark;\n\n  /// 申请描述\n  String? addWording;\n\n  /// 添加来源\n  String? addSource;\n\n  /// 添加类型\n  FriendTypeEnum addType;\n\n  FriendAddApplicationEntity({\n    required this.userID,\n    this.friendRemark,\n    this.addWording,\n    this.addSource,\n    required this.addType,\n  });\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['userID'] = this.userID;\n    if (this.friendRemark != null) data['friendRemark'] = this.friendRemark;\n    if (this.addWording != null) data['addWording'] = this.addWording;\n    if (this.addSource != null) data['addSource'] = this.addSource;\n    data['addType'] = FriendTypeTool.toInt(this.addType);\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_application_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/friend_application_type_enum.dart';\n\n/// 好友申请实体\nclass FriendApplicationEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 用户昵称\n  String? nickname;\n\n  /// 用户头像\n  String? faceUrl;\n\n  /// 申请时间\n  late int addTime;\n\n  /// 申请来源\n  String? addSource;\n\n  /// 申请描述\n  String? addWording;\n\n  /// 类型\n  late FriendApplicationTypeEnum type;\n\n  FriendApplicationEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['nickname'] != null) nickname = json['nickname'];\n    if (json['faceUrl'] != null) faceUrl = json['faceUrl'];\n    if (json['addTime'] != null) addTime = json['addTime'];\n    if (json['addSource'] != null) addSource = json['addSource'];\n    if (json['addWording'] != null) addWording = json['addWording'];\n    if (json['type'] != null)\n      type = FriendApplicationTypeTool.getByInt(json['type']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_application_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/friend_application_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 好友申请结果实体\nclass FriendApplicationResultEntity {\n  /// 未读数量\n  late int unreadCount;\n\n  /// 好友申请列表\n  late List<FriendApplicationEntity> friendApplicationList;\n\n  FriendApplicationResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['unreadCount'] != null) unreadCount = json['unreadCount'];\n    if (json['friendApplicationList'] != null)\n      friendApplicationList = ListUtil.generateOBJList<FriendApplicationEntity>(\n          json['friendApplicationList']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_check_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/friend_relation_type_enum.dart';\n\n/// 好友检测结果实体\nclass FriendCheckResultEntity {\n  /// 好友 id\n  late String userID;\n\n  /// 返回结果码\n  late int resultCode;\n\n  /// 返回结果描述\n  String? resultInfo;\n\n  /// 好友结果类型\n  FriendRelationTypeEnum? resultType;\n\n  FriendCheckResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['resultCode'] != null) resultCode = json['resultCode'];\n    if (json['resultInfo'] != null) resultInfo = json['resultInfo'];\n    if (json['resultType'] != null)\n      resultType = FriendRelationTypeTool.getByInt(json['resultType']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_group_entity.dart",
    "content": "import 'dart:convert';\n\n/// 好友分组实体\nclass FriendGroupEntity {\n  /// 组名\n  late String name;\n\n  /// 好友数量\n  late int friendCount;\n\n  /// 好友ID列表\n  late List<String> friendIDList;\n\n  FriendGroupEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['name'] != null) name = json['name'];\n    if (json['friendCount'] != null) friendCount = json['friendCount'];\n    if (json['friendIDList'] != null)\n      friendIDList = json['friendIDList']?.cast<String>();\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_info_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/user_entity.dart';\n\n/// 好友信息实体\nclass FriendInfoEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 好友备注\n  String? friendRemark;\n\n  /// 好友分组列表\n  List<String>? friendGroups;\n\n  /// 好友自定义信息\n  Map<String, String>? friendCustomInfo;\n\n  /// 用户信息\n  UserEntity? userProfile;\n\n  FriendInfoEntity({\n    required this.userID,\n    this.friendRemark,\n    this.friendCustomInfo,\n  });\n\n  FriendInfoEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['friendRemark'] != null) friendRemark = json['friendRemark'];\n    if (json['friendGroups'] != null) friendGroups = json['friendGroups']?.cast<String>();\n    if (json['friendCustomInfo'] != null) friendCustomInfo = json['friendCustomInfo']?.cast<String, String>();\n    if (json['userProfile'] != null) userProfile = UserEntity.fromJson(json['userProfile']);\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['userID'] = this.userID;\n    if (this.friendRemark != null) data['friendRemark'] = this.friendRemark;\n    if (this.friendCustomInfo != null) data['friendCustomInfo'] = this.friendCustomInfo;\n    return data;\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is FriendInfoEntity && runtimeType == other.runtimeType && userID == other.userID;\n\n  @override\n  int get hashCode => userID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/friend_info_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/friend_info_entity.dart';\nimport 'package:tencent_im_plugin/enums/friend_relation_type_enum.dart';\n\n/// 好友信息结果实体\nclass FriendInfoResultEntity {\n  /// 结果码\n  late int resultCode;\n\n  /// 结果信息`\n  String? resultInfo;\n\n  /// 好友类型\n  FriendRelationTypeEnum? relation;\n\n  /// 好友信息\n  FriendInfoEntity? friendInfo;\n\n  FriendInfoResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['resultCode'] != null) resultCode = json['resultCode'];\n    if (json['resultInfo'] != null) resultInfo = json['resultInfo'];\n    if (json['relation'] != null)\n      relation = FriendRelationTypeTool.getByInt(json['relation']);\n    if (json['friendInfo'] != null)\n      friendInfo = FriendInfoEntity.fromJson(json['friendInfo']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/friend_operation_result_entity.dart",
    "content": "import 'dart:convert';\n\n/// 好友操作结果实体\nclass FriendOperationResultEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 返回码\n  late int resultCode;\n\n  /// 返回信息\n  String? resultInfo;\n\n  FriendOperationResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['resultCode'] != null) resultCode = json['resultCode'];\n    if (json['resultInfo'] != null) resultInfo = json['resultInfo'];\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_administrator_op_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群管理员操作通知实体\nclass GroupAdministratorOpEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群成员列表\n  List<GroupMemberEntity>? changInfo;\n\n  /// 操作用户\n  GroupMemberEntity? opUser;\n\n  GroupAdministratorOpEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"changInfo\"] != null)\n      changInfo =\n          ListUtil.generateOBJList<GroupMemberEntity>(json['changInfo']);\n    if (json[\"opUser\"] != null)\n      opUser = GroupMemberEntity.fromJson(json[\"opUser\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_application_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/group_application_handler_result_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_application_handler_status_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_application_type_enum.dart';\n\n/// 群申请实体\nclass GroupApplicationEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 获取请求者 ID，请求加群:请求者，邀请加群:邀请人\n  late String fromUser;\n\n  /// 用户昵称\n  String? fromUserNickName;\n\n  /// 用户头像\n  String? fromUserFaceUrl;\n\n  /// 获取处理者 ID, 请求加群:0，邀请加群:被邀请人\n  String? toUser;\n\n  /// 获取群未决添加的时间，单位：秒\n  late int addTime;\n\n  /// 获取请求者添加的附加信息\n  String? requestMsg;\n\n  /// 获取处理者添加的附加信息，只有处理状态不为V2TIMGroupApplication#V2TIM_GROUP_APPLICATION_HANDLE_STATUS_UNHANDLED的时候有效\n  String? handledMsg;\n\n  /// 获取群未决请求类型\n  late GroupApplicationTypeEnum type;\n\n  /// 获取群未决处理状态\n  GroupApplicationHandlerStatusEnum? handleStatus;\n\n  /// 获取群未决处理操作类型，只有处理状态不为V2TIMGroupApplication#V2TIM_GROUP_APPLICATION_HANDLE_STATUS_UNHANDLED的时候有效\n  GroupApplicationHandlerResultEnum? handleResult;\n\n  GroupApplicationEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['fromUser'] != null) fromUser = json['fromUser'];\n    if (json['fromUserNickName'] != null)\n      fromUserNickName = json['fromUserNickName'];\n    if (json['fromUserFaceUrl'] != null)\n      fromUserFaceUrl = json['fromUserFaceUrl'];\n    if (json['toUser'] != null) toUser = json['toUser'];\n    if (json['addTime'] != null) addTime = json['addTime'];\n    if (json['requestMsg'] != null) requestMsg = json['requestMsg'];\n    if (json['handledMsg'] != null) handledMsg = json['handledMsg'];\n    if (json['type'] != null)\n      type = GroupApplicationTypeTool.getByInt(json['type']);\n    if (json['handleStatus'] != null)\n      handleStatus =\n          GroupApplicationHandlerStatusTool.getByInt(json['handleStatus']);\n    if (json['handleResult'] != null)\n      handleResult =\n          GroupApplicationHandlerResultTool.getByInt(json['handleResult']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_application_processed_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\n\n/// 群申请处理\nclass GroupApplicationProcessedEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 操作用户\n  GroupMemberEntity? opUser;\n\n  /// 操作原因\n  String? opReason;\n\n  /// 是否同意加入\n  bool? isAgreeJoin;\n\n  GroupApplicationProcessedEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['opReason'] != null) opReason = json['opReason'];\n    if (json['isAgreeJoin'] != null) isAgreeJoin = json['isAgreeJoin'];\n    if (json[\"opUser\"] != null)\n      opUser = GroupMemberEntity.fromJson(json['opUser']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_application_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_application_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群申请列表结果实体\nclass GroupApplicationResultEntity {\n  /// 未读申请数量\n  late int unreadCount;\n\n  /// 加群的申请列表\n  late List<GroupApplicationEntity> groupApplicationList;\n\n  GroupApplicationResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['unreadCount'] != null) unreadCount = json['unreadCount'];\n    if (json['groupApplicationList'] != null)\n      groupApplicationList = ListUtil.generateOBJList<GroupApplicationEntity>(\n          json['groupApplicationList']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_at_info_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/group_at_type_enum.dart';\n\n/// 群@信息实体\nclass GroupAtInfoEntity {\n  /// Seq序列号\n  int? seq;\n\n  /// @类型\n  GroupAtTypeEnum? atType;\n\n  GroupAtInfoEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['seq'] != null) seq = json[\"seq\"];\n    if (json['atType'] != null)\n      atType = GroupAtTypeTool.getByInt(json[\"atType\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_attribute_changed_entity.dart",
    "content": "import 'dart:convert';\n\n/// 群属性更新实体\nclass GroupAttributeChangedEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 属性对象\n  late Map<String, String> attributes;\n\n  GroupAttributeChangedEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['attributes'] != null)\n      attributes = (json[\"attributes\"] as Map).cast<String, String>();\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_changed_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/group_info_changed_type_enum.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群改变通知实体\nclass GroupChangedEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群改变信息实体\n  late List<GroupChangedInfoEntity> changInfo;\n\n  GroupChangedEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"changInfo\"] != null)\n      changInfo =\n          ListUtil.generateOBJList<GroupChangedInfoEntity>(json['changInfo']);\n  }\n}\n\n/// 群改变实体\nclass GroupChangedInfoEntity {\n  /// 类型\n  late GroupInfoChangedTypeEnum type;\n\n  /// Key\n  String? key;\n\n  /// Value\n  String? value;\n\n  GroupChangedInfoEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['type'] != null)\n      type = GroupInfoChangedTypeTool.getByInt(json['type']);\n    if (json['key'] != null) key = json['key'];\n    if (json['value'] != null) value = json['value'];\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_create_member_entity.dart",
    "content": "import 'package:tencent_im_plugin/enums/group_member_role_enum.dart';\n\n/// 群创建时需要传递的群成员实体\nclass GroupCreateMemberEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 角色\n  GroupMemberRoleEnum? role;\n\n  GroupCreateMemberEntity({\n    required this.userID,\n    this.role,\n  });\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['userID'] = this.userID;\n    if (this.role != null) data['role'] = GroupMemberRoleTool.toInt(this.role!);\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_dismissed_or_recycled_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\n\n/// 群解散或被回收通知实体\nclass GroupDismissedOrRecycledEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 操作用户\n  GroupMemberEntity? opUser;\n\n  GroupDismissedOrRecycledEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"opUser\"] != null)\n      opUser = GroupMemberEntity.fromJson(json[\"opUser\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_info_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/group_add_opt_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_member_role_enum.dart';\nimport 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_type_enum.dart';\n\n/// 群实体\nclass GroupInfoEntity {\n  /// 群ID\n  String? groupID;\n\n  /// 群类型\n  GroupTypeEnum? groupType;\n\n  /// 群名称\n  String? groupName;\n\n  /// 群公告\n  String? notification;\n\n  /// 群简介\n  String? introduction;\n\n  /// 群头像\n  String? faceUrl;\n\n  /// 是否设置了全员禁言\n  bool? allMuted;\n\n  /// 群主ID\n  String? owner;\n\n  /// 创建时间\n  int? createTime;\n\n  /// 加群审批类型。\n  GroupAddOptEnum? groupAddOpt;\n\n  /// 群最近一次群资料修改时间\n  int? lastInfoTime;\n\n  /// 群最近一次发消息时间\n  int? lastMessageTime;\n\n  /// 群成员总数量\n  int? memberCount;\n\n  /// 在线成员数量\n  int? onlineCount;\n\n  /// 群成员角色\n  GroupMemberRoleEnum? role;\n\n  /// 当前用户在此群组中的消息接收选项\n  ReceiveMessageOptEnum? recvOpt;\n\n  /// 当前用户在此群中的加入时间\n  int? joinTime;\n\n  /// 自定义字段\n  Map<String, String>? customInfo;\n\n  GroupInfoEntity({\n    this.groupID,\n    this.groupType,\n    this.groupName,\n    this.notification,\n    this.introduction,\n    this.faceUrl,\n    this.allMuted,\n    this.groupAddOpt,\n    this.customInfo,\n  });\n\n  /// 创建群聊快速方法\n  GroupInfoEntity.create({\n    this.groupID,\n    required this.groupName,\n    required this.groupType,\n    this.introduction,\n  });\n\n  /// 更新群聊信息快速方法\n  GroupInfoEntity.update({\n    required this.groupID,\n    this.groupName,\n    this.notification,\n    this.introduction,\n    this.faceUrl,\n    this.allMuted,\n    this.groupAddOpt,\n    this.customInfo,\n  });\n\n  GroupInfoEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['groupType'] != null) groupType = GroupTypeTool.getByString(json[\"groupType\"]);\n    if (json['groupName'] != null) groupName = json['groupName'];\n    if (json['notification'] != null) notification = json['notification'];\n    if (json['introduction'] != null) introduction = json['introduction'];\n    if (json['faceUrl'] != null) faceUrl = json['faceUrl'];\n    if (json['allMuted'] != null) allMuted = json['allMuted'];\n    if (json['owner'] != null) owner = json['owner'];\n    if (json['createTime'] != null) createTime = json['createTime'];\n    if (json['groupAddOpt'] != null) groupAddOpt = GroupAddOptTool.getByInt(json[\"groupAddOpt\"]);\n    if (json['lastInfoTime'] != null) lastInfoTime = json['lastInfoTime'];\n    if (json['lastMessageTime'] != null) lastMessageTime = json['lastMessageTime'];\n    if (json['memberCount'] != null) memberCount = json['memberCount'];\n    if (json['onlineCount'] != null) onlineCount = json['onlineCount'];\n    if (json['role'] != null) role = GroupMemberRoleTool.getByInt(json[\"role\"]);\n    if (json['recvOpt'] != null) recvOpt = ReceiveMessageOptTool.getByInt(json[\"recvOpt\"]);\n    if (json['joinTime'] != null) joinTime = json['joinTime'];\n    if (json['customInfo'] != null) customInfo = (json['customInfo'] as Map).cast<String, String>();\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['groupID'] = this.groupID;\n    if (this.groupType != null) data['groupType'] = GroupTypeTool.toTypeString(this.groupType!);\n    if (this.groupName != null) data['groupName'] = this.groupName;\n    if (this.notification != null) data['notification'] = this.notification;\n    if (this.introduction != null) data['introduction'] = this.introduction;\n    if (this.faceUrl != null) data['faceUrl'] = this.faceUrl;\n    if (this.allMuted != null) data['allMuted'] = this.allMuted;\n    if (this.groupAddOpt != null) data['groupAddOpt'] = GroupAddOptTool.toInt(this.groupAddOpt!);\n    if (this.customInfo != null) data['customInfo'] = this.customInfo;\n    return data;\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is GroupInfoEntity && runtimeType == other.runtimeType && groupID == other.groupID;\n\n  @override\n  int get hashCode => groupID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/group_info_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_info_entity.dart';\n\n/// 群信息结果实体\nclass GroupInfoResultEntity {\n  /// 返回码，0代表成功，非零代表失败\n  late int resultCode;\n\n  /// 返回消息描述\n  String? resultMessage;\n\n  /// 群信息\n  GroupInfoEntity? groupInfo;\n\n  GroupInfoResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['resultCode'] != null) resultCode = json['resultCode'];\n    if (json['resultMessage'] != null) resultMessage = json['resultMessage'];\n    if (json['groupInfo'] != null)\n      groupInfo = GroupInfoEntity.fromJson(json['groupInfo']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_member_changed_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群成员改变通知实体\nclass GroupMemberChangedEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群成员列表\n  late List<GroupMemberChangedInfoEntity> changInfo;\n\n  GroupMemberChangedEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"changInfo\"] != null)\n      changInfo = ListUtil.generateOBJList<GroupMemberChangedInfoEntity>(\n          json['changInfo']);\n  }\n}\n\n/// 群成员改变信息实体\nclass GroupMemberChangedInfoEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 禁言时长\n  late int muteTime;\n\n  GroupMemberChangedInfoEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['muteTime'] != null) muteTime = json['muteTime'];\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_member_enter_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群成员加入通知实体\nclass GroupMemberEnterEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群成员列表\n  late List<GroupMemberEntity> memberList;\n\n  GroupMemberEnterEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"memberList\"] != null)\n      memberList =\n          ListUtil.generateOBJList<GroupMemberEntity>(json['memberList']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_member_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/group_member_role_enum.dart';\n\n/// 群成员实体\nclass GroupMemberEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 用户昵称\n  String? nickName;\n\n  /// 好友备注\n  String? friendRemark;\n\n  /// 头像URL\n  String? faceUrl;\n\n  /// 角色\n  GroupMemberRoleEnum? role;\n\n  /// 群成员禁言结束时间戳\n  int? muteUntil;\n\n  /// 加入时间\n  int? joinTime;\n\n  /// 自定义字段\n  Map<String, String>? customInfo;\n\n  /// 群成员名片\n  String? nameCard;\n\n  GroupMemberEntity({\n    required this.userID,\n    this.customInfo,\n    this.nameCard,\n  });\n\n  GroupMemberEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['nickName'] != null) nickName = json['nickName'];\n    if (json['friendRemark'] != null) friendRemark = json['friendRemark'];\n    if (json['faceUrl'] != null) faceUrl = json['faceUrl'];\n    if (json['role'] != null) role = GroupMemberRoleTool.getByInt(json['role']);\n    if (json['muteUntil'] != null) muteUntil = json['muteUntil'];\n    if (json['joinTime'] != null) joinTime = json['joinTime'];\n    if (json['customInfo'] != null) customInfo = (json['customInfo'] as Map).cast<String, String>();\n    if (json['nameCard'] != null) nameCard = json['nameCard'];\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['userID'] = this.userID;\n    if (this.customInfo != null) data['customInfo'] = this.customInfo;\n    if (this.nameCard != null) data['nameCard'] = this.nameCard;\n    return data;\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is GroupMemberEntity && runtimeType == other.runtimeType && userID == other.userID;\n\n  @override\n  int get hashCode => userID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/group_member_info_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群成员信息结果实体\nclass GroupMemberInfoResultEntity {\n  /// 获取分页拉取的 seq。如果为 0 表示拉取结束。\n  late int nextSeq;\n\n  /// 群信息\n  List<GroupMemberEntity>? memberInfoList;\n\n  GroupMemberInfoResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['nextSeq'] != null) nextSeq = json['nextSeq'];\n    if (json['memberInfoList'] != null)\n      memberInfoList =\n          ListUtil.generateOBJList<GroupMemberEntity>(json['memberInfoList']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_member_invited_or_kicked_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\n\n/// 群成员邀请或踢出通知实体\nclass GroupMemberInvitedOrKickedEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群成员列表信息\n  List<GroupMemberEntity>? memberList;\n\n  /// 操作用户\n  GroupMemberEntity? opUser;\n\n  GroupMemberInvitedOrKickedEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"memberList\"] != null)\n      memberList =\n          ListUtil.generateOBJList<GroupMemberEntity>(json['memberList']);\n    if (json[\"opUser\"] != null)\n      opUser = GroupMemberEntity.fromJson(json[\"opUser\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_member_leave_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\n\n/// 群成员离开通知实体\nclass GroupMemberLeaveEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群成员信息\n  late GroupMemberEntity member;\n\n  GroupMemberLeaveEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json[\"member\"] != null)\n      member = GroupMemberEntity.fromJson(json[\"member\"]);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_member_operation_result_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/operation_result_enum.dart';\n\n/// 群成员操作结果实体\nclass GroupMemberOperationResultEntity {\n  /// 操作结果\n  late OperationResultEnum result;\n\n  /// 群成员ID\n  late String memberID;\n\n  GroupMemberOperationResultEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['result'] != null)\n      result = OperationResultTool.getByInt(json['result']);\n    if (json['memberID'] != null) memberID = json['memberID'];\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_receive_join_application_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\n\n/// 群加入申请实体\nclass GroupReceiveJoinApplicationEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 群成员\n  GroupMemberEntity? member;\n\n  /// 操作原因\n  String? opReason;\n\n  GroupReceiveJoinApplicationEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['opReason'] != null) opReason = json['opReason'];\n    if (json[\"member\"] != null)\n      member = GroupMemberEntity.fromJson(json['member']);\n  }\n}\n"
  },
  {
    "path": "lib/entity/group_receive_rest_entity.dart",
    "content": "import 'dart:convert';\n\n/// 群接收到REST自定义信息通知实体\nclass GroupReceiveRESTEntity {\n  /// 群ID\n  late String groupID;\n\n  /// 自定义数据\n  String? customData;\n\n  GroupReceiveRESTEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['groupID'] != null) groupID = json['groupID'];\n    if (json['customData'] != null) customData = json['customData'];\n  }\n}\n"
  },
  {
    "path": "lib/entity/message_entity.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/entity/offline_push_info_entity.dart';\nimport 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/message_priority_enum.dart';\nimport 'package:tencent_im_plugin/enums/message_status_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 消息实体\nclass MessageEntity {\n  /// 消息 ID\n  late String msgID;\n\n  /// 消息时间戳\n  int? timestamp;\n\n  /// 消息发送者 userID\n  String? sender;\n\n  /// 消息发送者昵称\n  String? nickName;\n\n  /// 好友备注。如果没有拉取过好友信息或者不是好友，返回 null\n  String? friendRemark;\n\n  /// 发送者头像 url\n  String? faceUrl;\n\n  /// 群组消息，nameCard 为发送者的群名片\n  String? nameCard;\n\n  /// 群组消息，groupID 为接收消息的群组 ID，否则为 null\n  String? groupID;\n\n  /// 单聊消息，userID 为会话用户 ID，否则为 null。 假设自己和 userA 聊天，无论是自己发给 userA 的消息还是 userA 发给自己的消息，这里的 userID 均为 userA\n  String? userID;\n\n  /// 消息发送状态\n  MessageStatusEnum? status;\n\n  /// 消息类型\n  MessageElemTypeEnum? elemType;\n\n  /// 消息自定义数据（本地保存，不会发送到对端，程序卸载重装后失效）\n  String? localCustomData;\n\n  /// 消息自定义数据（本地保存，不会发送到对端，程序卸载重装后失效）\n  int? localCustomInt;\n\n  /// 消息发送者是否是自己\n  bool? self;\n\n  /// 消息自己是否已读\n  bool? read;\n\n  /// 消息对方是否已读（只有 C2C 消息有效）\n  bool? peerRead;\n\n  /// 消息优先级\n  MessagePriorityEnum? priority;\n\n  /// 消息的离线推送信息\n  OfflinePushInfoEntity? offlinePushInfo;\n\n  /// 群@用户列表\n  List<String>? groupAtUserList;\n\n  /// 消息的序列号\n  /// 群聊中的消息序列号云端生成，在群里是严格递增且唯一的。 单聊中的序列号是本地生成，不能保证严格递增且唯一。\n  int? seq;\n\n  /// 描述信息，描述当前消息，可直接用于显示\n  String? note;\n\n  /// 消息节点信息\n  MessageNode? node;\n\n  /// 消息随机码\n  int? random;\n\n  MessageEntity({\n    required this.msgID,\n    this.timestamp,\n    this.sender,\n    this.nickName,\n    this.friendRemark,\n    this.faceUrl,\n    this.nameCard,\n    this.groupID,\n    this.userID,\n    required this.status,\n    this.elemType,\n    this.localCustomData,\n    this.localCustomInt,\n    this.self: true,\n    this.read: true,\n    this.peerRead: false,\n    this.priority,\n    this.offlinePushInfo,\n    this.groupAtUserList,\n    this.seq,\n    this.note,\n    this.node,\n    this.random,\n  });\n\n  MessageEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['msgID'] != null) msgID = json[\"msgID\"];\n    if (json['timestamp'] != null) timestamp = json[\"timestamp\"];\n    if (json['sender'] != null) sender = json[\"sender\"];\n    if (json['nickName'] != null) nickName = json[\"nickName\"];\n    if (json['friendRemark'] != null) friendRemark = json[\"friendRemark\"];\n    if (json['faceUrl'] != null) faceUrl = json[\"faceUrl\"];\n    if (json['nameCard'] != null) nameCard = json[\"nameCard\"];\n    if (json['groupID'] != null) groupID = json[\"groupID\"];\n    if (json['userID'] != null) userID = json[\"userID\"];\n    if (json[\"status\"] != null)\n      status = MessageStatusTool.getByInt(json[\"status\"]);\n    if (json[\"elemType\"] != null)\n      elemType = MessageElemTypeTool.getByInt(json[\"elemType\"]);\n    if (json['localCustomData'] != null)\n      localCustomData = json[\"localCustomData\"];\n    if (json['localCustomInt'] != null) localCustomInt = json[\"localCustomInt\"];\n    if (json[\"self\"] != null) self = json[\"self\"];\n    if (json[\"read\"] != null) read = json[\"read\"];\n    if (json[\"peerRead\"] != null) peerRead = json[\"peerRead\"];\n    if (json[\"priority\"] != null)\n      priority = MessagePriorityTool.getByInt(json[\"priority\"]);\n    if (json[\"offlinePushInfo\"] != null)\n      offlinePushInfo = OfflinePushInfoEntity.fromJson(json[\"offlinePushInfo\"]);\n    if (json['groupAtUserList'] != null)\n      groupAtUserList = json[\"groupAtUserList\"]?.cast<String>();\n    if (json['seq'] != null) seq = json[\"seq\"];\n    if (json['note'] != null) note = json[\"note\"];\n    if (json['node'] != null)\n      node = MessageElemTypeTool.getMessageNodeByMessageNodeType(\n          elemType!, json[\"node\"]);\n    if (json['random'] != null) random = json[\"random\"];\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['msgID'] = this.msgID;\n    if (this.timestamp != null) data['timestamp'] = this.timestamp;\n    if (this.sender != null) data['sender'] = this.sender;\n    if (this.nickName != null) data['nickName'] = this.nickName;\n    if (this.friendRemark != null) data['friendRemark'] = this.friendRemark;\n    if (this.faceUrl != null) data['faceUrl'] = this.faceUrl;\n    if (this.nameCard != null) data['nameCard'] = this.nameCard;\n    if (this.groupID != null) data['groupID'] = this.groupID;\n    if (this.userID != null) data['userID'] = this.userID;\n    if (this.status != null)\n      data['status'] = MessageStatusTool.toInt(this.status!);\n    if (this.elemType != null)\n      data['elemType'] = MessageElemTypeTool.toInt(this.elemType!);\n    if (this.localCustomData != null)\n      data['localCustomData'] = this.localCustomData;\n    if (this.localCustomInt != null)\n      data['localCustomInt'] = this.localCustomInt;\n    if (this.self != null) data['self'] = this.self;\n    if (this.read != null) data['read'] = this.read;\n    if (this.peerRead != null) data['peerRead'] = this.peerRead;\n    if (this.priority != null)\n      data['priority'] = MessagePriorityTool.toInt(this.priority!);\n    if (this.offlinePushInfo != null)\n      data['offlinePushInfo'] = this.offlinePushInfo!.toJson();\n    if (this.groupAtUserList != null)\n      data['groupAtUserList'] = this.groupAtUserList;\n    if (this.seq != null) data['seq'] = this.seq;\n    if (this.note != null) data['note'] = this.note;\n    if (this.random != null) data['random'] = this.random;\n    return data;\n  }\n\n  @override\n  bool operator ==(Object other) =>\n      identical(this, other) ||\n      other is MessageEntity &&\n          runtimeType == other.runtimeType &&\n          msgID == other.msgID;\n\n  @override\n  int get hashCode => msgID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/message_receipt_entity.dart",
    "content": "import 'dart:convert';\n\n/// 消息回执实体\nclass MessageReceiptEntity {\n  /// 用户ID\n  late String userID;\n\n  /// 时间\n  int? timestamp;\n\n  MessageReceiptEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json[\"userID\"];\n    if (json['timestamp'] != null) timestamp = json[\"timestamp\"];\n  }\n}\n"
  },
  {
    "path": "lib/entity/message_search_param.dart",
    "content": "// To parse this JSON data, do\n//\n//     final messageSearchParam = messageSearchParamFromJson(jsonString);\n\nimport 'dart:convert';\n\n/// 消息搜索参数对象\nclass MessageSearchParam {\n  MessageSearchParam({\n    this.conversationId,\n    this.keyword,\n    this.keywordMatchType,\n    this.senderUserIds,\n    this.messageTypes,\n    this.searchTimePosition,\n    this.searchTimePeriod,\n    this.pageSize,\n    this.pageIndex,\n  });\n\n  /// 指定会话ID\n  final String? conversationId;\n\n  /// 指定关键字，最多支持5个\n  final List<String>? keyword;\n\n  /// 关键字匹配类型\n  final int? keywordMatchType;\n\n  /// 发送人ID列表\n  final List<String>? senderUserIds;\n\n  /// 消息类型列表\n  final List<int>? messageTypes;\n\n  /// 搜索的起始时间点。默认为0即代表从现在开始搜索。UTC 时间戳，单位：秒\n  final int? searchTimePosition;\n\n  /// 从起始时间点开始的过去时间范围，单位秒。默认为0即代表不限制时间范围，传24x60x60代表过去一天。\n  final int? searchTimePeriod;\n\n  /// 每页结果数量：用于分页展示查找结果，如不希望分页可将其设置成 0，但如果结果太多，可能会带来性能问题。\n  final int? pageSize;\n\n  /// 分页的页号：用于分页展示查找结果，从零开始起步。 比如：您希望每页展示 10 条结果，请按照如下规则调用： - 首次调用：通过参数 pageSize = 10, pageIndex = 0 调用 searchLocalMessage，从结果回调中的 totalCount 可以获知总共有多少条结果。 - 计算页数：可以获知总页数：totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1) 。 - 再次调用：可以通过指定参数 pageIndex （pageIndex < totalPage）返回后续页号的结果。\n  final int? pageIndex;\n\n  factory MessageSearchParam.fromRawJson(String str) => MessageSearchParam.fromJson(json.decode(str));\n\n  String toRawJson() => json.encode(toJson());\n\n  factory MessageSearchParam.fromJson(Map<String, dynamic> json) => MessageSearchParam(\n        conversationId: json[\"conversationID\"] == null ? null : json[\"conversationID\"],\n        keyword: json[\"keyword\"] == null ? null : List<String>.from(json[\"keyword\"].map((x) => x)),\n        keywordMatchType: json[\"keywordMatchType\"] == null ? null : json[\"keywordMatchType\"],\n        senderUserIds: json[\"senderUserIds\"] == null ? null : List<String>.from(json[\"senderUserIds\"].map((x) => x)),\n        messageTypes: json[\"messageTypes\"] == null ? null : List<int>.from(json[\"messageTypes\"].map((x) => x)),\n        searchTimePosition: json[\"searchTimePosition\"] == null ? null : json[\"searchTimePosition\"],\n        searchTimePeriod: json[\"searchTimePeriod\"] == null ? null : json[\"searchTimePeriod\"],\n        pageSize: json[\"pageSize\"] == null ? null : json[\"pageSize\"],\n        pageIndex: json[\"pageIndex\"] == null ? null : json[\"pageIndex\"],\n      );\n\n  Map<String, dynamic> toJson() => {\n        \"conversationID\": conversationId == null ? null : conversationId,\n        \"keyword\": keyword == null ? null : List<dynamic>.from(keyword!.map((x) => x)),\n        \"keywordMatchType\": keywordMatchType == null ? null : keywordMatchType,\n        \"senderUserIds\": senderUserIds == null ? null : List<dynamic>.from(senderUserIds!.map((x) => x)),\n        \"messageTypes\": messageTypes == null ? null : List<dynamic>.from(messageTypes!.map((x) => x)),\n        \"searchTimePosition\": searchTimePosition == null ? null : searchTimePosition,\n        \"searchTimePeriod\": searchTimePeriod == null ? null : searchTimePeriod,\n        \"pageSize\": pageSize == null ? null : pageSize,\n        \"pageIndex\": pageIndex == null ? null : pageIndex,\n      };\n}\n"
  },
  {
    "path": "lib/entity/message_send_fail_entity.dart",
    "content": "import 'dart:convert';\n\n/// 消息发送失败实体\nclass MessageSendFailEntity {\n  /// 消息ID\n  late String msgId;\n\n  /// 错误码\n  late int code;\n\n  /// 错误描述\n  String? desc;\n\n  MessageSendFailEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['msgId'] != null) msgId = json[\"msgId\"];\n    if (json['code'] != null) code = json[\"code\"];\n    if (json['desc'] != null) desc = json[\"desc\"];\n  }\n}\n"
  },
  {
    "path": "lib/entity/message_send_progress_entity.dart",
    "content": "import 'dart:convert';\n\n/// 消息发送进度实体\nclass MessageSendProgressEntity {\n  /// 消息ID\n  late String msgId;\n\n  /// 发送进度\n  late int progress;\n\n  MessageSendProgressEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['msgId'] != null) msgId = json[\"msgId\"];\n    if (json['progress'] != null) progress = json[\"progress\"];\n  }\n}\n"
  },
  {
    "path": "lib/entity/offline_push_info_entity.dart",
    "content": "import 'dart:convert';\n\n/// 离线推送信息实体\nclass OfflinePushInfoEntity {\n  /// 通知栏标题\n  String? title;\n\n  /// 通知栏内容\n  String? desc;\n\n  /// 通知栏透传信息\n  String? ext;\n\n  /// 离线推送声音设置（仅对 iOS 生效）。 当 sound = IOS_OFFLINE_PUSH_NO_SOUND，表示接收时不会播放声音。 如果要自定义 iOSSound，需要先把语音文件链接进 Xcode 工程，然后把语音文件名（带后缀）设置给 iOSSound。\n  String? iOSSound;\n\n  /// 离线推送忽略 badge 计数（仅对 iOS 生效）， 如果设置为 true，在 iOS 接收端，这条消息不会使 APP 的应用图标未读计数增加。\n  bool? ignoreIOSBadge;\n\n  /// 离线推送设置 OPPO 手机 8.0 系统及以上的渠道 ID。\n  String? androidOPPOChannelID;\n\n  /// 获取是否关闭离线推送状态。\n  bool? disablePush;\n\n  OfflinePushInfoEntity({\n    this.title,\n    this.desc,\n    this.ext,\n    this.iOSSound,\n    this.ignoreIOSBadge,\n    this.androidOPPOChannelID,\n    this.disablePush,\n  });\n\n  OfflinePushInfoEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['title'] != null) title = json[\"title\"];\n    if (json['desc'] != null) desc = json[\"desc\"];\n    if (json['ext'] != null) ext = json[\"ext\"];\n    if (json['iOSSound'] != null) iOSSound = json[\"iOSSound\"];\n    if (json['ignoreIOSBadge'] != null) ignoreIOSBadge = json[\"ignoreIOSBadge\"];\n    if (json['androidOPPOChannelID'] != null)\n      androidOPPOChannelID = json[\"androidOPPOChannelID\"];\n    if (json['disablePush'] != null) disablePush = json[\"disablePush\"];\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    if (this.title != null) data['title'] = this.title;\n    if (this.desc != null) data['desc'] = this.desc;\n    if (this.ext != null) data['ext'] = this.ext;\n    if (this.iOSSound != null) data['iOSSound'] = this.iOSSound;\n    if (this.ignoreIOSBadge != null)\n      data['ignoreIOSBadge'] = this.ignoreIOSBadge;\n    if (this.androidOPPOChannelID != null)\n      data['androidOPPOChannelID'] = this.androidOPPOChannelID;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/entity/signaling_common_entity.dart",
    "content": "import 'dart:convert';\n\n/// 信令通用实体\nclass SignalingCommonEntity {\n  /// 邀请ID\n  late String inviteID;\n\n  /// 邀请人\n  String? inviter;\n\n  /// 群ID\n  String? groupID;\n\n  /// 受邀人，一般是拒绝/接受时此内容才会有值\n  String? invitee;\n\n  /// 被邀请人列表\n  List<String>? inviteeList;\n\n  /// 消息内容\n  String? data;\n\n  SignalingCommonEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['inviteID'] != null) inviteID = json[\"inviteID\"];\n    if (json['inviter'] != null) inviter = json[\"inviter\"];\n    if (json['groupID'] != null) groupID = json[\"groupID\"];\n    if (json['invitee'] != null) invitee = json[\"invitee\"];\n    if (json['inviteeList'] != null) inviteeList = json[\"inviteeList\"]?.cast<String>();\n    if (json['data'] != null) this.data = json[\"data\"];\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is SignalingCommonEntity && runtimeType == other.runtimeType && inviteID == other.inviteID;\n\n  @override\n  int get hashCode => inviteID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/signaling_info_entity.dart",
    "content": "import 'dart:convert';\n\nimport 'package:tencent_im_plugin/entity/offline_push_info_entity.dart';\nimport 'package:tencent_im_plugin/enums/signaling_action_type_enum.dart';\nimport 'package:uuid/uuid.dart';\n\n/// 信令信息实体\nclass SignalingInfoEntity {\n  /// 邀请ID\n  String? inviteID;\n\n  /// 群ID\n  String? groupID;\n\n  /// 邀请人\n  String? inviter;\n\n  /// 被邀请人\n  List<String>? inviteeList;\n\n  /// 数据\n  String? data;\n\n  /// 超时\n  int? timeout;\n\n  /// 类型\n  SignalingActionTypeEnum? actionType;\n\n  /// ID\n  int? businessID;\n\n  /// 是否仅在线用户\n  bool? onlineUserOnly;\n\n  /// 离线推送信息\n  OfflinePushInfoEntity? offlinePushInfo;\n\n  SignalingInfoEntity({\n    this.inviteID,\n    this.groupID,\n    required this.inviter,\n    required this.inviteeList,\n    required this.data,\n    this.timeout: 0,\n    required this.actionType,\n    this.businessID: 0,\n    this.onlineUserOnly: false,\n  });\n\n  SignalingInfoEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['inviteID'] != null) inviteID = json[\"inviteID\"];\n    if (json['groupID'] != null) groupID = json[\"groupID\"];\n    if (json['inviter'] != null) inviter = json[\"inviter\"];\n    if (json['inviteeList'] != null) inviteeList = json[\"inviteeList\"].cast<String>();\n    if (json['data'] != null) this.data = json[\"data\"];\n    if (json['timeout'] != null) timeout = json[\"timeout\"];\n    if (json['actionType'] != null) if (json[\"actionType\"] != null) actionType = SignalingActionTypeTool.getByInt(json[\"actionType\"]);\n    if (json['businessID'] != null) businessID = json[\"businessID\"];\n    if (json['onlineUserOnly'] != null) onlineUserOnly = json[\"onlineUserOnly\"];\n    if (json[\"offlinePushInfo\"] != null) offlinePushInfo = OfflinePushInfoEntity.fromJson(json[\"offlinePushInfo\"]);\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data['inviteID'] = this.inviteID ?? Uuid().v4().toString();\n    if (this.groupID != null) data['groupID'] = this.groupID;\n    if (this.inviter != null) data['inviter'] = this.inviter;\n    if (this.inviteeList != null) data['inviteeList'] = this.inviteeList;\n    if (this.data != null) data['data'] = this.data;\n    if (this.timeout != null) data['timeout'] = this.timeout;\n    if (this.actionType != null) data['actionType'] = SignalingActionTypeTool.toInt(this.actionType!);\n    if (this.businessID != null) data['businessID'] = this.businessID;\n    if (this.onlineUserOnly != null) data['onlineUserOnly'] = this.onlineUserOnly;\n    return data;\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is SignalingInfoEntity && runtimeType == other.runtimeType && inviteID == other.inviteID;\n\n  @override\n  int get hashCode => inviteID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity/user_entity.dart",
    "content": "import 'dart:convert';\n\nimport 'package:tencent_im_plugin/enums/user_allow_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/user_gender_enum.dart';\n\n/// 用户实体\nclass UserEntity {\n  /// ID\n  late String userID;\n\n  /// 昵称\n  String? nickName;\n\n  /// 头像\n  String? faceUrl;\n\n  /// 签名\n  String? selfSignature;\n\n  /// 性别\n  UserGenderEnum? gender;\n\n  /// 角色\n  int? role;\n\n  /// 等级\n  int? level;\n\n  /// 生日\n  int? birthday;\n\n  /// 好友验证方式\n  UserAllowTypeEnum? allowType;\n\n  /// 自定义字段\n  Map<String, String>? customInfo;\n\n  UserEntity({\n    this.nickName,\n    this.faceUrl,\n    this.selfSignature,\n    this.gender,\n    this.role,\n    this.level,\n    this.allowType,\n    this.customInfo,\n  });\n\n  UserEntity.fromJson(data) {\n    Map<String, dynamic> json = data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['userID'] != null) userID = json['userID'];\n    if (json['nickName'] != null) nickName = json['nickName'];\n    if (json['faceUrl'] != null) faceUrl = json['faceUrl'];\n    if (json['selfSignature'] != null) selfSignature = json['selfSignature'];\n    if (json['gender'] != null) gender = UserGenderTool.getByInt(json['gender']);\n    if (json['role'] != null) role = json['role'];\n    if (json['level'] != null) level = json['level'];\n    if (json['birthday'] != null) birthday = json['birthday'];\n    if (json['allowType'] != null) allowType = UserAllowTypeTool.getByInt(json['allowType']);\n    if (json['customInfo'] != null) customInfo = (json['customInfo'] as Map).cast<String, String>();\n  }\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    if (this.nickName != null) data['nickName'] = this.nickName;\n    if (this.faceUrl != null) data['faceUrl'] = this.faceUrl;\n    if (this.selfSignature != null) data['selfSignature'] = this.selfSignature;\n    if (this.gender != null) data['gender'] = UserGenderTool.toInt(this.gender!);\n    if (this.role != null) data['role'] = this.role;\n    if (this.level != null) data['level'] = this.level;\n    if (this.birthday != null) data['birthday'] = this.birthday;\n    if (this.allowType != null) data['allowType'] = UserAllowTypeTool.toInt(this.allowType!);\n    if (this.customInfo != null) data['customInfo'] = this.customInfo;\n    return data;\n  }\n\n  @override\n  bool operator ==(Object other) => identical(this, other) || other is UserEntity && runtimeType == other.runtimeType && userID == other.userID;\n\n  @override\n  int get hashCode => userID.hashCode;\n}\n"
  },
  {
    "path": "lib/entity_factory.dart",
    "content": "import 'dart:convert';\n\nimport 'package:tencent_im_plugin/entity/friend_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_application_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_group_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_operation_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_at_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_info_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_operation_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_receipt_entity.dart';\nimport 'package:tencent_im_plugin/entity/user_entity.dart';\nimport 'entity/conversation_entity.dart';\n\nclass EntityFactory {\n  static T? generateOBJ<T>(json) {\n    if (json is String) {\n      json = jsonDecode(json);\n    }\n\n    if (1 == 0) {\n      return null;\n    } else if (T.toString() == \"GroupInfoEntity\") {\n      return GroupInfoEntity.fromJson(json) as T;\n    } else if (T.toString() == \"MessageEntity\") {\n      return MessageEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupMemberEntity\") {\n      return GroupMemberEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupInfoResultEntity\") {\n      return GroupInfoResultEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupMemberOperationResultEntity\") {\n      return GroupMemberOperationResultEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupApplicationEntity\") {\n      return GroupApplicationEntity.fromJson(json) as T;\n    } else if (T.toString() == \"ConversationEntity\") {\n      return ConversationEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupAtInfoEntity\") {\n      return GroupAtInfoEntity.fromJson(json) as T;\n    } else if (T.toString() == \"UserEntity\") {\n      return UserEntity.fromJson(json) as T;\n    } else if (T.toString() == \"FriendOperationResultEntity\") {\n      return FriendOperationResultEntity.fromJson(json) as T;\n    } else if (T.toString() == \"FriendInfoEntity\") {\n      return FriendInfoEntity.fromJson(json) as T;\n    } else if (T.toString() == \"FriendInfoResultEntity\") {\n      return FriendInfoResultEntity.fromJson(json) as T;\n    } else if (T.toString() == \"FriendApplicationResultEntity\") {\n      return FriendApplicationResultEntity.fromJson(json) as T;\n    } else if (T.toString() == \"FriendApplicationEntity\") {\n      return FriendApplicationEntity.fromJson(json) as T;\n    } else if (T.toString() == \"FriendGroupEntity\") {\n      return FriendGroupEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupChangedInfoEntity\") {\n      return GroupChangedInfoEntity.fromJson(json) as T;\n    } else if (T.toString() == \"GroupMemberChangedInfoEntity\") {\n      return GroupMemberChangedInfoEntity.fromJson(json) as T;\n    } else if (T.toString() == \"MessageReceiptEntity\") {\n      return MessageReceiptEntity.fromJson(json) as T;\n    } else {\n      return null;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/conversation_type_enum.dart",
    "content": "/// 会话类型枚举\nenum ConversationTypeEnum {\n  /// 非法类型\n  Invalid,\n\n  /// 单聊\n  C2C,\n\n  /// 群聊\n  Group,\n}\n\nclass ConversationTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static ConversationTypeEnum getByInt(int index) =>\n      ConversationTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(ConversationTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/download_type_enum.dart",
    "content": "/// 下载类型枚举\nenum DownloadTypeEnum {\n  /// 语音\n  Sound,\n\n  /// 视频\n  Video,\n\n  /// 视频缩略图\n  VideoThumbnail,\n\n  /// 文件对象\n  File,\n}\n\nclass DownloadTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static DownloadTypeEnum getByInt(int index) => DownloadTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(DownloadTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/friend_application_agree_type_enum.dart",
    "content": "/// 好友申请接收时类型枚举\nenum FriendApplicationAgreeTypeEnum {\n  // 同意加好友（建立单向好友）\n  Agree,\n  // 同意加好友并加对方为好友（建立双向好友）\n  AgreeAndAdd,\n}\n\n/// 枚举工具\nclass FriendApplicationAgreeTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static FriendApplicationAgreeTypeEnum getByInt(int index) =>\n      FriendApplicationAgreeTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(FriendApplicationAgreeTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/friend_application_type_enum.dart",
    "content": "/// 好友申请类型枚举\nenum FriendApplicationTypeEnum {\n  // 别人发给我的加好友请求\n  ComeIn,\n  // 我发给别人的加好友请求\n  SendOut,\n  // 别人发给我的和我发给别人的加好友请求。仅在拉取时有效。\n  Both,\n}\n\n/// 枚举工具\nclass FriendApplicationTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static FriendApplicationTypeEnum getByInt(int index) =>\n      FriendApplicationTypeEnum.values[index - 1];\n\n  /// 将枚举转换为整型\n  static int toInt(FriendApplicationTypeEnum level) => level.index + 1;\n}\n"
  },
  {
    "path": "lib/enums/friend_relation_type_enum.dart",
    "content": "/// 好友关系枚举\nenum FriendRelationTypeEnum {\n  // 不是好友\n  None,\n  // 在我的好友列表\n  MyFriendList,\n  // 我在对方好友列表\n  OtherFriendList,\n  // 互为好友\n  BothWay,\n}\n\n/// 枚举工具\nclass FriendRelationTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static FriendRelationTypeEnum getByInt(int index) =>\n      FriendRelationTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(FriendRelationTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/friend_status_enum.dart",
    "content": "/// 好友状态枚举\nenum FriendStatusEnum {\n  /// 操作成功\n  SUCC,\n\n  /// 请求参数错误，请根据错误描述检查请求是否正确\n  PARAM_INVALID,\n\n  /// 加好友、响应好友时有效：自己的好友数已达系统上限\n  SELF_FRIEND_FULL,\n\n  /// 加好友、响应好友时有效：对方的好友数已达系统上限\n  THEIR_FRIEND_FULL,\n\n  /// 加好友时有效：被加好友在自己的黑名单中\n  IN_SELF_BLACK_LIST,\n\n  /// 加好友时有效：被加好友设置为禁止加好友\n  FRIEND_SIDE_FORBID_ADD,\n\n  /// 加好友时有效：已被被添加好友设置为黑名单\n  IN_OTHER_SIDE_BLACK_LIST,\n\n  /// 加好友时有效：等待好友审核同意\n  PENDING\n}\n\n/// 枚举工具\nclass FriendStatusEnumTool {\n  /// 根据数标获得枚举\n  static FriendStatusEnum? getEnumByIndex(index) {\n    switch (index) {\n      case 0:\n        return FriendStatusEnum.SUCC;\n      case 30001:\n        return FriendStatusEnum.PARAM_INVALID;\n      case 30010:\n        return FriendStatusEnum.SELF_FRIEND_FULL;\n      case 30014:\n        return FriendStatusEnum.THEIR_FRIEND_FULL;\n      case 30515:\n        return FriendStatusEnum.IN_SELF_BLACK_LIST;\n      case 30516:\n        return FriendStatusEnum.FRIEND_SIDE_FORBID_ADD;\n      case 30525:\n        return FriendStatusEnum.IN_OTHER_SIDE_BLACK_LIST;\n      case 30539:\n        return FriendStatusEnum.PENDING;\n      default:\n        return null;\n    }\n  }\n\n  /// 根据枚举获得数标\n  static int? getIndexByEnum(e) {\n    switch (e) {\n      case FriendStatusEnum.SUCC:\n        return 0;\n      case FriendStatusEnum.PARAM_INVALID:\n        return 30001;\n      case FriendStatusEnum.SELF_FRIEND_FULL:\n        return 30010;\n      case FriendStatusEnum.THEIR_FRIEND_FULL:\n        return 30514;\n      case FriendStatusEnum.IN_SELF_BLACK_LIST:\n        return 30515;\n      case FriendStatusEnum.FRIEND_SIDE_FORBID_ADD:\n        return 30516;\n      case FriendStatusEnum.IN_OTHER_SIDE_BLACK_LIST:\n        return 30525;\n      case FriendStatusEnum.PENDING:\n        return 30539;\n      default:\n        return null;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/friend_type_enum.dart",
    "content": "/// 好友类型枚举\nenum FriendTypeEnum {\n  // 单项加好友\n  Single,\n  // 双向加好友\n  Both,\n}\n\n/// 枚举工具\nclass FriendTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static FriendTypeEnum getByInt(int index) => FriendTypeEnum.values[index - 1];\n\n  /// 将枚举转换为整型\n  static int toInt(FriendTypeEnum level) => level.index + 1;\n}\n"
  },
  {
    "path": "lib/enums/get_message_type_enum.dart",
    "content": "/// 获得消息类型枚举\nenum GetMessageTypeEnum {\n  // 云端更老的消息\n  GetCloudOlderMsg,\n  // 云端更新的消息\n  GetCloudNewerMsg,\n  // 本地更老的消息\n  GetLocalOlderMsg,\n  // 本地更新的消息\n  GetLocalNewerMsg,\n}\n\n/// 枚举工具\nclass GetMessageTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GetMessageTypeEnum getByInt(int index) =>\n      GetMessageTypeEnum.values[index - 1];\n\n  /// 将枚举转换为整型\n  static int toInt(GetMessageTypeEnum level) => level.index + 1;\n}\n"
  },
  {
    "path": "lib/enums/group_add_opt_enum.dart",
    "content": "/// 加群选项\nenum GroupAddOptEnum {\n  /// 禁止加群\n  Forbid,\n\n  /// 需要管理员审批\n  Auth,\n\n  /// 自由加入\n  Any,\n}\n\nclass GroupAddOptTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupAddOptEnum getByInt(int index) => GroupAddOptEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupAddOptEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/group_application_handler_result_enum.dart",
    "content": "/// 群申请处理结果枚举\nenum GroupApplicationHandlerResultEnum {\n  /// 拒绝\n  Refuse,\n\n  /// 接收\n  Agree,\n}\n\nclass GroupApplicationHandlerResultTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupApplicationHandlerResultEnum getByInt(int index) =>\n      GroupApplicationHandlerResultEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupApplicationHandlerResultEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/group_application_handler_status_enum.dart",
    "content": "/// 群申请处理状态枚举\nenum GroupApplicationHandlerStatusEnum {\n  /// 未处理\n  Unhandled,\n\n  /// 其他人处理\n  ByOther,\n\n  /// 自己已处理\n  BySelf,\n}\n\nclass GroupApplicationHandlerStatusTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupApplicationHandlerStatusEnum getByInt(int index) =>\n      GroupApplicationHandlerStatusEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupApplicationHandlerStatusEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/group_application_type_enum.dart",
    "content": "/// 群申请类型枚举\nenum GroupApplicationTypeEnum {\n  /// 主动申请\n  Join,\n\n  /// 被邀请\n  Invite,\n}\n\nclass GroupApplicationTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupApplicationTypeEnum getByInt(int index) =>\n      GroupApplicationTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupApplicationTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/group_at_type_enum.dart",
    "content": "/// 群@类型枚举\nenum GroupAtTypeEnum {\n  /// 非法类型\n  Unknown,\n\n  /// @我\n  AtMe,\n\n  /// @所有人\n  AtAll,\n\n  /// @群里所有人，并单独@我\n  AtAllAtMe\n}\n\nclass GroupAtTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupAtTypeEnum getByInt(int index) => GroupAtTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupAtTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/group_info_changed_type_enum.dart",
    "content": "/// 群信息改变类型枚举\nenum GroupInfoChangedTypeEnum {\n  /// 非法值\n  Invalid,\n\n  /// 群名\n  Name,\n\n  /// 群简介\n  Introduction,\n\n  /// 群公告\n  Notification,\n\n  /// 群头像\n  FaceUrl,\n\n  /// 群主\n  Owner,\n\n  /// 自定义字段\n  Custom,\n}\n\nclass GroupInfoChangedTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupInfoChangedTypeEnum getByInt(int index) =>\n      GroupInfoChangedTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupInfoChangedTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/group_member_filter_enum.dart",
    "content": "/// 群成员过滤枚举\nenum GroupMemberFilterEnum {\n  /// 所有类型\n  All,\n\n  /// 群主\n  Owner,\n\n  /// 群管理员\n  Admin,\n\n  /// 普通群成员\n  Common,\n}\n\nclass GroupMemberFilterTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupMemberFilterEnum getByInt(int index) {\n    switch (index) {\n      case 0:\n        return GroupMemberFilterEnum.All;\n      case 1:\n        return GroupMemberFilterEnum.Owner;\n      case 2:\n        return GroupMemberFilterEnum.Admin;\n      case 4:\n        return GroupMemberFilterEnum.Common;\n    }\n    throw ArgumentError(\"参数异常\");\n  }\n\n  /// 将枚举转换为整型\n  static int toInt(GroupMemberFilterEnum role) {\n    switch (role) {\n      case GroupMemberFilterEnum.All:\n        return 0;\n      case GroupMemberFilterEnum.Owner:\n        return 1;\n      case GroupMemberFilterEnum.Admin:\n        return 2;\n      case GroupMemberFilterEnum.Common:\n        return 4;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/group_member_role_enum.dart",
    "content": "/// 群成员角色枚举\nenum GroupMemberRoleEnum {\n  /// 未定义\n  Undefined,\n\n  /// 群成员\n  Member,\n\n  /// 群管理员\n  Admin,\n\n  /// 群主\n  Owner,\n}\n\nclass GroupMemberRoleTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupMemberRoleEnum getByInt(int index) {\n    switch (index) {\n      case 0:\n        return GroupMemberRoleEnum.Undefined;\n      case 200:\n        return GroupMemberRoleEnum.Member;\n      case 300:\n        return GroupMemberRoleEnum.Admin;\n      case 400:\n        return GroupMemberRoleEnum.Owner;\n    }\n    throw ArgumentError(\"参数异常\");\n  }\n\n  /// 将枚举转换为整型\n  static int toInt(GroupMemberRoleEnum role) {\n    switch (role) {\n      case GroupMemberRoleEnum.Undefined:\n        return 0;\n      case GroupMemberRoleEnum.Member:\n        return 200;\n      case GroupMemberRoleEnum.Admin:\n        return 300;\n      case GroupMemberRoleEnum.Owner:\n        return 400;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/group_system_type.dart",
    "content": "/// 群系统提示类型\nenum GroupSystemType {\n  INVALID,\n  ADD_GROUP_REQUEST_TYPE,\n  ADD_GROUP_ACCEPT_TYPE,\n  ADD_GROUP_REFUSE_TYPE,\n  KICK_OFF_FROM_GROUP_TYPE,\n  DELETE_GROUP_TYPE,\n  CREATE_GROUP_TYPE,\n  INVITED_TO_GROUP_TYPE,\n  QUIT_GROUP_TYPE,\n  GRANT_ADMIN_TYPE,\n  CANCEL_ADMIN_TYPE,\n  REVOKE_GROUP_TYPE,\n  INVITE_TO_GROUP_REQUEST_TYPE,\n  INVITATION_ACCEPTED_TYPE,\n  INVITATION_REFUSED_TYPE,\n  CUSTOM_INFO,\n}\n\nclass GroupSystemTypeTool {\n  /// 根据int值获得枚举类型\n  static GroupSystemType? intToGroupSystemType(int value) {\n    switch (value) {\n      case 0:\n        return GroupSystemType.INVALID;\n      case 1:\n        return GroupSystemType.ADD_GROUP_REQUEST_TYPE;\n      case 2:\n        return GroupSystemType.ADD_GROUP_ACCEPT_TYPE;\n      case 3:\n        return GroupSystemType.ADD_GROUP_REFUSE_TYPE;\n      case 4:\n        return GroupSystemType.KICK_OFF_FROM_GROUP_TYPE;\n      case 5:\n        return GroupSystemType.DELETE_GROUP_TYPE;\n      case 6:\n        return GroupSystemType.CREATE_GROUP_TYPE;\n      case 7:\n        return GroupSystemType.INVITED_TO_GROUP_TYPE;\n      case 8:\n        return GroupSystemType.QUIT_GROUP_TYPE;\n      case 9:\n        return GroupSystemType.GRANT_ADMIN_TYPE;\n      case 10:\n        return GroupSystemType.CANCEL_ADMIN_TYPE;\n      case 11:\n        return GroupSystemType.REVOKE_GROUP_TYPE;\n      case 12:\n        return GroupSystemType.INVITE_TO_GROUP_REQUEST_TYPE;\n      case 13:\n        return GroupSystemType.INVITATION_ACCEPTED_TYPE;\n      case 14:\n        return GroupSystemType.INVITATION_REFUSED_TYPE;\n      case 255:\n        return GroupSystemType.CUSTOM_INFO;\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "lib/enums/group_tips_group_info_type.dart",
    "content": "/// 群资料变更消息类型\nenum GroupTipsGroupInfoType {\n  /// 非法值\n  Invalid,\n\n  /// 修改群名称\n  ModifyName,\n\n  /// 修改群简介\n  ModifyIntroduction,\n\n  /// 修改群公告\n  ModifyNotification,\n\n  /// 修改群头像URL\n  ModifyFaceUrl,\n\n  /// 修改群主\n  ModifyOwner,\n\n  /// 修改群自定义字段\n  ModifyCustom,\n}\n"
  },
  {
    "path": "lib/enums/group_tips_type_enum.dart",
    "content": "/// 群组事件通知类型\nenum GroupTipsTypeEnum {\n  /// 非法\n  Invalid,\n\n  /// 主动入群（memberList 加入群组，非 Work 群有效）\n  Join,\n\n  /// 被邀请入群（opMember 邀请 memberList 入群，Work 群有效）\n  Invite,\n\n  /// 退出群组\n  Quit,\n\n  /// 踢出群 (opMember 把 memberList 踢出群组)\n  Kicked,\n\n  /// 设置管理员 (opMember 把 memberList 设置为管理员)\n  Admin,\n\n  /// 取消管理员 (opMember 取消 memberList 管理员身份)\n  CancelAdmin,\n\n  /// 群资料变更 (opMember 修改群资料：groupName & introduction & notification & faceUrl & owner & custom)\n  GroupInfoChange,\n\n  /// 群成员资料变更 (opMember 修改群成员资料：muteTime)\n  MemberInfoChange,\n}\n\n/// 枚举工具\nclass GroupTipsTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static GroupTipsTypeEnum getByInt(int index) =>\n      GroupTipsTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(GroupTipsTypeEnum data) => data.index;\n}\n"
  },
  {
    "path": "lib/enums/group_type_enum.dart",
    "content": "import 'package:tencent_im_plugin/utils/enum_util.dart';\n\n/// 群类型\nenum GroupTypeEnum {\n  /// 工作群\n  Work,\n\n  /// 公开群\n  Public,\n\n  /// 会议群\n  Meeting,\n\n  /// 直播群\n  AVChatRoom,\n}\n\nclass GroupTypeTool {\n  /// 根据字符串类型值获得枚举\n  /// [type] 字符串常量\n  /// [Return] 枚举对象\n  static GroupTypeEnum? getByString(String type) =>\n      EnumUtil.nameOf(GroupTypeEnum.values, type);\n\n  /// 将枚举转换为整型\n  static String toTypeString(GroupTypeEnum type) => EnumUtil.getEnumName(type);\n}\n"
  },
  {
    "path": "lib/enums/image_type_enum.dart",
    "content": "import 'dart:io';\n\n/// 图片类型\n/// 由于腾讯云 Android 和 IOS 的 V2TIMImageType 对象不相同，所以需要单独解析\n///   Android 的下标为 0、1、2，IOS的为 1、2、4\nenum ImageTypeEnum {\n  /// 原图\n  Original,\n\n  /// 缩略图\n  Thumb,\n\n  /// 大图\n  Large,\n}\n\nclass ImageTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static ImageTypeEnum getByInt(int /*!*/ index) {\n    // 单独解析Android\n    if (Platform.isAndroid) {\n      return ImageTypeEnum.values[index];\n    }\n\n    switch (index) {\n      case 1:\n        return ImageTypeEnum.Original;\n      case 2:\n        return ImageTypeEnum.Thumb;\n      case 4:\n        return ImageTypeEnum.Large;\n    }\n    throw ArgumentError(\"参数异常\");\n  }\n\n  /// 将枚举转换为整型\n  static int toInt(ImageTypeEnum data) {\n    // 单独解析Android\n    if (Platform.isAndroid) {\n      return data.index;\n    }\n\n    switch (data) {\n      case ImageTypeEnum.Original:\n        return 1;\n      case ImageTypeEnum.Thumb:\n        return 2;\n      case ImageTypeEnum.Large:\n        return 4;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/log_print_level.dart",
    "content": "/// 日志打印等级\nenum LogPrintLevel {\n  none,\n  debug,\n  info,\n  warn,\n  error,\n}\n\nclass LogPrintLevelTool {\n  /// 将枚举转换为整型\n  static int? toInt(LogPrintLevel level) {\n    switch (level) {\n      case LogPrintLevel.none:\n        return 0;\n      case LogPrintLevel.debug:\n        return 3;\n      case LogPrintLevel.info:\n        return 4;\n      case LogPrintLevel.warn:\n        return 5;\n      case LogPrintLevel.error:\n        return 6;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/login_status_enum.dart",
    "content": "/// 登录状态枚举\nenum LoginStatusEnum {\n  // 已登录\n  Logined,\n  // 登录中\n  Logining,\n  // 未登录\n  Logout,\n}\n\nclass LoginStatusTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static LoginStatusEnum getByInt(int index) =>\n      LoginStatusEnum.values[index - 1];\n}\n"
  },
  {
    "path": "lib/enums/message_elem_type_enum.dart",
    "content": "import 'package:tencent_im_plugin/message_node/custom_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/face_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/file_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/group_tips_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/image_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/location_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\nimport 'package:tencent_im_plugin/message_node/sound_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/text_message_node.dart';\nimport 'package:tencent_im_plugin/message_node/video_message_node.dart';\n\n/// 消息节点类型\nenum MessageElemTypeEnum {\n  // 没有元素\n  None,\n\n  // 文本\n  Text,\n\n  // 自定义\n  Custom,\n\n  // 图片\n  Image,\n\n  // 语音\n  Sound,\n\n  // 视频\n  Video,\n\n  // 文件\n  File,\n\n  // 位置\n  Location,\n\n  // 表情\n  Face,\n\n  // 群提示\n  GroupTips,\n}\n\nclass MessageElemTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static MessageElemTypeEnum getByInt(int index) =>\n      MessageElemTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(MessageElemTypeEnum level) => level.index;\n\n  /// 根据消息节点类型获得消息节点\n  /// [nodeType] 节点类型\n  /// [json] json值\n  static MessageNode? getMessageNodeByMessageNodeType(\n      MessageElemTypeEnum nodeType, Map<String, dynamic> json) {\n    switch (nodeType) {\n      case MessageElemTypeEnum.None:\n        break;\n      case MessageElemTypeEnum.Text:\n        return TextMessageNode.fromJson(json);\n      case MessageElemTypeEnum.Custom:\n        return CustomMessageNode.fromJson(json);\n      case MessageElemTypeEnum.Image:\n        return ImageMessageNode.fromJson(json);\n      case MessageElemTypeEnum.Sound:\n        return SoundMessageNode.fromJson(json);\n      case MessageElemTypeEnum.Video:\n        return VideoMessageNode.fromJson(json);\n      case MessageElemTypeEnum.File:\n        return FileMessageNode.fromJson(json);\n      case MessageElemTypeEnum.Location:\n        return LocationMessageNode.fromJson(json);\n      case MessageElemTypeEnum.Face:\n        return FaceMessageNode.fromJson(json);\n      case MessageElemTypeEnum.GroupTips:\n        return GroupTipsMessageNode.fromJson(json);\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "lib/enums/message_priority_enum.dart",
    "content": "/// 消息优先级枚举\nenum MessagePriorityEnum {\n  // 默认为普通优先级\n  Default,\n  // 高优先级，一般用于礼物等重要消息\n  Hign,\n  // 普通优先级，一般用于普通消息\n  Normal,\n  // 低优先级，一般用于点赞消息\n  Low,\n  // 未知，保留状态，Android部分场景会出现\n  Unknown,\n}\n\nclass MessagePriorityTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static MessagePriorityEnum getByInt(int index) => MessagePriorityEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(MessagePriorityEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/message_status_enum.dart",
    "content": "/// 消息状态\nenum MessageStatusEnum {\n  /// 未知\n  Unknown,\n\n  /// 发送中\n  Sending,\n\n  /// 发送成功\n  SendSucc,\n\n  /// 发送失败\n  SendFail,\n\n  /// 删除\n  HasDeleted,\n\n  /// 导入到本地的消息\n  Imported,\n\n  /// 已撤回\n  HasRevoked,\n}\n\nclass MessageStatusTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static MessageStatusEnum getByInt(int index) {\n    switch (index) {\n      case 0:\n        return MessageStatusEnum.Unknown;\n      case 1:\n        return MessageStatusEnum.Sending;\n      case 2:\n        return MessageStatusEnum.SendSucc;\n      case 3:\n        return MessageStatusEnum.SendFail;\n      case 4:\n        return MessageStatusEnum.HasDeleted;\n      case 5:\n        return MessageStatusEnum.Imported;\n      case 6:\n        return MessageStatusEnum.HasRevoked;\n    }\n    throw ArgumentError(\"参数异常\");\n  }\n\n  /// 将枚举转换为整型\n  static int toInt(MessageStatusEnum status) {\n    switch (status) {\n      case MessageStatusEnum.Unknown:\n        return 0;\n      case MessageStatusEnum.Sending:\n        return 1;\n      case MessageStatusEnum.SendSucc:\n        return 2;\n      case MessageStatusEnum.SendFail:\n        return 3;\n      case MessageStatusEnum.HasDeleted:\n        return 4;\n      case MessageStatusEnum.Imported:\n        return 5;\n      case MessageStatusEnum.HasRevoked:\n        return 6;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/operation_result_enum.dart",
    "content": "/// 操作结果枚举\nenum OperationResultEnum {\n  /// 操作失败\n  Fail,\n\n  /// 操作成功\n  Succ,\n\n  /// 无效操作\n  Invalid,\n\n  /// 等待处理\n  Pending,\n}\n\nclass OperationResultTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static OperationResultEnum getByInt(int index) =>\n      OperationResultEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(OperationResultEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/pendency_examine_type_enum.dart",
    "content": "/// 未决审核类型枚举\nenum PendencyExamineTypeEnum {\n  // 同意加好友（建立单向好友）\n  AGREE,\n  // 同意加好友并加对方为好友（建立双向好友）\n  AGREE_AND_ADD,\n  // 拒绝对方好友请求\n  REJECT,\n}\n\n/// 枚举工具\nclass PendencyExamineTypeEnumTool {\n  /// 根据数标获得枚举\n  static PendencyExamineTypeEnum? getEnumByIndex(index) {\n    switch (index) {\n      case 0:\n        return PendencyExamineTypeEnum.AGREE;\n      case 1:\n        return PendencyExamineTypeEnum.AGREE_AND_ADD;\n      case 2:\n        return PendencyExamineTypeEnum.REJECT;\n      default:\n        return null;\n    }\n  }\n\n  /// 根据枚举获得数标\n  static int? getIndexByEnum(e) {\n    switch (e) {\n      case PendencyExamineTypeEnum.AGREE:\n        return 0;\n      case PendencyExamineTypeEnum.AGREE_AND_ADD:\n        return 1;\n      case PendencyExamineTypeEnum.REJECT:\n        return 2;\n      default:\n        return null;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/pendency_type_enum.dart",
    "content": "/// 未决类型\nenum PendencyTypeEnum {\n  /// 别人发给我的未决请求\n  COME_IN,\n\n  /// 我发给别人的未决请求\n  SEND_OUT,\n\n  /// 别人发给我的以及我发给别人的所有未决请求，仅在拉取时有效。\n  BOTH,\n}\n\n/// 枚举工具\nclass PendencyTypeTool {\n  /// 根据数标获得枚举\n  static PendencyTypeEnum? getEnumByIndex(index) {\n    switch (index) {\n      case 1:\n        return PendencyTypeEnum.COME_IN;\n      case 2:\n        return PendencyTypeEnum.SEND_OUT;\n      case 3:\n        return PendencyTypeEnum.BOTH;\n      default:\n        return null;\n    }\n  }\n\n  /// 根据枚举获得数标\n  static int? getIndexByEnum(e) {\n    switch (e) {\n      case PendencyTypeEnum.COME_IN:\n        return 1;\n      case PendencyTypeEnum.SEND_OUT:\n        return 2;\n      case PendencyTypeEnum.BOTH:\n        return 3;\n      default:\n        return null;\n    }\n  }\n}\n"
  },
  {
    "path": "lib/enums/receive_message_opt_enum.dart",
    "content": "/// 接收消息选项\nenum ReceiveMessageOptEnum {\n  /// 在线正常接收消息，离线时会有厂商的离线推送通知\n  ReceiveAndNotify,\n\n  /// 不会接收到消息\n  NotReceive,\n\n  /// 在线正常接收消息，离线不会有推送通知\n  ReceiveNotNotify,\n}\n\nclass ReceiveMessageOptTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static ReceiveMessageOptEnum getByInt(int index) => ReceiveMessageOptEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(ReceiveMessageOptEnum level) => level.index;\n}"
  },
  {
    "path": "lib/enums/signaling_action_type_enum.dart",
    "content": "/// 信令操作类型枚举\nenum SignalingActionTypeEnum {\n  // 邀请方发起邀请\n  Invite,\n  // 邀请方取消邀请\n  Cancel,\n  // 被邀请方接受邀请\n  Accept,\n  // 被邀请方拒绝邀请\n  Reject,\n  // 邀请超时\n  Timeout\n}\n\nclass SignalingActionTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static SignalingActionTypeEnum getByInt(int index) =>\n      SignalingActionTypeEnum.values[index - 1];\n\n  /// 将枚举转换为整型\n  static int toInt(SignalingActionTypeEnum level) => level.index + 1;\n}\n"
  },
  {
    "path": "lib/enums/sns_tips_type.dart",
    "content": "/// 关系链变更类型\nenum SnsTipsType {\n  /// 未知\n  INVALID,\n\n  /// 增加好友消息\n  ADD_FRIEND,\n\n  /// 删除好友\n  DEL_FRIEND,\n\n  /// 增加好友申请\n  ADD_FRIEND_REQ,\n\n  /// 删除好友申请\n  DEL_FRIEND_REQ,\n\n  /// 添加黑名单\n  ADD_BLACKLIST,\n\n  /// 删除黑名单\n  DEL_BLACKLIST,\n\n  /// 未决已读上报\n  PENDENCY_REPORT,\n\n  /// 关系链资料变更\n  SNS_PROFILE_CHANGE,\n\n  /// 推荐数据增加\n  ADD_RECOMMEND,\n\n  /// 推荐数据减少\n  DEL_RECOMMEND,\n\n  /// 已决增加\n  ADD_DECIDE,\n\n  /// 已决减少\n  DEL_DECIDE,\n\n  /// 推荐已读上报\n  RECOMMEND_REPORT,\n\n  /// 已决已读上报\n  DECIDE_REPORT\n}\n"
  },
  {
    "path": "lib/enums/tencent_im_listener_type_enum.dart",
    "content": "/// 监听器类型枚举\nenum TencentImListenerTypeEnum {\n  /// 新消息通知\n  NewMessage,\n\n  /// C2C已读回执\n  C2CReadReceipt,\n\n  /// 消息撤回\n  MessageRevoked,\n\n  /// 同步服务开始\n  SyncServerStart,\n\n  /// 同步服务完成\n  SyncServerFinish,\n\n  /// 同步服务失败\n  SyncServerFailed,\n\n  /// 新会话\n  NewConversation,\n\n  /// 会话刷新\n  ConversationChanged,\n\n  /// 好友申请新增通知\n  FriendApplicationListAdded,\n\n  /// 好友申请删除通知\n  FriendApplicationListDeleted,\n\n  /// 好友申请已读通知\n  FriendApplicationListRead,\n\n  /// 好友新增通知\n  FriendListAdded,\n\n  /// 好友删除通知\n  FriendListDeleted,\n\n  /// 黑名单新增通知\n  BlackListAdd,\n\n  /// 黑名单删除通知\n  BlackListDeleted,\n\n  /// 好友资料更新通知\n  FriendInfoChanged,\n\n  /// 有用户加入群\n  MemberEnter,\n\n  /// 有用户离开群\n  MemberLeave,\n\n  /// 有用户被拉入群\n  MemberInvited,\n\n  /// 有用户被踢出群\n  MemberKicked,\n\n  /// 群成员信息被修改\n  MemberInfoChanged,\n\n  /// 创建群\n  GroupCreated,\n\n  /// 群被解散\n  GroupDismissed,\n\n  /// 群被回收\n  GroupRecycled,\n\n  /// 群信息被修改\n  GroupInfoChanged,\n\n  /// 有新的加群申请\n  ReceiveJoinApplication,\n\n  /// 加群信息已被管理员处理\n  ApplicationProcessed,\n\n  /// 指定管理员身份\n  GrantAdministrator,\n\n  /// 取消管理员身份\n  RevokeAdministrator,\n\n  /// 主动退出群组\n  QuitFromGroup,\n\n  /// 收到 RESTAPI 下发的自定义系统消息\n  ReceiveRESTCustomData,\n\n  /// 收到群属性更新的回调\n  GroupAttributeChanged,\n\n  /// 正在连接到腾讯云服务器\n  Connecting,\n\n  /// 网络连接成功\n  ConnectSuccess,\n\n  /// 网络连接失败\n  ConnectFailed,\n\n  /// 踢下线\n  KickedOffline,\n\n  /// 当前用户的资料发生了更新\n  SelfInfoUpdated,\n\n  /// 用户登录的 userSig 过期（用户需要重新获取 userSig 后登录）\n  UserSigExpired,\n\n  /// 收到信令邀请\n  ReceiveNewInvitation,\n\n  /// 信令被邀请者接受邀请\n  InviteeAccepted,\n\n  /// 信令被邀请者拒绝邀请\n  InviteeRejected,\n\n  /// 信令邀请被取消\n  InvitationCancelled,\n\n  /// 信令邀请超时\n  InvitationTimeout,\n\n  /// 下载进度\n  DownloadProgress,\n\n  /// 消息发送成功\n  MessageSendSucc,\n\n  /// 消息发送失败\n  MessageSendFail,\n\n  /// 消息发送进度更新\n  MessageSendProgress,\n}\n"
  },
  {
    "path": "lib/enums/user_allow_type_enum.dart",
    "content": "/// 用户验证方式枚举\nenum UserAllowTypeEnum {\n  // 允许任何人\n  AllowAny,\n  // 需要确认\n  NeedConfirm,\n  // 拒绝任何人\n  DenyAny,\n}\n\nclass UserAllowTypeTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static UserAllowTypeEnum getByInt(int index) =>\n      UserAllowTypeEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(UserAllowTypeEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/enums/user_gender_enum.dart",
    "content": "/// 用户性别枚举\nenum UserGenderEnum {\n  // 未知\n  Unknown,\n  // 男\n  Male,\n  // 女\n  Female,\n}\n\nclass UserGenderTool {\n  /// 根据Int类型值获得枚举\n  /// [index] Int常量\n  /// [Return] 枚举对象\n  static UserGenderEnum getByInt(int index) => UserGenderEnum.values[index];\n\n  /// 将枚举转换为整型\n  static int toInt(UserGenderEnum level) => level.index;\n}\n"
  },
  {
    "path": "lib/list_util.dart",
    "content": "import 'dart:convert';\n\nimport 'entity_factory.dart';\n\nclass ListUtil {\n  /// 根据泛型生成集合\n  static List<T> generateOBJList<T>(arr) {\n    if (arr is String) {\n      arr = jsonDecode(arr);\n    }\n\n    List<T> data = [];\n    for (var item in arr) {\n      var d = EntityFactory.generateOBJ<T>(item);\n      if (d != null) {\n        data.add(d);\n      }\n    }\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/listener/tencent_im_plugin_listener.dart",
    "content": "import 'dart:convert';\n\nimport 'package:flutter/services.dart';\nimport 'package:logger/logger.dart';\nimport 'package:tencent_im_plugin/entity/conversation_entity.dart';\nimport 'package:tencent_im_plugin/entity/download_progress_entity.dart';\nimport 'package:tencent_im_plugin/entity/error_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_administrator_op_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_application_processed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_attribute_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_dismissed_or_recycled_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_enter_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_invited_or_kicked_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_leave_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_receive_join_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_receive_rest_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_receipt_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_send_fail_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_send_progress_entity.dart';\nimport 'package:tencent_im_plugin/entity/signaling_common_entity.dart';\nimport 'package:tencent_im_plugin/entity/user_entity.dart';\nimport 'package:tencent_im_plugin/enums/tencent_im_listener_type_enum.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\nimport 'package:tencent_im_plugin/utils/enum_util.dart';\n\n/// 监听器对象\nclass TencentImPluginListener {\n  /// 日志对象\n  static Logger _logger = Logger();\n\n  /// 监听器列表\n  static Set<TencentImListenerValue> listeners = Set();\n\n  TencentImPluginListener(MethodChannel channel) {\n    // 绑定监听器\n    channel.setMethodCallHandler((methodCall) async {\n      // 解析参数\n      Map<String, dynamic> arguments = jsonDecode(methodCall.arguments);\n\n      switch (methodCall.method) {\n        case 'onListener':\n          // 获得原始类型和参数\n          TencentImListenerTypeEnum type = EnumUtil.nameOf(\n              TencentImListenerTypeEnum.values, arguments['type'])!;\n          var originalParams = arguments['params'];\n\n          // 封装回调类型和参数\n          var params = originalParams;\n\n          try {\n            switch (type) {\n              case TencentImListenerTypeEnum.NewMessage:\n                params = MessageEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.C2CReadReceipt:\n                params = ListUtil.generateOBJList<MessageReceiptEntity>(\n                    originalParams);\n                break;\n              case TencentImListenerTypeEnum.MessageRevoked:\n                params = originalParams;\n                break;\n              case TencentImListenerTypeEnum.SyncServerStart:\n                break;\n              case TencentImListenerTypeEnum.SyncServerFinish:\n                break;\n              case TencentImListenerTypeEnum.SyncServerFailed:\n                break;\n              case TencentImListenerTypeEnum.NewConversation:\n                params = ListUtil.generateOBJList<ConversationEntity>(\n                    originalParams);\n                break;\n              case TencentImListenerTypeEnum.ConversationChanged:\n                params = ListUtil.generateOBJList<ConversationEntity>(\n                    originalParams);\n                break;\n              case TencentImListenerTypeEnum.FriendApplicationListAdded:\n                params = ListUtil.generateOBJList<FriendApplicationEntity>(\n                    originalParams);\n                break;\n              case TencentImListenerTypeEnum.FriendApplicationListDeleted:\n                break;\n              case TencentImListenerTypeEnum.FriendApplicationListRead:\n                break;\n              case TencentImListenerTypeEnum.FriendListAdded:\n                params =\n                    ListUtil.generateOBJList<FriendInfoEntity>(originalParams);\n                break;\n              case TencentImListenerTypeEnum.FriendListDeleted:\n                break;\n              case TencentImListenerTypeEnum.BlackListAdd:\n                params =\n                    ListUtil.generateOBJList<FriendInfoEntity>(originalParams);\n                break;\n              case TencentImListenerTypeEnum.BlackListDeleted:\n                break;\n              case TencentImListenerTypeEnum.FriendInfoChanged:\n                params =\n                    ListUtil.generateOBJList<FriendInfoEntity>(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MemberEnter:\n                params = GroupMemberEnterEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MemberLeave:\n                params = GroupMemberLeaveEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MemberInvited:\n                params =\n                    GroupMemberInvitedOrKickedEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MemberKicked:\n                params =\n                    GroupMemberInvitedOrKickedEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MemberInfoChanged:\n                params = GroupMemberChangedEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.GroupCreated:\n                break;\n              case TencentImListenerTypeEnum.GroupDismissed:\n                params =\n                    GroupDismissedOrRecycledEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.GroupRecycled:\n                params =\n                    GroupDismissedOrRecycledEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.GroupInfoChanged:\n                params = GroupChangedEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.ReceiveJoinApplication:\n                params =\n                    GroupReceiveJoinApplicationEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.ApplicationProcessed:\n                params =\n                    GroupApplicationProcessedEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.GrantAdministrator:\n                params = GroupAdministratorOpEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.RevokeAdministrator:\n                params = GroupAdministratorOpEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.QuitFromGroup:\n                break;\n              case TencentImListenerTypeEnum.ReceiveRESTCustomData:\n                params = GroupReceiveRESTEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.GroupAttributeChanged:\n                params = GroupAttributeChangedEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.Connecting:\n                break;\n              case TencentImListenerTypeEnum.ConnectSuccess:\n                break;\n              case TencentImListenerTypeEnum.ConnectFailed:\n                params = ErrorEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.KickedOffline:\n                break;\n              case TencentImListenerTypeEnum.SelfInfoUpdated:\n                params = UserEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.UserSigExpired:\n                break;\n              case TencentImListenerTypeEnum.ReceiveNewInvitation:\n                params = SignalingCommonEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.InviteeAccepted:\n                params = SignalingCommonEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.InviteeRejected:\n                params = SignalingCommonEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.InvitationCancelled:\n                params = SignalingCommonEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.InvitationTimeout:\n                params = SignalingCommonEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.DownloadProgress:\n                params = DownloadProgressEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MessageSendSucc:\n                params = MessageEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MessageSendFail:\n                params = MessageSendFailEntity.fromJson(originalParams);\n                break;\n              case TencentImListenerTypeEnum.MessageSendProgress:\n                params = MessageSendProgressEntity.fromJson(originalParams);\n                break;\n            }\n          } catch (err) {\n            _logger.e(err,\n                \"$type 监听器错误:$err，请联系开发者进行处理！Github Issues: https://github.com/JiangJuHong/FlutterTencentImPlugin/issues\");\n          }\n\n          // 回调触发\n          for (var item in listeners) {\n            item(type, params);\n          }\n\n          break;\n        default:\n          throw MissingPluginException();\n      }\n    });\n  }\n\n  /// 添加消息监听\n  void addListener(TencentImListenerValue func) {\n    listeners.add(func);\n  }\n\n  /// 移除消息监听\n  void removeListener(TencentImListenerValue func) {\n    listeners.remove(func);\n  }\n}\n\n/// 监听器值模型\ntypedef TencentImListenerValue<P> = void Function(\n    TencentImListenerTypeEnum type, P? params);\n"
  },
  {
    "path": "lib/message_node/custom_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 自定义消息节点\nclass CustomMessageNode extends MessageNode {\n  /// 自定义数据\n  String? data;\n\n  /// 描述信息\n  String? desc;\n\n  /// 扩展信息\n  String? ext;\n\n  CustomMessageNode({\n    required this.data,\n    this.desc,\n    this.ext,\n  }) : super(MessageElemTypeEnum.Custom);\n\n  CustomMessageNode.fromJson(Map<String, dynamic> json) : super(MessageElemTypeEnum.Custom) {\n    if (json['data'] != null) data = json['data'];\n    if (json['desc'] != null) desc = json['desc'];\n    if (json['ext'] != null) ext = json['ext'];\n  }\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"data\"] = this.data;\n    data[\"desc\"] = this.desc;\n    data[\"ext\"] = this.ext;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/face_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 表情消息节点\nclass FaceMessageNode extends MessageNode {\n  /// 索引\n  late int index;\n\n  /// 数据\n  late String data;\n\n  FaceMessageNode({\n    required this.index,\n    required this.data,\n  }) : super(MessageElemTypeEnum.Face);\n\n  FaceMessageNode.fromJson(Map<String, dynamic> json)\n      : super(MessageElemTypeEnum.Face) {\n    if (json['index'] != null) this.index = json[\"index\"];\n    if (json['data'] != null) this.data = json[\"data\"];\n  }\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"index\"] = this.index;\n    data[\"data\"] = this.data;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/file_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 文件消息节点\nclass FileMessageNode extends MessageNode {\n  /// 文件路径\n  String? filePath;\n\n  /// 文件名\n  String? fileName;\n\n  /// 文件ID\n  String? _uuid;\n\n  /// 文件大小\n  int? _size;\n\n  FileMessageNode({\n    required this.filePath,\n    required this.fileName,\n  }) : super(MessageElemTypeEnum.File);\n\n  FileMessageNode.fromJson(Map<String, dynamic> json) : super(MessageElemTypeEnum.File) {\n    if (json['filePath'] != null) this.filePath = json[\"filePath\"];\n    if (json['fileName'] != null) this.fileName = json[\"fileName\"];\n    if (json['uuid'] != null) this._uuid = json[\"uuid\"];\n    if (json['size'] != null) this._size = json[\"size\"];\n  }\n\n  /// 获得UUID\n  String? get uuid => _uuid;\n\n  /// 获得文件大小\n  int? get size => _size;\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"filePath\"] = this.filePath;\n    data[\"fileName\"] = this.fileName;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/group_tips_message_node.dart",
    "content": "import 'package:tencent_im_plugin/entity/group_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_changed_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/enums/group_tips_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 群提示节点\nclass GroupTipsMessageNode extends MessageNode {\n  /// 群ID\n  late String groupID;\n\n  /// 群组事件通知类型\n  late GroupTipsTypeEnum type;\n\n  /// 操作者\n  GroupMemberEntity? opMember;\n\n  /// 被操作人列表\n  List<GroupMemberEntity?>? memberList;\n\n  /// 群资料变更信息列表，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE时有效\n  List<GroupChangedInfoEntity>? groupChangeInfoList;\n\n  /// 群成员变更信息列表，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE时有效\n  List<GroupMemberChangedInfoEntity>? memberChangeInfoList;\n\n  /// 当前群成员数，仅当tipsType值为V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_JOIN, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_QUIT, V2TIMGroupTipsElem#V2TIM_GROUP_TIPS_TYPE_KICKED的时候有效\n  late int memberCount;\n\n  GroupTipsMessageNode() : super(MessageElemTypeEnum.GroupTips);\n\n  GroupTipsMessageNode.fromJson(Map<String, dynamic> json)\n      : super(MessageElemTypeEnum.GroupTips) {\n    if (json[\"groupID\"] != null) this.groupID = json[\"groupID\"];\n    if (json[\"type\"] != null)\n      this.type = GroupTipsTypeTool.getByInt(json[\"type\"]);\n    if (json[\"opMember\"] != null)\n      this.opMember = GroupMemberEntity.fromJson(json[\"opMember\"]);\n    if (json[\"memberList\"] != null)\n      this.memberList =\n          ListUtil.generateOBJList<GroupMemberEntity>(json[\"memberList\"]);\n    if (json[\"groupChangeInfoList\"] != null)\n      this.groupChangeInfoList =\n          ListUtil.generateOBJList<GroupChangedInfoEntity>(\n              json[\"groupChangeInfoList\"]);\n    if (json[\"memberChangeInfoList\"] != null)\n      this.memberChangeInfoList =\n          ListUtil.generateOBJList<GroupMemberChangedInfoEntity>(\n              json[\"memberChangeInfoList\"]);\n    if (json[\"memberCount\"] != null) this.memberCount = json[\"memberCount\"];\n  }\n}\n"
  },
  {
    "path": "lib/message_node/image_message_node.dart",
    "content": "import 'dart:convert';\nimport 'package:tencent_im_plugin/enums/image_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 图片消息节点\nclass ImageMessageNode extends MessageNode {\n  /// 图片路径\n  String? path;\n\n  /// 图片列表，根据类型分开\n  Map<ImageTypeEnum, ImageEntity>? _imageData;\n\n  ImageMessageNode({\n    required this.path,\n  }) : super(MessageElemTypeEnum.Image);\n\n  ImageMessageNode.fromJson(Map<String, dynamic> json)\n      : super(MessageElemTypeEnum.Image) {\n    if (json['path'] != null) path = json['path'];\n    if (json['imageData'] != null) {\n      _imageData = Map();\n      (json['imageData'] as List).forEach((v) {\n        ImageEntity imageEntity = ImageEntity.fromJson(v);\n        _imageData![imageEntity.type!] = imageEntity;\n      });\n    }\n  }\n\n  /// 获得图片列表\n  Map<ImageTypeEnum, ImageEntity>? get imageData => _imageData;\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"path\"] = this.path;\n    return data;\n  }\n}\n\n/// 图片实体\nclass ImageEntity {\n  /// 大小\n  int? size;\n\n  /// 宽度\n  int? width;\n\n  /// 类型\n  ImageTypeEnum? type;\n\n  /// uuid\n  String? uuid;\n\n  /// url\n  String? url;\n\n  /// 高度\n  int? height;\n\n  ImageEntity({\n    this.size,\n    this.width,\n    this.type,\n    this.uuid,\n    this.url,\n    this.height,\n  });\n\n  ImageEntity.fromJson(data) {\n    Map<String, dynamic> json =\n        data is Map ? data.cast<String, dynamic>() : jsonDecode(data);\n    if (json['size'] != null) size = json['size'];\n    if (json['width'] != null) width = json['width'];\n    if (json['type'] != null) type = ImageTypeTool.getByInt(json[\"type\"]);\n    if (json['uUID'] != null) uuid = json['uUID'];\n    if (json['url'] != null) url = json['url'];\n    if (json['height'] != null) height = json['height'];\n  }\n}\n"
  },
  {
    "path": "lib/message_node/location_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 位置节点\nclass LocationMessageNode extends MessageNode {\n  /// 位置描述\n  late String desc;\n\n  /// 经度\n  late double longitude;\n\n  /// 纬度\n  late double latitude;\n\n  LocationMessageNode({\n    required this.desc,\n    required this.longitude,\n    required this.latitude,\n  }) : super(MessageElemTypeEnum.Location);\n\n  LocationMessageNode.fromJson(Map<String, dynamic> json)\n      : super(MessageElemTypeEnum.Location) {\n    if (json['desc'] != null) desc = json['desc'];\n    if (json['longitude'] != null) longitude = json['longitude'];\n    if (json['latitude'] != null) latitude = json['latitude'];\n  }\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"desc\"] = this.desc;\n    data[\"longitude\"] = this.longitude;\n    data[\"latitude\"] = this.latitude;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\n\n/// 消息节点\nclass MessageNode {\n  /// 新消息节点类型\n  MessageElemTypeEnum nodeType;\n\n  MessageNode(this.nodeType);\n\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = new Map<String, dynamic>();\n    data[\"nodeType\"] = MessageElemTypeTool.toInt(this.nodeType);\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/sound_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 语音消息节点\nclass SoundMessageNode extends MessageNode {\n  /// 语音ID\n  String? _uuid;\n\n  /// 路径\n  String? path;\n\n  /// 时长\n  late int duration;\n\n  /// 数据大小\n  int? _dataSize;\n\n  SoundMessageNode({\n    required this.path,\n    required this.duration,\n  }) : super(MessageElemTypeEnum.Sound);\n\n  SoundMessageNode.fromJson(Map<String, dynamic> json)\n      : super(MessageElemTypeEnum.Sound) {\n    if (json['uuid'] != null) _uuid = json['uuid'];\n    if (json['path'] != null) path = json['path'];\n    if (json['duration'] != null) duration = json['duration'];\n    if (json['dataSize'] != null) _dataSize = json['dataSize'];\n  }\n\n  /// 获得语音ID\n  String? get uuid => _uuid;\n\n  /// 获得数据大小\n  int? get dataSize => _dataSize;\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"path\"] = this.path;\n    data[\"duration\"] = this.duration;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/text_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 文本消息节点\nclass TextMessageNode extends MessageNode {\n  /// 文本内容\n  late String content;\n\n  /// @的用户列表，只在群聊中有效\n  List<String>? _atUserList;\n\n  /// 是否需要@所有人\n  bool _atAll = false;\n\n  TextMessageNode({\n    required this.content,\n    List<String>? atUserList,\n    bool atAll: false,\n  })  : this._atUserList = atUserList,\n        this._atAll = atAll,\n        super(MessageElemTypeEnum.Text);\n\n  TextMessageNode.fromJson(Map<String, dynamic> json) : super(MessageElemTypeEnum.Text) {\n    if (json['content'] != null) content = json['content'];\n  }\n\n  /// 设置@列表\n  set atUserList(List<String> value) => _atUserList = value;\n\n  /// 设置@所有人\n  set atAll(bool value) => _atAll = value;\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"content\"] = this.content;\n    data[\"atUserList\"] = this._atUserList;\n    data[\"atAll\"] = this._atAll;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/message_node/video_message_node.dart",
    "content": "import 'package:tencent_im_plugin/enums/message_elem_type_enum.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\n\n/// 适配消息节点\nclass VideoMessageNode extends MessageNode {\n  /// 视频路径\n  String? videoPath;\n\n  /// 视频UUID\n  String? _videoUuid;\n\n  /// 视频大小\n  int? _videoSize;\n\n  /// 时长\n  late int duration;\n\n  /// 缩略图路径\n  String? snapshotPath;\n\n  /// 缩略图UUID\n  String? _snapshotUuid;\n\n  /// 缩略图大小\n  int? _snapshotSize;\n\n  /// 缩略图宽度\n  int? _snapshotWidth;\n\n  /// 缩略图高度\n  int? _snapshotHeight;\n\n  VideoMessageNode({\n    required this.videoPath,\n    required this.duration,\n    required this.snapshotPath,\n  }) : super(MessageElemTypeEnum.Video);\n\n  VideoMessageNode.fromJson(Map<String, dynamic> json)\n      : super(MessageElemTypeEnum.Video) {\n    if (json['videoPath'] != null) videoPath = json[\"videoPath\"];\n    if (json['videoUuid'] != null) _videoUuid = json[\"videoUuid\"];\n    if (json['videoSize'] != null) _videoSize = json[\"videoSize\"];\n    if (json['duration'] != null) duration = json[\"duration\"];\n    if (json['snapshotPath'] != null) snapshotPath = json[\"snapshotPath\"];\n    if (json['snapshotUuid'] != null) _snapshotUuid = json[\"snapshotUuid\"];\n    if (json['snapshotSize'] != null) _snapshotSize = json[\"snapshotSize\"];\n    if (json['snapshotWidth'] != null) _snapshotWidth = json[\"snapshotWidth\"];\n    if (json['snapshotHeight'] != null)\n      _snapshotHeight = json[\"snapshotHeight\"];\n  }\n\n  /// 获得视频UUID\n  String? get videoUuid => _videoUuid;\n\n  /// 获得视频大小\n  int? get videoSize => _videoSize;\n\n  /// 获得缩略图UUID\n  String? get snapshotUuid => _snapshotUuid;\n\n  /// 获得缩略图大小\n  int? get snapshotSize => _snapshotSize;\n\n  /// 获得缩略图宽度\n  int? get snapshotWidth => _snapshotWidth;\n\n  /// 获得缩略图高度\n  int? get snapshotHeight => _snapshotHeight;\n\n  @override\n  Map<String, dynamic> toJson() {\n    final Map<String, dynamic> data = super.toJson();\n    data[\"videoPath\"] = this.videoPath;\n    data[\"duration\"] = this.duration;\n    data[\"snapshotPath\"] = this.snapshotPath;\n    return data;\n  }\n}\n"
  },
  {
    "path": "lib/tencent_im_plugin.dart",
    "content": "import 'dart:async';\nimport 'dart:convert';\nimport 'package:flutter/services.dart';\nimport 'package:tencent_im_plugin/entity/conversation_entity.dart';\nimport 'package:tencent_im_plugin/entity/conversation_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/find_friend_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/find_group_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/find_message_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_add_application_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_application_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_check_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_group_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_info_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/friend_operation_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_application_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_create_member_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_info_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_info_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/group_member_operation_result_entity.dart';\nimport 'package:tencent_im_plugin/entity/message_search_param.dart';\nimport 'package:tencent_im_plugin/entity/offline_push_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/signaling_info_entity.dart';\nimport 'package:tencent_im_plugin/entity/user_entity.dart';\nimport 'package:tencent_im_plugin/enums/friend_application_agree_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/friend_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/get_message_type_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_member_filter_enum.dart';\nimport 'package:tencent_im_plugin/enums/group_member_role_enum.dart';\nimport 'package:tencent_im_plugin/enums/receive_message_opt_enum.dart';\nimport 'package:tencent_im_plugin/enums/login_status_enum.dart';\nimport 'package:tencent_im_plugin/enums/message_priority_enum.dart';\nimport 'package:tencent_im_plugin/list_util.dart';\nimport 'package:tencent_im_plugin/listener/tencent_im_plugin_listener.dart';\nimport 'package:tencent_im_plugin/message_node/message_node.dart';\nimport 'package:tencent_im_plugin/entity/message_entity.dart';\nimport 'package:tencent_im_plugin/enums/log_print_level.dart';\n\nclass TencentImPlugin {\n  static const MethodChannel _channel = const MethodChannel('tencent_im_plugin');\n\n  /// 监听器对象\n  static TencentImPluginListener listener = TencentImPluginListener(_channel);\n\n  /// C2C会话前缀\n  static const String conversationC2CPrefix = \"c2c_\";\n\n  /// 群聊会话前缀\n  static const String conversationGroupPrefix = \"group_\";\n\n  /// 获得会话ID，可在 [conversationID] 会话ID | [userID] 用户ID | [groupID] 群组ID 三选一\n  static String _getConversationID({String? conversationID, String? userID, String? groupID}) {\n    String? cID = conversationID;\n    if (cID == null && userID != null) {\n      cID = conversationC2CPrefix + userID;\n    } else if (cID == null && groupID != null) {\n      cID = conversationGroupPrefix + groupID;\n    }\n    if (cID == null) throw Exception(\"conversationID、userID、groupID 不能都为空\");\n    return cID;\n  }\n\n  /// 初始化SDK\n  /// [appid] 应用ID\n  /// [logPrintLevel] 日志打印级别\n  static initSDK({required String appid, LogPrintLevel logPrintLevel: LogPrintLevel.error}) {\n    return _channel.invokeMethod('initSDK', {\"appid\": appid, \"logPrintLevel\": LogPrintLevelTool.toInt(logPrintLevel)});\n  }\n\n  /// 反初始化SDK\n  static unInitSDK() => _channel.invokeMethod('unInitSDK');\n\n  /// 获取SDK版本\n  /// [Return] SDK版本\n  static Future<String> getVersion() async => await _channel.invokeMethod('getVersion');\n\n  /// 获取服务器当前时间\n  /// [Return] 服务器时间，单位 s\n  static Future<int> getServerTime() async => await _channel.invokeMethod('getServerTime');\n\n  /// 登录腾讯云IM\n  /// [userID] 用户ID\n  /// [userSig] 用户签名\n  static Future<void> login({required String userID, required String userSig}) {\n    return _channel.invokeMethod('login', {\"userID\": userID, \"userSig\": userSig});\n  }\n\n  /// 退出登录腾讯云IM\n  static Future<void> logout() => _channel.invokeMethod('logout');\n\n  /// 获得用户登录状态\n  /// [Return] 用户当前登录状态\n  static Future<LoginStatusEnum> getLoginStatus() async => LoginStatusTool.getByInt(await (_channel.invokeMethod('getLoginStatus')));\n\n  /// 获得当前登录用户\n  /// [Return] 当前用户ID\n  static Future<String?> getLoginUser() => _channel.invokeMethod('getLoginUser');\n\n  /// 邀请某个人\n  /// [invitee] 被邀请人用户 ID\n  /// [data] 自定义数据\n  /// [onlineUserOnly] 是否只有在线用户才能收到邀请，如果设置为 true，只有在线用户才能收到， 并且 invite 操作也不会产生历史消息（针对该次 invite 的后续 cancel、accept、reject、timeout 操作也同样不会产生历史消息）。\n  /// [offlinePushInfo] 离线推送信息，其中 desc 为必填字段，推送的时候会默认展示 desc 信息。\n  /// [timeout] 超时时间，单位秒，如果设置为 0，SDK 不会做超时检测，也不会触发 onInvitationTimeout 回调\n  /// [Return] 邀请 ID，如果邀请失败，返回 null\n  static Future<String?> invite({required String invitee, required String data, OfflinePushInfoEntity? offlinePushInfo, bool onlineUserOnly: false, int timeout: 0}) {\n    return _channel.invokeMethod('invite', {\n      \"invitee\": invitee,\n      \"data\": data,\n      \"onlineUserOnly\": onlineUserOnly,\n      \"offlinePushInfo\": jsonEncode(offlinePushInfo ?? OfflinePushInfoEntity()),\n      \"timeout\": timeout,\n    });\n  }\n\n  /// 邀请群内的某些人\n  /// [groupID] 发起邀请所在群组\n  /// [inviteeList] 被邀请人列表，inviteeList 必须已经在 groupID 群里，否则邀请无效\n  /// [data] 自定义数据\n  /// [onlineUserOnly] 是否只有在线用户才能收到邀请，如果设置为 true，只有在线用户才能收到， 并且 invite 操作也不会产生历史消息（针对该次 invite 的后续 cancel、accept、reject、timeout 操作也同样不会产生历史消息）。\n  /// [timeout] 超时时间，单位秒，如果设置为 0，SDK 不会做超时检测，也不会触发 onInvitationTimeout 回调\n  /// [Return] 邀请 ID，如果邀请失败，返回 null\n  static Future<String?> inviteInGroup({required String groupID, required List<String> inviteeList, required String data, bool onlineUserOnly: false, int timeout: 0}) {\n    return _channel.invokeMethod('inviteInGroup', {\n      \"groupID\": groupID,\n      \"inviteeList\": inviteeList.join(\",\"),\n      \"data\": data,\n      \"onlineUserOnly\": onlineUserOnly,\n      \"timeout\": timeout,\n    });\n  }\n\n  /// 邀请方取消邀请\n  /// [inviteID] 邀请ID\n  /// [data] 自定义数据\n  static Future<String?> cancel({required String inviteID, required String data}) {\n    return _channel.invokeMethod('cancel', {\n      \"inviteID\": inviteID,\n      \"data\": data,\n    });\n  }\n\n  /// 接收方接收邀请\n  /// [inviteID] 邀请ID\n  /// [data] 自定义数据\n  static Future<String?> accept({required String inviteID, required String data}) {\n    return _channel.invokeMethod('accept', {\n      \"inviteID\": inviteID,\n      \"data\": data,\n    });\n  }\n\n  /// 接收方拒绝邀请\n  /// [inviteID] 邀请ID\n  /// [data] 自定义数据\n  static Future<String?> reject({required String inviteID, required String data}) {\n    return _channel.invokeMethod('reject', {\n      \"inviteID\": inviteID,\n      \"data\": data,\n    });\n  }\n\n  /// 获取信令信息\n  /// [message] 消息对象\n  /// [Return] V2TIMSignalingInfo 信令信息，如果为 null，则 msg 不是一条信令消息。\n  static Future<SignalingInfoEntity> getSignalingInfo({required FindMessageEntity message}) async {\n    return SignalingInfoEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getSignalingInfo', {\n      \"message\": jsonEncode(message),\n    }))));\n  }\n\n  /// 添加邀请信令（可以用于群离线推送消息触发的邀请信令）\n  /// [info] 信令信息对象\n  static Future<void> addInvitedSignaling({required SignalingInfoEntity info}) {\n    return _channel.invokeMethod('addInvitedSignaling', {\n      \"info\": jsonEncode(info),\n    });\n  }\n\n  /// 发送消息\n  /// [receiver] 消息接收者的 userID, 如果是发送 C2C 单聊消息，只需要指定 receiver 即可。\n  /// [groupID] 目标群组 ID，如果是发送群聊消息，只需要指定 groupID 即可。\n  /// [ol] 是否为在线消息(无痕)，如果为true，将使用 sendOnlineMessage 通道进行消息发送\n  /// [localCustomInt] 自定义Int\n  /// [localCustomStr] 自定义Str\n  /// [node] 消息节点\n  /// [priority] 消息优先级，仅针对群聊消息有效。请把重要消息设置为高优先级（比如红包、礼物消息），高频且不重要的消息设置为低优先级（比如点赞消息）。\n  /// [offlinePushInfo] 离线推送时携带的标题和内容。\n  /// [Return] 消息ID\n  static Future<String?> sendMessage({\n    String? receiver,\n    String? groupID,\n    required MessageNode node,\n    bool ol: false,\n    int? localCustomInt,\n    String? localCustomStr,\n    MessagePriorityEnum priority: MessagePriorityEnum.Default,\n    OfflinePushInfoEntity? offlinePushInfo,\n  }) {\n    return _channel.invokeMethod(\n      'sendMessage',\n      {\n        \"receiver\": receiver,\n        \"groupID\": groupID,\n        \"node\": jsonEncode(node),\n        \"ol\": ol,\n        \"localCustomInt\": localCustomInt,\n        \"localCustomStr\": localCustomStr,\n        \"priority\": MessagePriorityTool.toInt(priority),\n        \"offlinePushInfo\": offlinePushInfo == null ? null : jsonEncode(offlinePushInfo),\n      }..removeWhere((key, value) => value == null),\n    );\n  }\n\n  /// 重发消息\n  /// [message] 消息查找对象\n  /// [receiver] 消息接收者的 userID, 如果是发送 C2C 单聊消息，只需要指定 receiver 即可。\n  /// [groupID] 目标群组 ID，如果是发送群聊消息，只需要指定 groupID 即可。\n  /// [ol] 是否为在线消息(无痕)，如果为true，将使用 sendOnlineMessage 通道进行消息发送\n  /// [localCustomInt] 自定义Int\n  /// [localCustomStr] 自定义Str\n  /// [priority] 消息优先级，仅针对群聊消息有效。请把重要消息设置为高优先级（比如红包、礼物消息），高频且不重要的消息设置为低优先级（比如点赞消息）。\n  /// [offlinePushInfo] 离线推送时携带的标题和内容。\n  /// [Return] 消息ID\n  static Future<String?> resendMessage({\n    required FindMessageEntity message,\n    String? receiver,\n    String? groupID,\n    bool ol: false,\n    int? localCustomInt,\n    String? localCustomStr,\n    MessagePriorityEnum priority: MessagePriorityEnum.Default,\n    OfflinePushInfoEntity? offlinePushInfo,\n  }) {\n    return _channel.invokeMethod(\n      'resendMessage',\n      {\n        \"message\": jsonEncode(message),\n        \"receiver\": receiver,\n        \"groupID\": groupID,\n        \"ol\": ol,\n        \"localCustomInt\": localCustomInt,\n        \"localCustomStr\": localCustomStr,\n        \"priority\": MessagePriorityTool.toInt(priority),\n        \"offlinePushInfo\": offlinePushInfo == null ? null : jsonEncode(offlinePushInfo),\n      }..removeWhere((key, value) => value == null),\n    );\n  }\n\n  /// 撤回消息\n  /// [message] 消息查找对象\n  static Future<void> revokeMessage({required FindMessageEntity message}) {\n    return _channel.invokeMethod('revokeMessage', {\n      \"message\": jsonEncode(message),\n    });\n  }\n\n  /// 获取历史消息高级接口\n  /// [userID] 用户ID\n  /// [groupID] 群聊ID\n  /// [count] 拉取消息的个数，不宜太多，会影响消息拉取的速度，这里建议一次拉取 20 个\n  /// [lastMsg] 获取消息的起始消息，如果传 null，起始消息为会话的最新消息\n  /// [type] 拉取消息类型，可以设置拉取本地、云端更老或则更新的消息。\n  static Future<List<MessageEntity>> getHistoryMessageList({String? userID, String? groupID, required int count, GetMessageTypeEnum type: GetMessageTypeEnum.GetCloudOlderMsg, FindMessageEntity? lastMsg}) async {\n    if (userID == null && groupID == null) throw ArgumentError(\"userID 和 groupID 不能同时为空!\");\n    return ListUtil.generateOBJList<MessageEntity>(jsonDecode(await (_channel.invokeMethod(\n      'getHistoryMessageList',\n      {\n        \"userID\": userID,\n        \"groupID\": groupID,\n        \"count\": count,\n        \"type\": GetMessageTypeTool.toInt(type),\n        \"lastMsg\": lastMsg == null ? null : jsonEncode(lastMsg),\n      }..removeWhere((key, value) => value == null),\n    ))));\n  }\n\n  /// 获得单聊历史记录\n  /// [userId] 用户ID\n  /// [count] 拉取消息的个数，不宜太多，会影响消息拉取的速度，这里建议一次拉取 20 个\n  /// [lastMsg] 获取消息的起始消息，如果传 null，起始消息为会话的最新消息\n  static Future<List<MessageEntity>> getC2CHistoryMessageList({required String userID, required int count, FindMessageEntity? lastMsg}) async {\n    return ListUtil.generateOBJList<MessageEntity>(jsonDecode(await (_channel.invokeMethod(\n      'getC2CHistoryMessageList',\n      {\n        \"userID\": userID,\n        \"count\": count,\n        \"lastMsg\": lastMsg == null ? null : jsonEncode(lastMsg),\n      }..removeWhere((key, value) => value == null),\n    ))));\n  }\n\n  /// 获得群聊历史记录\n  /// [groupID] 群ID\n  /// [count] 拉取消息的个数，不宜太多，会影响消息拉取的速度，这里建议一次拉取 20 个\n  /// [lastMsg] 获取消息的起始消息，如果传 null，起始消息为会话的最新消息\n  static Future<List<MessageEntity>> getGroupHistoryMessageList({required String groupID, required int count, FindMessageEntity? lastMsg}) async {\n    return ListUtil.generateOBJList<MessageEntity>(jsonDecode(await (_channel.invokeMethod(\n      'getGroupHistoryMessageList',\n      {\n        \"groupID\": groupID,\n        \"count\": count,\n        \"lastMsg\": lastMsg == null ? null : jsonEncode(lastMsg),\n      }..removeWhere((key, value) => value == null),\n    ))));\n  }\n\n  /// 设置聊天记录为已读，此为 markC2CMessageAsRead 和 markGroupMessageAsRead 的封装\n  /// [userID] 用户ID\n  /// [groupID] 群ID\n  static Future<void> markMessageAsRead({String? userID, String? groupID}) {\n    if (userID == null && groupID == null) throw ArgumentError(\"userID 和 groupID 不能同时为空!\");\n    if (userID != null) {\n      return markC2CMessageAsRead(userID: userID);\n    } else {\n      return markGroupMessageAsRead(groupID: groupID!);\n    }\n  }\n\n  /// 设置单聊已读\n  /// [groupID] 群ID\n  static Future<void> markC2CMessageAsRead({required String userID}) {\n    return _channel.invokeMethod('markC2CMessageAsRead', {\n      \"userID\": userID,\n    });\n  }\n\n  /// 设置群聊已读\n  /// [groupID] 群ID\n  static Future<void> markGroupMessageAsRead({required String groupID}) {\n    return _channel.invokeMethod('markGroupMessageAsRead', {\n      \"groupID\": groupID,\n    });\n  }\n\n  /// 删除本地消息\n  /// [message] 消息对象\n  static Future<void> deleteMessageFromLocalStorage({required FindMessageEntity message}) {\n    return _channel.invokeMethod('deleteMessageFromLocalStorage', {\n      \"message\": jsonEncode(message),\n    });\n  }\n\n  /// 删除本地及漫游消息\n  /// 该接口会删除本地历史的同时也会把漫游消息即保存在服务器上的消息也删除，卸载重装后无法再拉取到。需要注意的是：\n  ///   1. 一次最多只能删除 30 条消息\n  ///   2. 要删除的消息必须属于同一会话\n  ///   3. 一秒钟最多只能调用一次该接口\n  ///   4. 如果该账号在其他设备上拉取过这些消息，那么调用该接口删除后，这些消息仍然会保存在那些设备上，即删除消息不支持多端同步。\n  /// [message] 消息对象\n  static Future<void> deleteMessages({required List<FindMessageEntity> message}) {\n    return _channel.invokeMethod('deleteMessages', {\n      \"message\": jsonEncode(message),\n    });\n  }\n\n  /// 向群组消息列表中添加一条消息\n  /// [groupID] 群ID\n  /// [sender] 发送人\n  /// [message] 消息对象\n  static Future<void> insertGroupMessageToLocalStorage({required String groupID, required String sender, required MessageNode node}) {\n    return _channel.invokeMethod('insertGroupMessageToLocalStorage', {\n      \"groupID\": groupID,\n      \"sender\": sender,\n      \"node\": jsonEncode(node),\n    });\n  }\n\n  /// 向用户消息列表中添加一条消息\n  /// [userID] 用户ID\n  /// [sender] 发送人\n  /// [message] 消息对象\n  static Future<void> insertC2CMessageToLocalStorage({required String userID, required String sender, required MessageNode node}) {\n    return _channel.invokeMethod('insertC2CMessageToLocalStorage', {\n      \"userID\": userID,\n      \"sender\": sender,\n      \"node\": jsonEncode(node),\n    });\n  }\n\n  /// 下载视频\n  /// [message] 消息对象\n  /// [path] 下载路径\n  static Future<void> downloadVideo({required FindMessageEntity message, required String path}) {\n    return _channel.invokeMethod('downloadVideo', {\n      \"message\": jsonEncode(message),\n      \"path\": path,\n    });\n  }\n\n  /// 下载视频缩略图\n  /// [message] 消息对象\n  /// [path] 下载路径\n  static Future<void> downloadVideoThumbnail({required FindMessageEntity message, required String path}) {\n    return _channel.invokeMethod('downloadVideoThumbnail', {\n      \"message\": jsonEncode(message),\n      \"path\": path,\n    });\n  }\n\n  /// 下载语音\n  /// [message] 消息对象\n  /// [path] 下载路径\n  static Future<void> downloadSound({required FindMessageEntity message, required String path}) {\n    return _channel.invokeMethod('downloadSound', {\n      \"message\": jsonEncode(message),\n      \"path\": path,\n    });\n  }\n\n  /// 下载视频\n  /// [message] 消息对象\n  /// [path] 下载路径\n  static Future<void> downloadFile({required FindMessageEntity message, required String path}) {\n    return _channel.invokeMethod('downloadFile', {\n      \"message\": jsonEncode(message),\n      \"path\": path,\n    });\n  }\n\n  /// 设置消息本地Str\n  /// [message] 消息对象\n  /// [data] 数据对象\n  static Future<void> setMessageLocalCustomStr({required FindMessageEntity message, required String data}) {\n    return _channel.invokeMethod('setMessageLocalCustomStr', {\n      \"message\": jsonEncode(message),\n      \"data\": data,\n    });\n  }\n\n  /// 设置消息本地Int\n  /// [message] 消息对象\n  /// [data] 数据对象\n  static Future<void> setMessageLocalCustomInt({required FindMessageEntity message, required int data}) {\n    return _channel.invokeMethod('setMessageLocalCustomInt', {\n      \"message\": jsonEncode(message),\n      \"data\": data,\n    });\n  }\n\n  /// 查找消息列表\n  /// [messages] 需要获得的消息查找对象\n  static Future<List<MessageEntity>> findMessages({required List<FindMessageEntity> messages}) async {\n    return ListUtil.generateOBJList<MessageEntity>(await _channel.invokeMethod('findMessages', {\n      \"messages\": jsonEncode(messages),\n    }));\n  }\n\n  /// 创建群，[info]对象建议使用[GroupInfoEntity.create]，进行创建\n  /// [info] 群信息对象\n  /// [memberList] 指定初始的群成员（直播群 AVChatRoom 不支持指定初始群成员，memberList 请传 null）\n  /// [Return] 群ID\n  static Future<String?> createGroup({required GroupInfoEntity info, List<GroupCreateMemberEntity>? memberList}) {\n    return _channel.invokeMethod(\n      'createGroup',\n      {\n        \"info\": jsonEncode(info),\n        \"memberList\": memberList == null ? null : jsonEncode(memberList),\n      }..removeWhere((key, value) => value == null),\n    );\n  }\n\n  /// 加入群\n  /// [groupID] 群ID\n  /// [message] 描述\n  static Future<void> joinGroup({required String groupID, required String message}) {\n    return _channel.invokeMethod('joinGroup', {\n      \"groupID\": groupID,\n      \"message\": message,\n    });\n  }\n\n  /// 退出群\n  /// [groupID] 群ID\n  static Future<void> quitGroup({required String groupID}) {\n    return _channel.invokeMethod('quitGroup', {\n      \"groupID\": groupID,\n    });\n  }\n\n  /// 解散群\n  /// [groupID] 群ID\n  static Future<void> dismissGroup({required String groupID}) {\n    return _channel.invokeMethod('dismissGroup', {\n      \"groupID\": groupID,\n    });\n  }\n\n  /// 获取已经加入的群列表（不包括已加入的直播群）\n  static Future<List<GroupInfoEntity>> getJoinedGroupList() async {\n    return ListUtil.generateOBJList<GroupInfoEntity>(jsonDecode(await (_channel.invokeMethod('getJoinedGroupList'))));\n  }\n\n  /// 拉取群资料\n  /// [groupIDList] 群ID列表\n  static Future<List<GroupInfoResultEntity>> getGroupsInfo({required List<String> groupIDList}) async {\n    return ListUtil.generateOBJList<GroupInfoResultEntity>(jsonDecode(await (_channel.invokeMethod('getGroupsInfo', {\n      \"groupIDList\": groupIDList.join(\",\"),\n    }))));\n  }\n\n  /// 修改群资料\n  /// [info] 群信息\n  static Future<void> setGroupInfo({required GroupInfoEntity info}) async {\n    return _channel.invokeMethod('setGroupInfo', {\n      \"info\": jsonEncode(info),\n    });\n  }\n\n  /// 搜索群列表\n  ///\n  /// [keywordList] 关键字列表\n  /// [isSearchGroupID] 是否根据群ID搜索\n  /// [isSearchGroupName] 是否根据群名称搜索\n  static Future<List<GroupInfoResultEntity>> searchGroups({required List<String> keywordList, bool isSearchGroupID: false, bool isSearchGroupName: false}) async {\n    return ListUtil.generateOBJList<GroupInfoResultEntity>(jsonDecode(await (_channel.invokeMethod('searchGroups', {\n      \"keywordList\": keywordList,\n      \"isSearchGroupID\": isSearchGroupID,\n      \"isSearchGroupName\": isSearchGroupName,\n    }))));\n  }\n\n  /// 搜索群成员列表\n  ///\n  /// [keywordList] 关键字列表\n  /// [groupIDList] 群ID列表\n  /// [isSearchMemberNameCard] 是否根据群名片搜索\n  /// [isSearchMemberUserID] 是否根据群用户ID搜索\n  /// [isSearchMemberRemark] 是否根据群用户备注搜索\n  /// [isSearchMemberNickName] 是否根据群用户昵称搜索\n  static Future<void> searchGroupMembers({\n    required List<String> keywordList,\n    required List<String> groupIDList,\n    bool isSearchMemberNameCard: false,\n    bool isSearchMemberUserID: false,\n    bool isSearchMemberRemark: false,\n    bool isSearchMemberNickName: false,\n  }) async {\n    return _channel.invokeMethod('searchGroupMembers', {\n      \"keywordList\": keywordList,\n      \"groupIDList\": groupIDList,\n      \"isSearchMemberNameCard\": isSearchMemberNameCard,\n      \"isSearchMemberUserID\": isSearchMemberUserID,\n      \"isSearchMemberRemark\": isSearchMemberRemark,\n      \"isSearchMemberNickName\": isSearchMemberNickName,\n    });\n  }\n\n  /// 修改群消息接收选项\n  /// [ids] 用户ID列表\n  /// [opt] 消息接收选项\n  static Future<void> setC2CReceiveMessageOpt({required List<String> ids, required ReceiveMessageOptEnum opt}) async {\n    return _channel.invokeMethod('setC2CReceiveMessageOpt', {\"ids\": ids, \"opt\": ReceiveMessageOptTool.toInt(opt)});\n  }\n\n  /// 修改群消息接收选项\n  /// [groupID] 群ID\n  /// [opt] 消息接收选项\n  static Future<void> setGroupReceiveMessageOpt({required String groupID, required ReceiveMessageOptEnum opt}) async {\n    return _channel.invokeMethod('setGroupReceiveMessageOpt', {\"groupID\": groupID, \"opt\": ReceiveMessageOptTool.toInt(opt)});\n  }\n\n  /// 获得C2C消息接收选项\n  /// [ids] 用户ID列表\n  /// [Return] key: 用户ID，Value: 消息接收选项\n  static Future<Map<String, ReceiveMessageOptEnum>> getC2CReceiveMessageOpt({required List<String> ids}) async {\n    Map<String, int> result = await _channel.invokeMethod('getC2CReceiveMessageOpt', ids);\n    return result.map((key, value) => MapEntry(key, ReceiveMessageOptTool.getByInt(value)));\n  }\n\n  /// 初始化群属性，会清空原有的群属性列表\n  /// [groupID] 群ID\n  /// [attributes] 群属性\n  ///   1. attributes 的使用限制如下：\n  ///   2. 目前只支持 AVChatRoom\n  ///   3. key 最多支持16个，长度限制为32字节\n  ///   4. value 长度限制为4k\n  ///   5. 总的 attributes（包括 key 和 value）限制为16k\n  ///   6. initGroupAttributes、setGroupAttributes、deleteGroupAttributes 接口合并计算， SDK 限制为5秒10次，超过后回调8511错误码；后台限制1秒5次，超过后返回10049错误码\n  ///   7. getGroupAttributes 接口 SDK 限制5秒20次\n  static Future<void> initGroupAttributes({required String groupID, required Map<String, String> attributes}) async {\n    return _channel.invokeMethod('initGroupAttributes', {\n      \"groupID\": groupID,\n      \"attributes\": jsonEncode(attributes),\n    });\n  }\n\n  /// 设置群属性。已有该群属性则更新其 value 值，没有该群属性则添加该属性。\n  /// [groupID] 群ID\n  /// [attributes] 群属性\n  static Future<void> setGroupAttributes({required String groupID, required Map<String, String> attributes}) async {\n    return _channel.invokeMethod('setGroupAttributes', {\n      \"groupID\": groupID,\n      \"attributes\": jsonEncode(attributes),\n    });\n  }\n\n  /// 删除指定群属性，keys 传 null 则清空所有群属性。\n  /// [groupID] 群ID\n  /// [keys] 群属性Key,keys 传 null 则清空所有群属性。\n  static Future<void> deleteGroupAttributes({required String groupID, List<String>? keys}) async {\n    return _channel.invokeMethod(\n      'deleteGroupAttributes',\n      {\n        \"groupID\": groupID,\n        \"keys\": keys == null ? null : keys.join(\",\"),\n      }..removeWhere((key, value) => value == null),\n    );\n  }\n\n  /// 获取指定群属性，keys 传 null 则获取所有群属性。\n  /// [groupID] 群ID\n  /// [keys] 群属性Key,keys 传 null 则清空所有群属性。\n  static Future<Map<String, String>> getGroupAttributes({required String groupID, List<String>? keys}) async {\n    return (jsonDecode(await (_channel.invokeMethod(\n      'getGroupAttributes',\n      {\n        \"groupID\": groupID,\n        \"keys\": keys == null ? null : keys.join(\",\"),\n      }..removeWhere((key, value) => value == null),\n    ))))\n        .cast<String, String>();\n  }\n\n  /// 获取指定群在线人数\n  /// [groupID] 群ID\n  static Future<int> getGroupOnlineMemberCount({required String groupID}) async {\n    return await _channel.invokeMethod('getGroupOnlineMemberCount', {\n      \"groupID\": groupID,\n    });\n  }\n\n  /// 获取群成员列表。\n  /// [groupID] 群ID\n  /// [filter] 指定群成员类型\n  /// [nextSeq] 分页拉取标志，第一次拉取填0，回调成功如果 nextSeq 不为零，需要分页，传入再次拉取，直至为0。\n  static Future<GroupMemberInfoResultEntity> getGroupMemberList({required String groupID, GroupMemberFilterEnum filter: GroupMemberFilterEnum.All, int nextSeq: 0}) async {\n    return GroupMemberInfoResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getGroupMemberList', {\n      \"groupID\": groupID,\n      \"filter\": GroupMemberFilterTool.toInt(filter),\n      \"nextSeq\": nextSeq,\n    }))));\n  }\n\n  /// 获取指定的群成员资料。\n  /// [groupID] 群ID\n  /// [memberList] 群成员列表\n  static Future<List<GroupMemberEntity>> getGroupMembersInfo({required String groupID, required List<String> memberList}) async {\n    return ListUtil.generateOBJList<GroupMemberEntity>(jsonDecode(await (_channel.invokeMethod('getGroupMembersInfo', {\n      \"groupID\": groupID,\n      \"memberList\": memberList.join(\",\"),\n    }))));\n  }\n\n  /// 修改指定的群成员资料。\n  /// [groupID] 群ID\n  /// [info] 群成员对象\n  static Future<void> setGroupMemberInfo({required String groupID, required GroupMemberEntity info}) {\n    return _channel.invokeMethod('setGroupMemberInfo', {\n      \"groupID\": groupID,\n      \"info\": jsonEncode(info),\n    });\n  }\n\n  /// 禁言（只有管理员或群主能够调用）。\n  /// [groupID] 群ID\n  /// [userID] 用户ID\n  /// [seconds] 禁言时长\n  static Future<void> muteGroupMember({required String groupID, required String userID, required int seconds}) {\n    return _channel.invokeMethod('muteGroupMember', {\n      \"groupID\": groupID,\n      \"userID\": userID,\n      \"seconds\": seconds,\n    });\n  }\n\n  /// 邀请他人入群\n  /// [groupID] 群ID\n  /// [userList] 用户ID列表\n  static Future<List<GroupMemberOperationResultEntity>> inviteUserToGroup({required String groupID, required List<String> userList}) async {\n    return ListUtil.generateOBJList<GroupMemberOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('inviteUserToGroup', {\n      \"groupID\": groupID,\n      \"userList\": userList.join(\",\"),\n    }))));\n  }\n\n  /// 踢人\n  /// [groupID] 群ID\n  /// [memberList] 群成员ID列表\n  /// [reason] 理由\n  static Future<List<GroupMemberOperationResultEntity>> kickGroupMember({required String groupID, required List<String> memberList, String reason: \"\"}) async {\n    return ListUtil.generateOBJList<GroupMemberOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('kickGroupMember', {\n      \"groupID\": groupID,\n      \"memberList\": memberList.join(\",\"),\n      \"reason\": reason,\n    }))));\n  }\n\n  /// 切换群成员的角色。\n  /// [groupID] 群ID\n  /// [userID] 用户ID\n  /// [role] 角色\n  static Future<void> setGroupMemberRole({required String groupID, required String userID, required GroupMemberRoleEnum role}) {\n    return _channel.invokeMethod('setGroupMemberRole', {\"groupID\": groupID, \"userID\": userID, \"role\": GroupMemberRoleTool.toInt(role)});\n  }\n\n  /// 转让群主\n  /// [groupID] 群ID\n  /// [userID] 用户ID\n  static Future<void> transferGroupOwner({required String groupID, required String userID}) {\n    return _channel.invokeMethod('transferGroupOwner', {\"groupID\": groupID, \"userID\": userID});\n  }\n\n  /// 获取加群的申请列表\n  static Future<GroupApplicationResultEntity> getGroupApplicationList() async {\n    return GroupApplicationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getGroupApplicationList'))));\n  }\n\n  /// 同意某一条加群申请\n  /// [application] 申请对象\n  /// [reason] 理由\n  static Future<void> acceptGroupApplication({required FindGroupApplicationEntity application, String reason: \"\"}) {\n    return _channel.invokeMethod('acceptGroupApplication', {\"application\": jsonEncode(application), \"reason\": reason});\n  }\n\n  /// 拒绝某一条加群申请\n  /// [application] 申请对象\n  /// [reason] 理由\n  static Future<void> refuseGroupApplication({required FindGroupApplicationEntity application, String reason: \"\"}) {\n    return _channel.invokeMethod('refuseGroupApplication', {\"application\": jsonEncode(application), \"reason\": reason});\n  }\n\n  /// 标记申请列表为已读\n  static Future<void> setGroupApplicationRead() {\n    return _channel.invokeMethod('setGroupApplicationRead');\n  }\n\n  /// 获取会话列表\n  /// [nextSeq] 分页拉取的游标，第一次默认取传 0，后续分页拉传上一次分页拉取成功回调里的 nextSeq\n  /// [count] 分页拉取的个数，一次分页拉取不宜太多，会影响拉取的速度，建议每次拉取 100 个会话\n  static Future<ConversationResultEntity> getConversationList({int nextSeq: 0, int count: 100}) async {\n    return ConversationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getConversationList', {\"nextSeq\": nextSeq, \"count\": count}))));\n  }\n\n  /// 获得指定会话（[conversationID] | [userID] | [groupID] 参数三选一）\n  /// [conversationID] 会话ID\n  /// [userID] 用户ID\n  /// [groupID] 群ID\n  static Future<ConversationEntity> getConversation({String? conversationID, String? userID, String? groupID}) async {\n    return ConversationEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getConversation', {\"conversationID\": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID)}))));\n  }\n\n  /// 删除会话（[conversationID] | [userID] | [groupID] 参数三选一）\n  /// [conversationID] 会话ID\n  /// [userID] 用户ID\n  /// [groupID] 群ID\n  static Future<void> deleteConversation({String? conversationID, String? userID, String? groupID}) {\n    return _channel.invokeMethod('deleteConversation', {\"conversationID\": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID)});\n  }\n\n  /// 设置会话草稿（[conversationID] | [userID] | [groupID] 参数三选一）\n  /// [conversationID] 会话ID\n  /// [userID] 用户ID\n  /// [groupID] 群ID\n  /// [draftText] 草稿内容，null代表取消设置\n  static Future<void> setConversationDraft({String? conversationID, String? userID, String? groupID, String? draftText}) {\n    return _channel.invokeMethod(\n      'setConversationDraft',\n      {\n        \"conversationID\": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID),\n        \"draftText\": draftText,\n      }..removeWhere((key, value) => value == null),\n    );\n  }\n\n  /// 会话置顶，可在 [conversationID] 会话ID | [userID] 用户ID | [groupID] 群组ID 三选一\n  /// [isPinned] 是否需要置顶\n  static Future<void> pinConversation({String? conversationID, String? userID, String? groupID, required bool? isPinned}) {\n    return _channel.invokeMethod('pinConversation', {\"conversationID\": _getConversationID(conversationID: conversationID, userID: userID, groupID: groupID), \"isPinned\": isPinned});\n  }\n\n  /// 获得会话总未读数\n  /// 未读总数会减去设置为免打扰的会话的未读数，即消息接收选项设置为 V2TIMMessage.V2TIM_NOT_RECEIVE_MESSAGE 的会话。\n  static Future<int> getTotalUnreadMessageCount() async => await _channel.invokeMethod('getTotalUnreadMessageCount');\n\n  /// 获取用户资料\n  /// [userList] 用户ID列表\n  static Future<List<UserEntity>> getUsersInfo({required List<String> userIDList}) async {\n    return ListUtil.generateOBJList<UserEntity>(jsonDecode(await (_channel.invokeMethod('getUsersInfo', {\n      \"userIDList\": userIDList.join(\",\"),\n    }))));\n  }\n\n  /// 修改个人资料，注意：此接口调用后马上调用 getUsersInfo 可能会刷新不及时，可以使用Future.\n  /// [info] 资料对象\n  static Future<void> setSelfInfo({required UserEntity info}) {\n    return _channel.invokeMethod('setSelfInfo', {\"info\": jsonEncode(info)});\n  }\n\n  /// 添加用户到黑名单\n  /// [userIDList] 用户ID列表\n  static Future<List<FriendOperationResultEntity>> addToBlackList({\n    required List<String> userIDList,\n  }) async {\n    return ListUtil.generateOBJList<FriendOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('addToBlackList', {\"userIDList\": userIDList.join(\",\")}))));\n  }\n\n  /// 从黑名单中删除\n  /// [userIDList] 用户ID列表\n  static Future<List<FriendOperationResultEntity>> deleteFromBlackList({\n    required List<String> userIDList,\n  }) async {\n    return ListUtil.generateOBJList<FriendOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('deleteFromBlackList', {\"userIDList\": userIDList.join(\",\")}))));\n  }\n\n  /// 获得黑名单列表\n  static Future<List<FriendInfoEntity>> getBlackList() async {\n    return ListUtil.generateOBJList<FriendInfoEntity>(jsonDecode(await (_channel.invokeMethod('getBlackList'))));\n  }\n\n  /// 设置离线推送Token,Android使用setOfflinePushConfig，IOS使用setAPNS\n  /// [token] Token\n  /// [bussid] 推送证书 ID，是在 IM 控制台上生成的\n  ///\n  /// [tpns] 是否是tpnsToken\n  static Future<void> setOfflinePushConfig({required String token, required int bussid, required bool tpns}) {\n    return _channel.invokeMethod('setOfflinePushConfig', {\n      \"token\": token,\n      \"bussid\": bussid,\n      \"tpns\": tpns,\n    });\n  }\n\n  /// 设置未读桌标，Android使用doBackground，IOS更改setAPNSListener值\n  /// [number] 桌标数量\n  static Future<void> setUnreadBadge({required int number}) {\n    return _channel.invokeMethod('setUnreadBadge', {\n      \"number\": number,\n    });\n  }\n\n  /// 获得好友列表\n  static Future<List<FriendInfoEntity>> getFriendList() async {\n    return ListUtil.generateOBJList<FriendInfoEntity>(jsonDecode(await (_channel.invokeMethod('getFriendList'))));\n  }\n\n  /// 获得指定好友信息\n  /// [userIDList] 好友ID列表\n  static Future<List<FriendInfoResultEntity>> getFriendsInfo({required List<String> userIDList}) async {\n    return ListUtil.generateOBJList<FriendInfoResultEntity>(jsonDecode(await (_channel.invokeMethod('getFriendsInfo', {\n      \"userIDList\": userIDList.join(\",\"),\n    }))));\n  }\n\n  /// 设置好友资料\n  /// [info] 好友资料\n  static Future<void> setFriendInfo({required FriendInfoEntity info}) {\n    return _channel.invokeMethod('setFriendInfo', {\n      \"info\": jsonEncode(info),\n    });\n  }\n\n  /// 添加好友\n  /// [info] 申请对象\n  static Future<FriendOperationResultEntity> addFriend({required FriendAddApplicationEntity info}) async {\n    return FriendOperationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('addFriend', {\n      \"info\": jsonEncode(info),\n    }))));\n  }\n\n  /// 删除好友\n  /// [userIDList] 好友ID列表，ID 建议一次最大 100 个，因为数量过多可能会导致数据包太大被后台拒绝，后台限制数据包最大为 1M\n  /// [deleteType] 删除类型\n  static Future<List<FriendOperationResultEntity>> deleteFromFriendList({required List<String> userIDList, required FriendTypeEnum deleteType}) async {\n    return ListUtil.generateOBJList<FriendOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('deleteFromFriendList', {\n      \"userIDList\": userIDList.join(\",\"),\n      \"deleteType\": FriendTypeTool.toInt(deleteType),\n    }))));\n  }\n\n  /// 检查好友关系\n  /// [userID] 用户ID\n  /// [checkType] 检测类型类型\n  static Future<FriendCheckResultEntity> checkFriend({required String userID, required FriendTypeEnum checkType}) async {\n    return FriendCheckResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('checkFriend', {\n      \"userID\": userID,\n      \"checkType\": FriendTypeTool.toInt(checkType),\n    }))));\n  }\n\n  /// 获取好友申请列表\n  static Future<FriendApplicationResultEntity> getFriendApplicationList() async {\n    return FriendApplicationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('getFriendApplicationList'))));\n  }\n\n  /// 同意好友申请\n  /// [application] 查找好友申请对象实体\n  /// [responseType] 建立关系类型\n  static Future<FriendOperationResultEntity> acceptFriendApplication({required FindFriendApplicationEntity application, required FriendApplicationAgreeTypeEnum responseType}) async {\n    return FriendOperationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('acceptFriendApplication', {\n      \"application\": jsonEncode(application),\n      \"responseType\": FriendApplicationAgreeTypeTool.toInt(responseType),\n    }))));\n  }\n\n  /// 拒绝好友申请\n  /// [application] 查找好友申请对象实体\n  static Future<FriendOperationResultEntity> refuseFriendApplication({required FindFriendApplicationEntity application}) async {\n    return FriendOperationResultEntity.fromJson(jsonDecode(await (_channel.invokeMethod('refuseFriendApplication', {\n      \"application\": jsonEncode(application),\n    }))));\n  }\n\n  /// 删除好友申请\n  /// [application] 查找好友申请对象实体\n  static Future<void> deleteFriendApplication({required FindFriendApplicationEntity application}) {\n    return _channel.invokeMethod('deleteFriendApplication', {\n      \"application\": jsonEncode(application),\n    });\n  }\n\n  /// 设置好友申请为已读\n  static Future<void> setFriendApplicationRead() {\n    return _channel.invokeMethod('setFriendApplicationRead');\n  }\n\n  /// 新建好友分组\n  /// [groupName] 组名\n  /// [userIDList] 用户列表\n  static Future<List<FriendOperationResultEntity>> createFriendGroup({required String groupName, required List<String> userIDList}) async {\n    return ListUtil.generateOBJList<FriendOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('createFriendGroup', {\n      \"groupName\": groupName,\n      \"userIDList\": userIDList.join(\",\"),\n    }))));\n  }\n\n  /// 获取分组信息\n  /// [groupNameList] 分组名称\n  static Future<List<FriendGroupEntity>> getFriendGroups({List<String>? groupNameList}) async {\n    return ListUtil.generateOBJList<FriendGroupEntity>(jsonDecode(await (_channel.invokeMethod(\n      'getFriendGroups',\n      {\n        \"groupNameList\": groupNameList?.join(\",\"),\n      }..removeWhere((key, value) => value == null),\n    ))));\n  }\n\n  /// 删除好友分组\n  /// [groupNameList] 分组名称\n  static Future<void> deleteFriendGroup({required List<String> groupNameList}) {\n    return _channel.invokeMethod('deleteFriendGroup', {\n      \"groupNameList\": groupNameList.join(\",\"),\n    });\n  }\n\n  /// 修改分组名称\n  /// [oldName] 旧名称\n  /// [newName] 新名称\n  static Future<void> renameFriendGroup({required String oldName, required String newName}) {\n    return _channel.invokeMethod('renameFriendGroup', {\n      \"oldName\": oldName,\n      \"newName\": newName,\n    });\n  }\n\n  /// 添加好友到分组\n  /// [groupName] 组名\n  /// [userIDList] 好友ID\n  static Future<List<FriendOperationResultEntity>> addFriendsToFriendGroup({required String groupName, required List<String> userIDList}) async {\n    return ListUtil.generateOBJList<FriendOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('addFriendsToFriendGroup', {\n      \"groupName\": groupName,\n      \"userIDList\": userIDList.join(\",\"),\n    }))));\n  }\n\n  /// 从分组中删除好友\n  /// [groupName] 组名\n  /// [userIDList] 好友ID\n  static Future<List<FriendOperationResultEntity>> deleteFriendsFromFriendGroup({required String groupName, required List<String> userIDList}) async {\n    return ListUtil.generateOBJList<FriendOperationResultEntity>(jsonDecode(await (_channel.invokeMethod('deleteFriendsFromFriendGroup', {\n      \"groupName\": groupName,\n      \"userIDList\": userIDList.join(\",\"),\n    }))));\n  }\n\n  /// 根据[param] 消息搜索参数对象 搜索本地消息\n  static Future<void> searchLocalMessages({required MessageSearchParam param}) {\n    return _channel.invokeListMethod(\"searchLocalMessages\", param.toJson());\n  }\n\n  /// 添加消息监听\n  static void addListener(TencentImListenerValue func) => listener.addListener(func);\n\n  /// 移除消息监听\n  static void removeListener(TencentImListenerValue func) => listener.removeListener(func);\n}\n"
  },
  {
    "path": "lib/utils/enum_util.dart",
    "content": "/// 枚举工具类\nclass EnumUtil {\n  /// 获得枚举的名称(不包含前缀)\n  static String getEnumName(enumObj) {\n    var es = enumObj.toString().split(\".\");\n    return es[es.length - 1];\n  }\n\n  /// 根据名字获得枚举\n  static T? nameOf<T>(List<T> array, String name) {\n    for (var item in array) {\n      if (EnumUtil.getEnumName(item) == name) {\n        return item;\n      }\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "pubspec.yaml",
    "content": "name: tencent_im_plugin\ndescription: This plug-in integrates Tencent cloud 'imsdk', realizes cross platform im access, and is compatible with Android and IOS devices.\nversion: 3.0.0\nhomepage: https://www.yuque.com/jiangjuhong/tencent-im-flutter/zk6p14\nrepository: https://github.com/JiangJuHong/FlutterTencentImPlugin\n\nenvironment:\n  sdk: '>=2.12.0 <3.0.0'\n  flutter: \">=1.12.0\"\n\ndependencies:\n  flutter:\n    sdk: flutter\n  # 生成UUID(https://pub.dev/packages/uuid)\n  uuid: ^3.0.3\n  # 日志输出(https://pub.dev/packages/logger)\n  logger: ^1.0.0\n\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n\n# For information on the generic Dart part of this file, see the\n# following page: https://dart.dev/tools/pub/pubspec\n\n# The following section is specific to Flutter.\nflutter:\n  # This section identifies this Flutter project as a plugin project.\n  # The androidPackage and pluginClass identifiers should not ordinarily\n  # be modified. They are used by the tooling to maintain consistency when\n  # adding or updating assets for this project.\n  plugin:\n    platforms:\n      android:\n        package: top.huic.tencent_im_plugin\n        pluginClass: TencentImPlugin\n      ios:\n        pluginClass: TencentImPlugin\n\n  # To add assets to your plugin package, add an assets section, like this:\n  # assets:\n  #  - images/a_dot_burr.jpeg\n  #  - images/a_dot_ham.jpeg\n  #\n  # For details regarding assets in packages, see\n  # https://flutter.dev/assets-and-images/#from-packages\n  #\n  # An image asset can refer to one or more resolution-specific \"variants\", see\n  # https://flutter.dev/assets-and-images/#resolution-aware.\n\n  # To add custom fonts to your plugin package, add a fonts section here,\n  # in this \"flutter\" section. Each entry in this list should have a\n  # \"family\" key with the font family name, and a \"fonts\" key with a\n  # list giving the asset and other descriptors for the font. For\n  # example:\n  # fonts:\n  #   - family: Schyler\n  #     fonts:\n  #       - asset: fonts/Schyler-Regular.ttf\n  #       - asset: fonts/Schyler-Italic.ttf\n  #         style: italic\n  #   - family: Trajan Pro\n  #     fonts:\n  #       - asset: fonts/TrajanPro.ttf\n  #       - asset: fonts/TrajanPro_Bold.ttf\n  #         weight: 700\n  #\n  # For details regarding fonts in packages, see\n  # https://flutter.dev/custom-fonts/#from-packages\n"
  }
]