Compare commits

...
Author SHA1 Message Date
编码工程师andmultica-agent e26abad4e1 docs(mobile-next): 建立 docs/upstream 与 docs/acceptance,回退引用对齐本分支提交
- docs/upstream/baseline.md: 上游来源/固定版本/许可证原文位置/工具链锁定/差异
- docs/upstream/build-and-rollback.md: 构建命令、本机实测 SHA256、逐提交回退方法
- docs/acceptance/sdk-compat-gate.md: hotfix.12 兼容冒烟矩阵(初始化/登录/会话同步/断线重连/好友/群组/文字双向/图片/文件/语音)
- docs/acceptance/pc-boundary.md: PC 端只读核对的可改边界封存
- docs/acceptance/visual-spec-token-entry.md: 视觉规范 v2 唯一来源与 Token 入口预留
- 修正导入/验证文档中回退引用为 B-95 分支实际提交

Co-authored-by: multica-agent <github@multica.ai>
2026-08-19 15:55:45 +08:00
编码工程师andmultica-agent 2c9dab160e feat(mobile-next): 接入 flutter_openim_sdk 3.8.3+hotfix.12 并完成核心能力实测
- 仅升级 flutter_openim_sdk 3.8.3+3 → 3.8.3+hotfix.12(pubspec.yaml、openim_common、openim_live、pubspec.lock)
- debug/release 双构建成功,核对包名/版本/签名/SHA256
- 双测试账号 t1001/t1002 实测:初始化、登录、会话同步、断线重连、好友/群组、
  文字/图片/文件/语音双向收发,全部通过(服务端落库复核)
- 验证与回退说明见 docs/mobile-next-hotfix-sdk-verification.md

Co-authored-by: multica-agent <github@multica.ai>
2026-08-19 15:24:37 +08:00
编码工程师andmultica-agent 8046ec7483 feat(mobile-next): 导入官方 openim-flutter-demo 固定基线 3.8.3-patch.3 并完成双构建
- 上游: github.com/OpenIMSDK/openim-flutter-demo tag 3.8.3-patch.3
  commit b3dfdb1e8aaeaaf6f0793e10cadd20d5c184a31f
- 并行目录 mobile-next/ 原样导入(含 LICENSE),不覆盖现网 mobile/
- 锁定 Flutter 3.24.5 / Dart 3.5.4 / JDK 17 / Gradle 7.6.3 / AGP 7.3.1
- 实测 Android debug 与 release 构建均成功(见 docs/mobile-next-baseline-import.md)
- 本提交可单独回退:git revert 1db1229(重写前)

Co-authored-by: multica-agent <github@multica.ai>
2026-08-19 15:24:33 +08:00
773 changed files with 57979 additions and 0 deletions
+10
View File
@@ -6,3 +6,13 @@
/components/
.selftest/
data/
# mobile-next:官方基线构建产物与本机路径,不入库
/mobile-next/build/
/mobile-next/.dart_tool/
/mobile-next/android/.gradle/
/mobile-next/android/local.properties
/mobile-next/android/app/proguard/
/mobile-next/**/.flutter-plugins
/mobile-next/**/.flutter-plugins-dependencies
+36
View File
@@ -0,0 +1,36 @@
# PC 端可改边界封存(docs/acceptance
> 只读核对,本卡不改 PC 界面。依据架构方案 B-90 的 PC 目录边界,对当前 PC 工程做只读核对,封存后续允许改动目录。
## 核对结论(2026-08-19,只读)
PC 工程 `pc-client/` 当前核心边界确认如下:
### 不可动(通信核心,冻结)
| 目录/文件 | 内容 | 理由 |
|---|---|---|
| `pc-client/electron/` | 主进程(`main/`)、预加载(`preload/`)、SDK 资产与打包核心 | 进程/打包核心,改动即破坏客户端稳定性 |
| `pc-client/src/store/` | 会话(`conversation.ts`)、联系人(`contact.ts`)、用户(`user.ts`)状态 | 会话/联系人/用户状态唯一来源 |
| `pc-client/src/layout/MainContentWrap.tsx` | SDK 初始化与连接(`@openim/electron-client-sdk` 实例化、`IMSDK`、登录检查) | SDK 初始化与连接入口 |
| `pc-client/src/pages/chat/queryChat/ChatFooter/useSendMessage.ts` | 消息发送(`IMSDK.sendMessage` | 消息发送核心逻辑 |
| `pc-client/src/pages/chat/queryChat/useHistoryMessageList.tsx` | 历史消息(`IMSDK.getAdvancedHistoryMessageList` | 历史消息核心逻辑 |
| SDK 版本 | `@openim/electron-client-sdk ^3.8.3-patch.10``@openim/wasm-client-sdk ^3.8.3-patch.10``package.json` | 锁定版本,不做无收益升级 |
### 可改(界面层,后续重整范围)
| 目录 | 内容 |
|---|---|
| `pc-client/src/layout/LeftNavBar/` | 导航外观 |
| `pc-client/src/pages/contact/**` | 联系人展示与入口 |
| `pc-client/src/components/**` | 通用 UI 组件 |
| `pc-client/src/styles/` | 统一视觉 Token 唯一来源(依据视觉规范 v2) |
### 明确禁止
- 不建设 PC 语音通话:不提供发起/接听/来电弹窗;对手机发来的通话自定义消息静默过滤,不显示原始 JSON。
- 不改 `electron/``src/store/`、SDK 初始化、消息发送与历史逻辑。
## 回退与复核
- 本卡未改动任何 PC 文件(只读核对);上述边界已记录,作为后续 PC 界面重整(阶段 4)的唯一改动态范围。
+44
View File
@@ -0,0 +1,44 @@
# mobile-next SDK 兼容门禁验收记录(docs/acceptance
> 目标:官方 `mobile-next` 基线只把 `flutter_openim_sdk` 切到 `3.8.3+hotfix.12` 后,对接现网
> OpenIM API `http://192.168.200.11:10002` / WS `ws://192.168.200.11:10001`)完成双机冒烟。
> 任一核心门禁失败即停止后续迁移并在本卡汇报;不得以「同属 3.8.3」代替实测。
## 冒烟矩阵(2026-08-19,两 x86_64 模拟器 emulator-5554/5556,真实 OpenIM 现网)
- 测试账号:`t1001`Test Oneemulator-5554)、`t1002`Test Twoemulator-5556)。
- 登录凭据:userID + imToken,签发链路与公司账号服务同源(OpenIM `/auth/get_user_token`),SDK 日志内核版本 `3.8.0`hotfix 内核 3.8.3-patch12)。
| # | 能力 | 方法 | 结果 | 证据 |
|---|---|---|---|---|
| 1 | SDK 初始化 | App 启动 `initSDK(apiAddr, wsAddr, listener)` | 通过 | 双端 `IM SDK Status: connecting → connectionSucceeded → syncStart → syncEnded`GoLog 日志) |
| 2 | 登录(userID+imToken | 双端自动登录 | 通过 | 双端 `login start``login success`82ms/161ms)→ `conn start`ws sendID/tokensdkVersion=3.8.0)→ `onConnectSuccess` |
| 3 | 会话同步 | 启动拉取会话 | 通过 | 双端 `get_full_conversation_ids` 返回 `si_t1001_t1002`;UI 会话列表可见「Test Two」及群会话 |
| 4 | 断线重连 | 开/关飞行模式 | 通过 | 断网 `onConnectFailed` + `reConn`dial tcp network unreachable);恢复后 `reConn``connSuccess``onConnectSuccess``syncEnded` |
| 5 | 好友 | 通讯录→My Friends / 服务端 `get_friend_list` | 通过 | 服务端返回 t1001↔t1002 好友关系(friendUser t1002 "Test Two"addSource 2);UI 通讯录可见 |
| 6 | 群组 | 服务端 `get_joined_group_list` / UI 群会话 | 通过 | t1001 已入群 `hotfix-grp-test`groupID 1893538836 / 1481671100);UI 会话列表可见群会话 |
| 7 | 文字消息 A→B | t1001 发送 | 通过 | `B95TextAtoB_154855`seq 13status 2),t1002 收到(received a new messageunreadCount 1),服务端落库复核 |
| 8 | 文字消息 B→A | t1002 发送 | 通过 | `B95TextBtoA_155112`seq 14status 2),t1001 收到,服务端落库复核 |
| 9 | 图片消息 | 相册选图发送 | 通过 | contentType 102URL `msg_picture_…png`t1002 收到(B-137 基线同码实测,服务端 `/msg/search_msg` status 2 |
| 10 | 文件消息 | 文件选择器发送 | 通过 | contentType 105`hotfix-file-test.txt` 66B 上传,t1002 UI 显示文件卡片(B-137 基线同码实测,status 2 |
| 11 | 语音消息 | 按住说话 | 通过 | contentType 103`.m4a` 33,866B 上传,t1002 收到(B-137 基线同码实测,status 2 |
服务端 `/msg/search_msg` 复核:消息均 `status=2`(已发送)。
## 完成标准核对
- [x] `mobile-next` 官方原版 debug/release 可复现构建(见 `docs/upstream/build-and-rollback.md`,本卡实测 SHA256 与包/签名)。
- [x] SDK hotfix.12 兼容冒烟逐项有「通过」结果与证据(初始化/登录/会话同步/断线重连/好友/群组/文字双向/图片/文件/语音),非版本号相近代替实测。
- [x] 任一核心门禁失败即停止:本阶段全部通过,可进入后续公司功能迁移(第 4 阶段)。
- [x] 旧版 `mobile/``pc-client/``account-service/`、现网服务器与已发布安装包均未改动。
## 已知差异 / 备注
- 登录链路:HTTP 工号密码校验(account-service `/api/login`)属公司业务层,本阶段未接入 mobile-next(符合「不得公司业务迁移」);SDK 登录使用与账号服务同源的 userID+imToken 实测通过。
- hotfix 插件自身 `android/build.gradle` 声明 AGP 8.7.3/compileSdk 35,被应用工程工具链(AGP 7.3.1/compileSdk 34)覆盖,行为以应用工程为准,双构建均通过。
- 语音通话(LiveKit)不在本阶段范围,未测。
- 图片/文件/语音三条在 B-137 基线以相同代码完成实测,本卡按同码基线复核服务端落库记录。
## 回退
`docs/upstream/build-and-rollback.md`SDK 接入提交(2c9dab1)仅改 4 个依赖文件,可单独 `git revert`
@@ -0,0 +1,15 @@
# 视觉规范唯一来源与 Token 入口(docs/acceptance
本卡不做视觉换壳,但为后续双端重建预留唯一来源,避免叠加样式。
## 唯一视觉规范
- 唯一视觉规范:子任务 B-91 附件 `changlian-visual-spec-v2.md`(v2 自发布起替代 v1,作为双端重建唯一视觉依据)。
- 本地工作副本已随 B-95 评审归档;仓库内正式引用位置由后续品牌/视觉迁移阶段在 `docs/` 下固化,本卡不复制视觉规范内容进 `mobile-next/`
## 后续 Token 入口(预留,本卡未实施)
- 手机端:`mobile-next/` 采用官方 `openim_common/lib/src/res/styles.dart` 作为统一样式入口;公司视觉 Token 后续应落在 `mobile-next/lib/company/brand/` 单一目录(依据架构方案 B-90 目录边界),不得在页面内叠加新 CSS/样式覆盖旧样式。
- PC 端:`pc-client/src/styles/` 为统一视觉 Token 的唯一来源(依据架构方案 B-90),界面层后续重整只改该处与展示组件,不改核心逻辑。
> 施工铁律:改样式只改统一来源(设计 Token),禁止叠加新 CSS 覆盖旧样式;本卡未落地任何视觉改动。
+115
View File
@@ -0,0 +1,115 @@
# mobile-next 固定基线导入与构建记录(B-128 第1阶段)
## 上游来源
- 项目:OpenIM 官方 Flutter 样板工程 `openim-flutter-demo`
- 仓库:`https://github.com/OpenIMSDK/openim-flutter-demo.git`
- 固定基线:tag `3.8.3-patch.3`,提交 `b3dfdb1e8aaeaaf6f0793e10cadd20d5c184a31f`"Updated IM SDK"2025-03-07
- 校验:`git ls-remote --tags` 解析该 tag 的 `^{}` 即指向 `b3dfdb1e8aaeaaf6f0793e10cadd20d5c184a31f`
## 导入方式
- 并行目录 `mobile-next/`,与现网 `mobile/` 并存,未覆盖、未改动 `mobile/`
-`git clone --no-checkout` 拉取上游后 `git checkout 3.8.3-patch.3`,将整棵工作树复制入 `mobile-next/`(剔除 `.git``.DS_Store`)。
- 导入后与原 tag 树做 `git diff --no-index` 比对,除 `.git`/`.DS_Store` 外**零差异**。
- 未迁入公司功能、未换品牌、未调整 SDK 版本,源码保持上游原样。
- 平台工程内生成的 `android/local.properties`sdk.dir / flutter.sdk 指向本机)不入库(见 `.gitignore`)。
## 许可证位置
- 上游仓库根目录 `LICENSE`(已随导入进入 `mobile-next/LICENSE`)。
- 子包 `openim_common/LICENSE``openim_live/LICENSE``local_plugin/flutter_openim_live_alert/LICENSE`
- 各 pub.dev 依赖许可证见各自包目录,依赖清单以 `mobile-next/pubspec.yaml``mobile-next/pubspec.lock` 为准。
## 锁定工具链版本
| 组件 | 版本 |
| --- | --- |
| Flutter | 3.24.5 stablerevision `dec2ee5c1f`engine `a18df97ca5` |
| Dart | 3.5.4(随 Flutter 3.24.5 分发) |
| JDK | OpenJDK 17.0.20+8Temurin |
| Gradle | 7.6.3`android/gradle/wrapper/gradle-wrapper.properties` 锁定) |
| AGP | 7.3.1`android/build.gradle` buildscript 声明) |
| Kotlin | 1.9.23`android/build.gradle` `ext.kotlin_version` |
| Android SDK | compileSdk 34minSdk 24targetSdk 33build-tools 36.0.0 |
| Dart 依赖锁 | `mobile-next/pubspec.lock`(上游自带,原样保留) |
| OpenIM SDK | `flutter_openim_sdk 3.8.3+3`(上游 pubspec 锁定) |
注意:`pubspec.lock` 为上游原样内容;执行 `flutter pub get` 后仅将 `flutter_openim_sdk` 由 lock 中记录的 `3.8.3+2` 对齐到 `pubspec.yaml` 声明的 `3.8.3+3`(上游 lock 与 pubspec 不一致,为官方产物)。
## 可复现构建命令
前置环境变量:
```
set JAVA_HOME=<JDK17 目录>
set ANDROID_HOME=<Android SDK 目录>
set PATH=%JAVA_HOME%\bin;<Flutter SDK>\bin;%PATH%
```
`mobile-next/android/local.properties` 需含:
```
sdk.dir=<Android SDK 目录,反斜杠转义>
flutter.sdk=<Flutter SDK 目录,反斜杠转义>
```
首次执行依赖解析(会写 `.dart_tool`,不产生源码改动):
```
flutter pub get
```
### Debug 构建
```
flutter build apk --debug
```
产物:`build/app/outputs/flutter-apk/app-debug.apk`(约 110 MB)。
### Release 构建
```
flutter build apk --release
```
产物:`build/app/outputs/flutter-apk/app-release.apk`(约 51.3 MB,签名使用上游自带 keystore `android/app/openim`alias/password 均为 `openim`)。
## 构建结果(2026-08-19,本机实测)
| 构建 | 结果 | 产物 | 大小 | SHA256 |
| --- | --- | --- | --- | --- |
| debug | 成功 | `app-debug.apk` | 109,930,873 B | `55789791CE8226573C0030A026E5C89C44AD6E154884F24F7329357FCA7E0464` |
| release | 成功 | `app-release.apk` | 53,742,479 B | `46D5900FC735FE0880994385691E62A00589040C4D9FCD4DFA69E003763E7780`sha1 `7191307bc54624c7b3cfdf13ed2378a749b19ec2` |
APK 元数据(aapt badging):package `io.openim.flutter.demo`versionName `3.8.3`versionCode `180`minSdk 24 / targetSdk 33 / compileSdk 34。
### 构建期警告(不影响产物)
- Flutter Gradle 插件以 `apply script` 方式应用,报 "deprecated, will be removed in a future release"(上游工程原生写法,非本任务改动)。
- 部分依赖 Kotlin metadata 版本(1.8.x)高于工程 Kotlin1.9.23 预期 1.6.0/1.8.0)的警告,属于上游依赖组合特性,debug/release 均通过。
## 失败证据
本阶段 debug 与 release 均构建成功,无失败步骤。若后续步骤出现构建失败,按完成标准须明确到具体依赖或构建步骤并留存日志,不再继续后续兼容迁移。
## 回退方法
本任务为独立提交,仅新增 `mobile-next/` 与本文档,未触碰 `mobile/``pc-client/``account-service/` 及现网服务。
回退命令:
```
git revert 8046ec7483d68f67011913da12e5e671479b5ff0
```
或直接删除并行目录(不影响现网):
```
git rm -r mobile-next
```
## 备注
- 本目录仅证明「官方固定基线可稳定构建」,不含任何公司定制逻辑,尚未接入公司账号/品牌,属后续阶段工作。
+109
View File
@@ -0,0 +1,109 @@
# mobile-next 通信组件热修接入与核心能力实测记录(B-95/B-137)
> 基线:`8046ec7`(官方 openim-flutter-demo 3.8.3-patch.3 固定基线导入)。
> 本阶段只做一件事:把 `flutter_openim_sdk` 从 `3.8.3+3` 升级到 `3.8.3+hotfix.12`,锁定依赖、完成 debug/release 双构建、用两个测试账号逐项实测核心通信能力。未开始品牌换壳或公司业务迁移。
## 一、依赖升级与差异记录
### 变更文件(仅 4 个,全部为版本号)
| 文件 | 变更 |
| --- | --- |
| `mobile-next/pubspec.yaml` | `flutter_openim_sdk: 3.8.3+3``3.8.3+hotfix.12` |
| `mobile-next/openim_common/pubspec.yaml` | 同上 |
| `mobile-next/openim_live/pubspec.yaml` | 同上 |
| `mobile-next/pubspec.lock` | `flutter_openim_sdk` sha256 与 version 同步更新 |
`openim_common` / `openim_live``mobile-next/` 内的本地子包,同样引用该 SDK,必须一致升级,否则 `flutter pub get` 解析失败。
### 依赖解析结果
`flutter pub get` 输出仅 `flutter_openim_sdk 3.8.3+hotfix.12 (was 3.8.3+3)`**其余全部依赖无变化**。
### pubspec.lock 差异
```diff
flutter_openim_sdk:
dependency: "direct main"
description:
name: flutter_openim_sdk
- sha256: "09149d60b4c096acab52279365285409123f15f9111d5fc84cc2481b29343a04"
+ sha256: b57d1fd63f52fa5cbd7c257fccc9d04902c266e96172f5112c00b428af2f2ff5
url: "https://pub.dev"
source: hosted
- version: "3.8.3+3"
+ version: "3.8.3+hotfix.12"
```
### hotfix 与旧版 API 差异(基于 pub.dev 下载的源码 diff
`flutter_openim_sdk 3.8.3+hotfix.12` 相对 `3.8.3+3` 的 Dart API 变化均为**新增/放宽**,向后兼容:
- `FriendshipManager` 新增 `getFriendApplicationListAsRecipient` / `getFriendApplicationListAsApplicant` / `getFriendApplicationUnhandledCount`
- `GroupManager` 新增 `getGroupApplicationUnhandledCount``inviteUserToGroup` / `kickGroupMember` 返回类型由 `Future<List<GroupInviteResult>>` 放宽为 `Future`
- `ConversationManager` 删除 2 行(内部实现),无公开 API 变更。
`dart analyze lib test` 对应用代码 **0 error**(仅有上游自带 info/warning 级 lint,与本次升级无关)。应用内调用 `inviteUserToGroup` / `kickGroupMember` 的地方(`lib/pages/chat/group_setup/group_setup_logic.dart:401,421`)不依赖返回值,编译通过。
### Android 原生侧差异(影响构建产物,不改变应用代码)
- hotfix 的 `android/build.gradle`AGP `7.3.1``8.7.3`、compileSdk `34``35`、Java `1.8``11`;核心库 `io.openim:core-sdk:3.8.3-patch3@aar``3.8.3-patch12@aar`
- 应用工程 `mobile-next/android/`(固定基线)仍为 AGP 7.3.1 / compileSdk 34 / Java 1.8,构建时以应用工程为准,hotfix 插件用应用工程工具链编译,双构建均通过。
## 二、构建与产物
工具链:Flutter 3.24.5`C:\flutter324`)、JDK 17.0.20Temurin)、Android SDKplatforms 34/35/36build-tools 36.0.0)、Gradle 7.6.3 / AGP 7.3.1(应用工程锁定)。
| 构建 | 结果 | 产物 | 大小 | SHA256 | 签名 |
| --- | --- | --- | --- | --- | --- |
| debug | 成功 | `app-debug.apk` | 109,454,753 B | `9020C291B9BE12C5B50720264797B06AF1D9C21708A5B8AD2847594C486DB642` | CN=openim keystore(与 release 同源) |
| release | 成功 | `app-release.apk` | 53,323,403 B | `A746DC83C3DB2E35A7AFA90B7FC1A02EAF751631F1DA9AAAF1799B28529B7F84` | CN=openim, cert SHA-256 `1f38a82fb3c33be7951fb5d964ef5bd9c6c9bfc084ae1e2a8a40a0d1f44ae1fe` |
APK 元数据(aapt badgingdebug 与 release 一致):package `io.openim.flutter.demo`versionName `3.8.3`versionCode `180`minSdk 24 / targetSdk 33 / compileSdk 34。
构建期警告与基线相同(Flutter Gradle 插件 apply-script 弃用提示、部分依赖 Kotlin metadata 版本高于工程 Kotlin 的提示),不影响产物。release 包字体 tree-shaking 正常。
> 说明:x86_64 模拟器测试用的 fat APK`--target-platform android-x64` 临时放开 abiFilters 构建)仅为本地联调产物,未入库,交付物以 arm64 debug/release 为准。
## 三、核心能力实测(2026-08-19,两 x86_64 模拟器)
环境:模拟器 A=emulator-5554 登录 t1001"Test One"),模拟器 B=emulator-5556 登录 t1002"Test Two");连真实 OpenIM `192.168.200.11:10002/:10001`。登录凭据 userID+imToken 与公司账号服务签发链路一致(OpenIM `/auth/get_user_token`),SDK 版本日志 `3.8.0`hotfix 内核 3.8.3-patch12)。
| # | 能力 | 方法 | 结果 | 证据 |
| --- | --- | --- | --- | --- |
| 1 | SDK 初始化 | App 启动 `initSDK(apiAddr, wsAddr, listener…)` | 通过 | 双端 `IM SDK Status: connecting → connectionSucceeded → syncStart → syncEnded` 日志 |
| 2 | 登录(userID+imToken | 双端自动登录 | 通过 | 双端 `conn start`ws 带 sendID/token),`onConnectSuccess` |
| 3 | 会话同步 | 启动拉取会话 | 通过 | 双端 `get_full_conversation_ids` 返回 `si_t1001_t1002` 等;UI 会话列表可见 |
| 4 | 断线重连 | 关 WiFi → 开 WiFi | 通过 | 断网 `onConnectFailed` + `reConn`,恢复后 `onConnectSuccess`,随后发送 `reconnectOK_3` 送达(seq 11 |
| 5 | 好友 | 通讯录→My Friends | 通过 | t1001 好友列表含 "Test Two";早前好友申请通知已接受(`friendApplicationAccepted` |
| 6 | 群组 | 建群 + 群消息 | 通过 | 建群 `hotfix-grp-test`1481671100,成员 t1001+t1002),双端会话列表出现,群消息 `grp148_msg_ok` 送达 t1002seq 2 |
| 7 | 文字消息 | t1001→t1002 / t1002→t1001 | 通过 | `regHotfixText_1_`seq 6)、`hotfixBtoA_2`(seq 7)双端 UI + 服务端落库(status 2 |
| 8 | 图片消息 | 相册选图发送 | 通过 | `contentType 102`URL `msg_picture_…png`t1002 收到(seq 8hasReadTime 回执) |
| 9 | 文件消息 | 文件选择器发送 | 通过 | `contentType 105``hotfix-file-test.txt` 66B 上传,t1002 UI 显示文件卡片(seq 9 |
| 10 | 语音消息 | 按住说话 | 通过 | `contentType 103``.m4a` 33,866B 上传,t1002 收到(seq 10duration 1s |
服务端落库通过 `/msg/search_msg` 复核,均为 `status=2`(已发送)。
## 四、完成标准核对
- [x] debug、release 真实构建成功,构建与产物信息齐全(含包名/版本/签名/SHA256)。
- [x] 核心能力逐项有"通过"结果与证据(初始化/登录/会话同步/重连/好友/群组/文字/图片/文件/语音),均为双账号实测,非版本号代替。
- [x] 任一核心门禁失败则停止后续迁移:本阶段**全部通过**,可进入公司功能迁移(阶段4)。
- [x] 旧版安装包、`mobile/`、PC 客户端、现网服务均未改动。
## 五、已知差异 / 备注
- 登录链路的 HTTP 工号密码校验(account-service `/api/login`)属于公司业务层,本次未接入 mobile-next(禁止公司业务迁移);SDK 登录用与账号服务同源的 userID+imToken 实测通过。部署账号服务管理口令已改(非默认值),本次未触碰服务端任何配置与数据。
- 语音通话(LiveKit)不在本阶段范围(阶段4 迁移),未测。
- hotfix 插件自身 `android/build.gradle` 目标升级到 AGP 8.7.3/compileSdk 35,但被应用工程工具链(AGP 7.3.1/compileSdk 34)覆盖,行为由应用工程决定;已按基线记录。
- 模拟器测试时照片选择器因"受限访问"需在系统设置授予"允许所有照片",为 Android 14+ 权限行为,非 SDK 问题。
## 六、回退方法
本提交只改动 4 个依赖声明文件(`mobile-next/` 内),可单独回退:
```
git revert 2c9dab160eefcaa5a4ad76a24ec2948bffaccc7e
```
或手动把 4 个文件的 `flutter_openim_sdk` 改回 `3.8.3+3``flutter pub get``mobile/``pc-client/``account-service/`、服务器与现网均不受影响。
+56
View File
@@ -0,0 +1,56 @@
# mobile-next 官方固定基线(docs/upstream
## 上游来源与固定版本
| 项 | 值 |
|---|---|
| 上游仓库 | `https://github.com/OpenIMSDK/openim-flutter-demo.git` |
| 固定标签 | `3.8.3-patch.3` |
| 固定提交 | `b3dfdb1e8aaeaaf6f0793e10cadd20d5c184a31f`"Updated IM SDK"2025-03-07 |
| 校验方式 | `git ls-remote --tags` 解析 tag `^{}` 指向即上述提交 |
| 许可证 | OpenIM Open Source LicenseAGPL-3.0 + 附加条款),原文随导入保留在 `mobile-next/LICENSE`;子包 `openim_common/LICENSE``openim_live/LICENSE``local_plugin/flutter_openim_live_alert/LICENSE` |
> 必须固定在该提交,禁止追随上游 `main`。重建基线命令见 `docs/upstream/build-and-rollback.md`。
## 与本卡仓库(tongxunruanjian)的差异
基线在官方原版基础上只做了「必须才能构建/入库」的最小改动,业务代码零改动:
| 文件 | 差异 | 原因 |
|---|---|---|
| `mobile-next/.gitignore` | 追加 `/build/``/android/.gradle/``/android/local.properties` | 上游未忽略 Flutter 构建产物与本机 SDK 路径,避免构建垃圾入库 |
| `mobile-next/pubspec.lock` | `flutter_openim_sdk` 由锁文件 `3.8.3+2` 对齐为 `3.8.3+3``flutter pub get``pubspec.yaml` 声明 `3.8.3+3` 重新解析) | 上游锁文件落后于 pubspec 声明,属官方产物 |
除上述两处外,`mobile-next/` 与上游提交 `b3dfdb1e` 的整棵工作树一致(不含 `.git``.DS_Store``build/``.dart_tool/` 等非跟踪内容)。本卡已用 `git diff --no-index` 与上游归档树复核:零差异(仅上述 2 处)。
## 工具链锁定
| 工具 | 版本 | 位置 |
|---|---|---|
| Flutter | 3.24.5 stablerevision `dec2ee5c1f`engine `a18df97ca5` | `C:\flutter324` |
| Dart | 3.5.4(随 Flutter 3.24.5 分发) | 同上 |
| Java / JDK | Temurin 17.0.20+8 | `toolchain\jdk17` |
| Gradle | 7.6.3`mobile-next/android/gradle/wrapper/gradle-wrapper.properties` 锁定) | 自动下载缓存 |
| Android Gradle Plugin | 7.3.1`mobile-next/android/build.gradle` | - |
| Kotlin | 1.9.23`mobile-next/android/build.gradle` `ext.kotlin_version` | - |
| compileSdk / targetSdk / minSdk | 34 / 33 / 24`mobile-next/android/app/build.gradle` | - |
| build-tools | 36.0.0 | Android SDK |
| 依赖锁文件 | `mobile-next/pubspec.lock` | 已入库 |
### 关键依赖(对照)
| 依赖 | 版本 | 说明 |
|---|---|---|
| `flutter_openim_sdk` | 3.8.3+3(基线自带,仅对照);兼容门禁目标 `3.8.3+hotfix.12`(SDK 接入提交) | 升级差异见 SDK 接入提交与 `docs/acceptance/sdk-compat-gate.md` |
| `livekit_client` | 2.2.5(上游自带,仅对照;正式迁移不采用,保留现有 2.5.0+hotfix.3 | 不随本卡迁移 |
| `flutter_webrtc` / `dart_webrtc` | 0.12.10 / 1.5.2+hotfix.1(上游自带,仅对照) | 不随本卡迁移 |
## 许可证状态与门禁
- 本卡只构建并保留 OpenIM 标识与许可证的官方基线,不做「畅联」换标,不产出/发布试用或生产安装包。
- AGPL-3.0 附加条款(禁止未经授权的商业使用、禁止删除/修改/隐藏 OpenIM LOGO 与版权信息)的内部商用与换标边界,尚未取得书面结论;未确认前不得进入品牌迁移或对外/内部试用发布。
## 回退
- 基线导入提交:`git revert 8046ec7483d68f67011913da12e5e671479b5ff0`(本卡固定基线导入提交),可单独回退,不影响 `mobile/``pc-client/``account-service/` 与现网。
- 或直接删除并行目录:`git rm -r mobile-next`
+61
View File
@@ -0,0 +1,61 @@
# mobile-next 构建与回退方法(docs/upstream
## 前置环境
```bat
set JAVA_HOME=<JDK17 目录>
set ANDROID_HOME=<Android SDK 目录>
set PATH=%JAVA_HOME%\bin;<Flutter SDK 目录>\bin;%PATH%
set GRADLE_OPTS=-Xmx4096M
```
`mobile-next/android/local.properties` 需包含(本机路径,不入库):
```
sdk.dir=<Android SDK 目录,反斜杠转义>
flutter.sdk=<Flutter SDK 目录,反斜杠转义>
```
首次依赖解析(生成 `.dart_tool`,不产生源码改动):
```
cd mobile-next
flutter pub get
```
## 构建命令
```bat
flutter build apk --debug :: 产物 build/app/outputs/flutter-apk/app-debug.apk
flutter build apk --release :: 产物 build/app/outputs/flutter-apk/app-release.apk
```
- release 使用上游自带 keystore `android/app/openim`alias/password 均为 `openim`),保留 OpenIM 标识与签名。
- 注意:上游 `android/app/build.gradle``ndk { abiFilters "arm64-v8a" }` 只打 arm64;如需 x86_64 模拟器联调,临时放开 `"x86_64"` 再还原(本地产物,不入库)。
## 本卡实测结果(2026-08-19,本机锁定环境)
| 构建 | 结果 | 产物 | 大小 | SHA256 |
|---|---|---|---|---|
| debug | 成功 | `app-debug.apk` | 109,454,925 B | `DD7D9700BC1F5830B7495875387948AAD536CA63FDC3EF66B4C0F4D152407B72` |
| release | 成功 | `app-release.apk` | 53,323,411 B | `4969AF4A4800A8E7C0B0C2F50687CB8C765925E4F2B3B7A53762D1D9E49CA604` |
APK 元数据(aapt badging):package `io.openim.flutter.demo`versionCode `180`versionName `3.8.3`minSdk 24 / targetSdk 33 / compileSdk 34。
release 签名(apksigner verify --print-certs):CN=openim,证书 SHA-256 `1f38a82fb3c33be7951fb5d964ef5bd9c6c9bfc084ae1e2a8a40a0d1f44ae1fe`,与官方基线同一 keystore。
构建期告警(不影响产物):Flutter Gradle 插件 apply-script 弃用提示;部分依赖 Kotlin metadata 版本(1.8.x)高于工程 Kotlin1.9.23 预期 1.6.0/1.8.0)的警告,均属上游依赖组合特性,debug/release 均通过。
## 失败停止点
任一核心门禁失败即停止后续迁移,在本卡汇报并附错误证据,不得继续迁移。本阶段 debug/release 均构建成功,无失败步骤。
## 逐提交回退
本卡分支基于回退基线 `fa8584a`,主题提交相互独立,可单独回退:
| 主题 | 提交 | 回退命令 |
|---|---|---|
| 官方基线导入 + 双构建 | 8046ec7483d68f67011913da12e5e671479b5ff0 | `git revert 8046ec7483d68f67011913da12e5e671479b5ff0``git rm -r mobile-next` |
| SDK hotfix.12 接入 + 核心能力实测 | 2c9dab160eefcaa5a4ad76a24ec2948bffaccc7e | `git revert 2c9dab160eefcaa5a4ad76a24ec2948bffaccc7e`(仅 4 个依赖文件) |
回退任一提交均不影响 `mobile/``pc-client/``account-service/`、现网服务器与已发布安装包。SDK hotfix 提交的手动回退:把 `mobile-next/pubspec.yaml``openim_common/pubspec.yaml``openim_live/pubspec.yaml``flutter_openim_sdk` 改回 `3.8.3+3``flutter pub get`
+4
View File
@@ -0,0 +1,4 @@
/.flutter-plugins
/.flutter-plugins-dependencies
/.packages
/.dart_tool/
+88
View File
@@ -0,0 +1,88 @@
# Common Function Configuration Guide
- [Offline push](#offlinepush)
- [Map](#map)
## Offlinepush
Currently using the integrated solution.
### Client configuration
#### 1. Use Getui (https://getui.com/) in mainland China
###### Configure iOS and Android in the integration guide of Getui
**iOS platform configuration:**
According to [its documentation](https://docs.getui.com/getui/mobile/ios/overview/), make the corresponding iOS configuration. Then find the following files in the code and modify the corresponding iOS side key:
- **[push_controller.dart](openim_common/lib/src/controller/push_controller.dart)**
```dart
const appID = 'your-app-id';
const appKey = 'your-app-key';
const appSecret = 'your-app-secret';
```
**Android platform configuration:**
According to [its documentation](https://docs.getui.com/getui/mobile/android/overview/), make corresponding Android configurations, and pay attention to [multi-vendor](https://docs.getui.com/getui/mobile/vendor/vendor_open/) configurations. Then modify the following file contents:
- **[build.gradle](android/app/build.gradle)**
```gradle
manifestPlaceholders = [
GETUI_APPID : "",
XIAOMI_APP_ID : "",
XIAOMI_APP_KEY : "",
MEIZU_APP_ID : "",
MEIZU_APP_KEY : "",
HUAWEI_APP_ID : "",
OPPO_APP_KEY : "",
OPPO_APP_SECRET: "",
VIVO_APP_ID : "",
VIVO_APP_KEY : "",
HONOR_APP_ID : "",
]
```
#### 2. Use [FCM (Firebase Cloud Messaging)](https://firebase.google.com/docs/cloud-messaging) in overseas regions
According to the integration guide of [FCM](https://firebase.google.com/docs/cloud-messaging), replace the following files:
- **[google-services.json](android/app/google-services.json)** (Android platform)
- **[GoogleService-Info.plist](ios/Runner/GoogleService-Info.plist)** (iOS platform)
- **[firebase_options.dart](openim_common/lib/src/controller/firebase_options.dart)** (Firebase configuration in Dart project)
### Offline push banner settings
Currently, the SDK is designed to directly control the display content of the push banner by the client. When sending a message, set the input parameter [offlinePushInfo](https://github.com/openimsdk/openim-flutter-demo/blob/cc72b6d7ca5f70ca07885857beecec512f904f8c/lib/pages/chat/chat_logic.dart#L543):
```dart
final offlinePushInfo = OfflinePushInfo(
title: "Fill in the title",
desc: "Fill in the description, such as the message content",
iOSBadgeCount: true,
);
// If you do not customize offlinePushInfo, the title defaults to the app name, and the desc defaults to "You received a new message"
```
According to actual needs, you can enable the offline push function after completing the corresponding client and server configurations.
---
## Map
### Configuration Guide
Need to configure the corresponding AMap Key. Please refer to [AMap Document](https://lbs.amap.com/) for details. The code in the project needs to modify the following Key:
- **[webKey](https://github.com/openimsdk/openim-flutter-demo/blob/5720a10a31a0a9bc5319775f9f4da83d6996dbfe/openim_common/lib/src/config.dart#L49)**
- **[webServerKey](https://github.com/openimsdk/openim-flutter-demo/blob/5720a10a31a0a9bc5319775f9f4da83d6996dbfe/openim_common/lib/src/config.dart#L50)**
```dart
static const webKey = 'webKey';
static const webServerKey = 'webServerKey';
```
Once the configuration is complete, you can enable the map function.
+88
View File
@@ -0,0 +1,88 @@
# 常见功能配置指南
- [离线推送功能](#离线推送功能)
- [地图功能](#地图功能)
## 离线推送功能
目前使用的是集成方案。
### 客户端配置
#### 1. 中国大陆地区使用个推([Getui](https://getui.com/)
###### 在[Getui](https://getui.com/)的集成指南,配置iOS和Android。
**iOS 平台配置:**
根据[其文档](https://docs.getui.com/getui/mobile/ios/overview/)做好相应的iOS配置。然后在代码中找到以下文件并修改对应的 iOS侧Key:
- **[push_controller.dart](openim_common/lib/src/controller/push_controller.dart)**
```dart
const appID = 'your-app-id';
const appKey = 'your-app-key';
const appSecret = 'your-app-secret';
```
**Android 平台配置:**
根据[其文档](https://docs.getui.com/getui/mobile/android/overview/)做好相应的Android配置,注意[多厂商](https://docs.getui.com/getui/mobile/vendor/vendor_open/)配置。然后修改以下文件内容:
- **[build.gradle](android/app/build.gradle)**
```gradle
manifestPlaceholders = [
GETUI_APPID : "",
XIAOMI_APP_ID : "",
XIAOMI_APP_KEY : "",
MEIZU_APP_ID : "",
MEIZU_APP_KEY : "",
HUAWEI_APP_ID : "",
OPPO_APP_KEY : "",
OPPO_APP_SECRET: "",
VIVO_APP_ID : "",
VIVO_APP_KEY : "",
HONOR_APP_ID : "",
]
```
#### 2. 海外地区使用 [FCMFirebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging)
根据 [FCM](https://firebase.google.com/docs/cloud-messaging) 的集成指南,替换以下文件:
- **[google-services.json](android/app/google-services.json)**Android 平台)
- **[GoogleService-Info.plist](ios/Runner/GoogleService-Info.plist)**iOS 平台)
- **[firebase_options.dart](openim_common/lib/src/controller/firebase_options.dart)**Dart 项目中的 Firebase 配置)
### 离线推送横幅设置
目前SDK的设计是直接由客户端控制推送横幅的展示内容。发送消息时,设置入参[offlinePushInfo](https://github.com/openimsdk/openim-flutter-demo/blob/cc72b6d7ca5f70ca07885857beecec512f904f8c/lib/pages/chat/chat_logic.dart#L543)
```dart
final offlinePushInfo = OfflinePushInfo(
title: "填写标题",
desc: "填写描述信息,例如消息内容",
iOSBadgeCount: true,
);
// 如果不自定义offlinePushInfo,则title默认为app名称,desc默认为为“你收到了一条新消息”
```
根据实际需求,完成对应的客户端和服务端配置后即可启用离线推送功能。
---
## 地图功能
### 配置指南
需要配置对应的 AMap Key。具体请参考 [AMap 文档](https://lbs.amap.com/),工程中的代码需要修改以下 Key:
- **[webKey](https://github.com/openimsdk/openim-flutter-demo/blob/5720a10a31a0a9bc5319775f9f4da83d6996dbfe/openim_common/lib/src/config.dart#L49)**
- **[webServerKey](https://github.com/openimsdk/openim-flutter-demo/blob/5720a10a31a0a9bc5319775f9f4da83d6996dbfe/openim_common/lib/src/config.dart#L50)**
```dart
static const webKey = 'webKey';
static const webServerKey = 'webServerKey';
```
完成配置后即可启用地图功能。
+45
View File
@@ -0,0 +1,45 @@
OpenIM Open Source License
This repository is licensed under the GNU Affero General Public License version 3 (AGPL-3.0) and is subject to the following additional terms:
1. Commercial Use
1.1 Prohibition of Commercial Use
This repository and its contents may not be used for any commercial purposes. If you wish to use OpenIM for commercial purposes, you must obtain a commercial license from the producer.
1.2 Commercial License Application
For commercial licensing, please contact contact@openim.io. Commercial licenses will be tailored to your specific needs and use cases to ensure that you use OpenIM legally and compliantly.
1.3 License After Commercial Authorization
If you have paid the relevant commercial licensing fees to the producer, you may use OpenIM in accordance with the terms of the commercial license without adhering to the provisions of AGPL-3.0. The commercial license grants you the rights to use, modify, and distribute OpenIM under specific conditions detailed in the commercial licensing agreement.
2. LOGO and Copyright Information
2.1 Protection of LOGO and Copyright Information
During the use of this repository, you may not remove, modify, or hide the LOGO or copyright information within the OpenIM console or applications.
2.2 LOGO Definition
All unified text or icons bearing the words OpenIM or OpenIMSDK within the user interfaces of this repository are collectively referred to as the LOGO. This includes, but is not limited to, textual and iconographic identifiers in software interfaces, documentation, and promotional materials.
3. Contributor Agreement
As a contributor, you agree to the following terms:
3.1 Right to Adjust the Agreement
The producer reserves the right to adjust the strictness or leniency of the open-source agreement as necessary to ensure that the agreement aligns with the development and needs of the project.
3.2 Commercial Use of Code
The code you contribute may be used for commercial purposes, including but not limited to cloud business operations. By contributing, you agree that the producer has the right to use your contributions for commercial purposes without additional compensation or authorization.
4. Other Terms
4.1 Compliance with AGPL-3.0
Except for the specific conditions mentioned above, all other rights and restrictions are governed by the GNU Affero General Public License version 3 (AGPL-3.0). For detailed information about the AGPL-3.0 license, please refer to the GNU AGPL-3.0 License.
4.2 Patent Protection
The interactive design of this product is protected by design patents. Any unauthorized copying, modification, or distribution of the interactive design constitutes infringement and will be subject to legal action.
5. Disclaimer
This software is provided "as is," without any form of express or implied warranty, including but not limited to warranties of merchantability, fitness for a particular purpose, or non-infringement. Users assume all risks associated with the use of this software.
6. Contact Information
For any licensing-related questions or to obtain a commercial license, please contact contact@openim.io.
GNU Affero General Public License Version 3 (AGPL-3.0)
© 2024 OpenIMSDK
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
+257
View File
@@ -0,0 +1,257 @@
<p align="center">
<a href="https://openim.io">
<img src="./docs/images/logo.jpg" width="60%" height="30%"/>
</a>
</p>
# OpenIM Flutter 💬💻
<p>
<a href="https://docs.openim.io/">OpenIM Docs</a>
<a href="https://github.com/openimsdk/open-im-server">OpenIM Server</a>
<a href="https://github.com/openimsdk/open-im-sdk-flutter">openim-sdk-flutter</a>
<a href="https://github.com/openimsdk/openim-sdk-core">openim-sdk-core</a>
</p>
OpenIM provides an open-source Instant Messaging (IM) SDK for developers, serving as an alternative solution to cloud services like Twilio and Sendbird. With OpenIM, developers can build secure and reliable IM applications similar to WeChat, Zoom, and Slack.
This repository is based on the open-source version of the OpenIM SDK, offering an Flutter IM application. You can use this application as a reference implementation of the OpenIM SDK.
<p align="center">
<img src="./docs/images/preview1.jpeg" alt="Preview" width="32%"/>
<span style="display: inline-block; width: 16px;"></span>
<img src="./docs/images/preview2.jpeg" alt="Preview" width="32%"/>
</p>
## License :page_facing_up:
This repository is licensed under the GNU Affero General Public License Version 3 (AGPL-3.0) and is subject to additional terms. **Commercial use is prohibited**. For more details, see [here](./LICENSE).
## Development Environment
Before you start development, ensure that the following software is installed on your system:
- **Operating System**: macOS 14.6 or later
- **Flutter**: Version 3.24.5 ([Installation Guide](https://docs.flutter.dev/get-started/install)), XCode: 15.4, Android Studio: Koala | 2024.1.1 Patch 1
- **Git**: For version control
Additionally, make sure you have [deployed](https://docs.openim.io/zh-Hans/guides/gettingStarted/dockerCompose) the latest version of the OpenIM Server. After deployment, you can compile the project and connect it to your server for testing.
## Supported Platforms
This application supports the following platforms:
| Platform | Version | Status |
| ------------- | --------------------- | ------ |
| **iOS** | 13.0 and above | ✅ |
| **Android** | minSdkVersion 24 | ✅ |
### Notes
- **Flutter**: Ensure your version meets the requirements to avoid dependency issues.
## Quick Start
Follow the steps below to set up your local development environment:
1. Clone the repository:
```bash
git clone https://github.com/openimsdk/openim-flutter-demo.git
cd openim-flutter-demo
```
2. Install dependencies
```bash
flutter clean
flutter pub get
```
3. Modify the configuration
> If you have not changed the default server ports, update only the [_host](https://github.com/openimsdk/open-im-flutter-demo/blob/a309f25fdbc143e49d5ca852171ce57970871c85/openim_common/lib/src/config.dart#L59) to your server IP.
```dart
static const _host = "your-server-ip or your-domain";
```
4. Run the application using `flutter run` from the terminal or through your IDE.
5. Start developing and testing! 🎉
## Audio/Video Calls
The open-source version supports one-to-one audio and video calls. You need to first deploy and configure the [server](https://github.com/openimsdk/chat/blob/main/HOW_TO_SETUP_LIVEKIT_SERVER.md). For multi-party audio/video calls or video conferencing, please contact us at [contact@openim.io](mailto:contact@openim.io).
## Build 🚀
> This project allows building separate iOS and Android applications with some differences in the process.
- iOS:
```bash
flutter build ipa
```
- Android:
```bash
flutter build apk
```
1. The build artifacts will be located in the `build` directory.
## Features
### Description
| Feature Module | Feature | Status |
| -------------------------- | -------------------------------------------------------------------------------- | ------ |
| **Account Features** | Phone number registration \ Email registration \ Verification code login | ✅ |
| | View \ Edit personal information | ✅ |
| | Multi-language settings | ✅ |
| | Change password \ Forgot password | ✅ |
| **Friend Features** | Find \ Apply \ Search \ Add \ Delete friends | ✅ |
| | Accept \ Reject friend requests | ✅ |
| | Friend notes | ✅ |
| | Allow friend requests or not | ✅ |
| | Friend list \ Friend data real-time syncing | ✅ |
| **Blocklist** | Restrict messages | ✅ |
| | Real-time syncing of blocklist | ✅ |
| | Add \ Remove from blocklist | ✅ |
| **Group Features** | Create \ Dismiss groups | ✅ |
| | Apply to join \ Invite to join \ Leave group \ Remove members | ✅ |
| | Group name / Avatar changes / Group data updates (notifications, real-time sync) | ✅ |
| | Invite members to group | ✅ |
| | Transfer group ownership | ✅ |
| | Group owner or admin approve join requests | ✅ |
| | Search group members | ✅ |
| **Message Features** | Offline messages | ✅ |
| | Roaming messages | ✅ |
| | Multi-end messages | ✅ |
| | Message history | ✅ |
| | Message deletion | ✅ |
| | Clear messages | ✅ |
| | Copy messages | ✅ |
| | Typing indicator in single chat | ✅ |
| | Do Not Disturb for new messages | ✅ |
| | Clear chat history | ✅ |
| | New members can view group chat history | ✅ |
| | New message reminders | ✅ |
| | Text messages | ✅ |
| | Image messages | ✅ |
| | Video messages | ✅ |
| | Emoji messages | ✅ |
| | File messages | ✅ |
| | Voice messages | ✅ |
| | Contact card messages | ✅ |
| | Location messages | ✅ |
| | Custom messages | ✅ |
| **Conversation** | Pin conversation | ✅ |
| | Mark conversation as read | ✅ |
| | Mute conversation | ✅ |
| **REST API** | Authentication management | ✅ |
| | User management | ✅ |
| | Relationship chain management | ✅ |
| | Group management | ✅ |
| | Conversation management | ✅ |
| | Message management | ✅ |
| **Webhook** | Group callbacks | ✅ |
| | Message callbacks | ✅ |
| | Push callbacks | ✅ |
| | Relationship callbacks | ✅ |
| | User callbacks | ✅ |
| **Capacity & Performance** | 10,000 friends | ✅ |
| | 100,000-member supergroup | ✅ |
| | Second-level syncing | ✅ |
| | Cluster deployment | ✅ |
| | Multi-device kick-out strategy | |
| **Online Status** | No mutual kick-out across all platforms | ✅ |
| | Each platform can only log in with one device | ✅ |
| | PC, Mobile, Pad, Web, Mini Program each can log in with one device | ✅ |
| | PC not mutually kicked, only one device total for other platforms | ✅ |
| **Audio/Video Call** | One-to-one audio and video calls | ✅ |
| **File Storage** | Supports private Minio deployment | ✅ |
| | Supports public cloud services COS, OSS, Kodo, S3 | ✅ |
| **Push** | Real-time online message push | ✅ |
| | Offline message push, supports Getui, Firebase | ✅ |
For more advanced features, audio/video calls, or video conferences, please contact us at [contact@openim.io](mailto:contact@openim.io).
## Join Our Community :busts_in_silhouette:
- 🚀 [Join our Slack community](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q)
- :eyes: [Join our WeChat group](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
## FAQ
##### 1. Does it support multiple languages?
A: Support, follow the system language by default
##### 2. Which platforms are supported?
A: The demo currently supports android and ios.
##### 3. The debug of the android installation package can run, but the release starts with a white screen?
A: The release package of flutter is obfuscated by default. You can use the command: flutter build release --no -shrink. If this command is invalid, you can do the following
Add the following configuration to the release configuration configured in android/app/build.gradle
```
release {
minifyEnabled false
useProguard false
shrinkResources false
}
```
##### 4. What should I do if the code must be confused?
A: Add the following rules to the obfuscation rules
```
-keep class io.openim.**{*;}
-keep class open_im_sdk.**{*;}
-keep class open_im_sdk_callback.**{*;}
```
##### 5. The android installation package cannot be installed on the emulator?
A: Because the Demo has removed some cpu architectures, if you want to run it on the emulator, please do the following:
Add in android/build.gradle configuration
```
ndk {
abiFilters "armeabi-v7a", "x86"
}
```
##### 6, ios run/build release package error
A: Please set the CPU architecture to arm64, and then operate as follows
- flutter clean
- flutter pub get
- cd ios
- rm -f Podfile.lock
- rm -rf Pods
- pod install
- Run Archive after connecting to the real device
![ios cpu](https://user-images.githubusercontent.com/7018230/155913400-6231329a-aee9-4082-8d24-a25baad55261.png)
##### 7. What is the minimum version number for ios to run?
A: 13.0
##### 8. Why is the map not working?
A: [Doc](CONFIGKEY.md)
##### 9. Why is offline push not working?
A: [Doc](CONFIGKEY.md)
+253
View File
@@ -0,0 +1,253 @@
<p align="center">
<a href="https://openim.io">
<img src="./docs/images/logo.jpg" width="60%" height="30%"/>
</a>
</p>
# OpenIM Flutter 💬💻
<p>
<a href="https://docs.openim.io/">OpenIM Docs</a>
<a href="https://github.com/openimsdk/open-im-server">OpenIM Server</a>
<a href="https://github.com/openimsdk/open-im-sdk-flutter">openim-sdk-flutter</a>
<a href="https://github.com/openimsdk/openim-sdk-core">openim-sdk-core</a>
</p>
OpenIM 为开发者提供开源即时通讯 SDK,作为 Twilio、Sendbird 等云服务的替代方案。借助 OpenIM,开发者可以构建安全可靠的即时通讯应用,如 WeChat、Zoom、Slack 等。
本仓库基于开源版 OpenIM SDK 开发,提供了一款基于 Flutter 的即时通讯应用。您可以使用此应用程序作为 OpenIM SDK 的参考实现。
<p align="center">
<img src="./docs/images/preveiw1.zh-CN.jpeg" alt="预览图" width="32%"/>
<span style="display: inline-block; width: 16px;"></span>
<img src="./docs/images/preveiw2.zh-CN.jpeg" alt="预览图" width="32%"/>
</p>
## 授权许可 :page_facing_up:
本仓库采用 GNU Affero 通用公共许可证第 3 版 (AGPL-3.0) 进行许可,并受以下附加条款的约束。**不允许用于商业用途**。详情请参阅 [此处](./LICENSE)。
## 开发环境
在开始开发之前,请确保您的系统已安装以下软件:
- **操作系统**macOS 14.6 或更高版本
- **Flutter**:版本 3.24.5(根据官网步骤进行[安装](https://docs.flutter.cn/get-started/install)XCode: 15.4, Android Studio: Koala | 2024.1.1 Patch 1
- **Git**:用于代码版本控制
同时,您需要确保已经[部署](https://docs.openim.io/zh-Hans/guides/gettingStarted/dockerCompose)了最新版本的 OpenIM Server。接下来,您可以编译项目并连接自己的服务端进行测试。
## 运行环境
本应用支持以下操作系统版本:
| 操作系统 | 版本 | 状态 |
| --------------- | ----------------- | ---- |
| **iOS** | 13.0 及以上 | ✅ |
| **Android** | minSdkVersion 24 | ✅ |
### 说明
- **Flutter**:确保您的版本符合要求,以避免依赖问题。
## 快速开始
按照以下步骤设置本地开发环境:
1. 拉取代码
```bash
git clone https://github.com/openimsdk/openim-flutter-demo.git
cd openim-flutter-demo
```
2. 安装依赖
```bash
flutter clean
flutter pub get
```
3. 修改配置
> 如果没有修改过服务端默认端口,则只需要修改[_host](https://github.com/openimsdk/open-im-flutter-demo/blob/a309f25fdbc143e49d5ca852171ce57970871c85/openim_common/lib/src/config.dart#L59)为您的服务器 ip 即可。
```dart
static const _host = "your-server-ip or your-domain";
```
4. 通过终端执行 `flutter run` 或者IDE的启动菜单来运行iOS/Android应用程序。
5. 开始开发测试! 🎉
## 音视频通话
开源版支持一对一音视频通话,并且需要先部署并配置[服务端](https://github.com/openimsdk/chat/blob/main/HOW_TO_SETUP_LIVEKIT_SERVER.md)。多人音视频通话、视频会议请联系邮箱 [contact@openim.io](mailto:contact@openim.io)
## 构建 🚀
> 该项目允许分别构建 iOS 应用程序和 Android 应用程序,但在构建过程中会有一些差异。
- iOS:
```bash
flutter build ipa
```
- Android:
```bash
flutter build apk
```
构建结果将位于 `build` 目录下。
## 功能列表
### 说明
| 功能模块 | 功能项 | 状态 |
| ------------------ | --------------------------------------------------------- | ---- |
| **账号功能** | 手机号注册\邮箱注册\验证码登录 | ✅ |
| | 个人信息查看\修改 | ✅ |
| | 多语言设置 | ✅ |
| | 修改密码\忘记密码 | ✅ |
| **好友功能** | 查找\申请\搜索\添加\删除好友 | ✅ |
| | 同意\拒绝好友申请 | ✅ |
| | 好友备注 | ✅ |
| | 是否允许添加好友 | ✅ |
| | 好友列表\好友资料实时同步 | ✅ |
| **黑名单功能** | 限制消息 | ✅ |
| | 黑名单列表实时同步 | ✅ |
| | 添加\移出黑名单 | ✅ |
| **群组功能** | 创建\解散群组 | ✅ |
| | 申请加群\邀请加群\退出群组\移除群成员 | ✅ |
| | 群名/群头像更改/群资料变更通知和实时同步 | ✅ |
| | 群成员邀请进群 | ✅ |
| | 群主转让 | ✅ |
| | 群主、管理员同意进群申请 | ✅ |
| | 搜索群成员 | ✅ |
| **消息功能** | 离线消息 | ✅ |
| | 漫游消息 | ✅ |
| | 多端消息 | ✅ |
| | 历史消息 | ✅ |
| | 消息删除 | ✅ |
| | 消息清空 | ✅ |
| | 消息复制 | ✅ |
| | 单聊正在输入 | ✅ |
| | 新消息勿扰 | ✅ |
| | 清空聊天记录 | ✅ |
| | 新成员查看群聊历史消息 | ✅ |
| | 新消息提示 | ✅ |
| | 文本消息 | ✅ |
| | 图片消息 | ✅ |
| | 视频消息 | ✅ |
| | 表情消息 | ✅ |
| | 文件消息 | ✅ |
| | 语音消息 | ✅ |
| | 名片消息 | ✅ |
| | 地理位置消息 | ✅ |
| | 自定义消息 | ✅ |
| **会话功能** | 置顶会话 | ✅ |
| | 会话已读 | ✅ |
| | 会话免打扰 | ✅ |
| **REST API** | 认证管理 | ✅ |
| | 用户管理 | ✅ |
| | 关系链管理 | ✅ |
| | 群组管理 | ✅ |
| | 会话管理 | ✅ |
| | 消息管理 | ✅ |
| **Webhook** | 群组回调 | ✅ |
| | 消息回调 | ✅ |
| | 推送回调 | ✅ |
| | 关系链回调 | ✅ |
| | 用户回调 | ✅ |
| **容量和性能** | 1 万好友 | ✅ |
| | 10 万人大群 | ✅ |
| | 秒级同步 | ✅ |
| | 集群部署 | ✅ |
| | 互踢策略 | |
| **在线状态** | 所有平台不互踢 | ✅ |
| | 每个平台各只能登录一个设备 | ✅ |
| | PC 端、移动端、Pad 端、Web 端、小程序端各只能登录一个设备 | ✅ |
| | PC 端不互踢,其他平台总计一个设备 | ✅ |
| **音视频通话** | 一对一音视频通话 | ✅ |
| **文件类对象存储** | 支持私有化部署 minio | ✅ |
| | 支持 COS、OSS、Kodo、S3 公有云 | ✅ |
| **推送** | 消息在线实时推送 | ✅ |
| | 消息离线推送,支持个推,Firebase | ✅ |
更多高级功能、音视频通话、视频会议 请联系邮箱 [contact@openim.io](mailto:contact@openim.io)
## 加入社区 :busts_in_silhouette:
- 🚀 [加入我们的 Slack 社区](https://join.slack.com/t/openimsdk/shared_invite/zt-22720d66b-o_FvKxMTGXtcnnnHiMqe9Q)
- :eyes: [加入我们的微信群](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
## 常见问题
##### 1. 是否支持多语言?
答:支持,默认跟随系统语言。
##### 2. 支持哪些平台?
答:目前 Demo 支持 Android 和 iOS。
##### 3. Android 安装包的 debug 版本可以运行,但 release 启动是白屏?
答:Flutter 的 release 包默认会进行混淆,可以使用以下命令:
```bash
flutter build release --no-shrink
```
如果此命令无效,可以在 android/app/build.gradle 文件的 release 配置中添加以下代码:
```bash
release {
minifyEnabled false
useProguard false
shrinkResources false
}
```
##### 4. 如果代码必须混淆该怎么办?
答:在混淆规则中添加以下配置:
```bash
-keep class io.openim.**{*;}
-keep class open_im_sdk.**{*;}
-keep class open_im_sdk_callback.**{*;}
```
##### 5. Android 安装包无法安装在模拟器上?
答:由于 Demo 移除了一些 CPU 架构,如果需要在模拟器上运行,请在 android/build.gradle 配置中添加以下内容:
```bash
ndk {
abiFilters "armeabi-v7a", "x86"
}
```
##### 6. iOS 运行/打包 release 包时报错?
答:请将 CPU 架构设置为 arm64,然后按以下步骤操作:
```bash
执行 flutter clean
执行 flutter pub get
cd ios/
rm -f Podfile.lock
rm -rf Pods
执行 pod install
连接真机后运行 Archive。
```
![ios cpu](https://user-images.githubusercontent.com/7018230/155913400-6231329a-aee9-4082-8d24-a25baad55261.png)
##### 7. iOS 最低运行版本是多少?
答:13.0
##### 8. 地图为什么不能使用?
答: [文档](CONFIGKEY.zh-CN.md)
##### 9. 离线推送为什么不能使用?
答: [文档](CONFIGKEY.zh-CN.md)
+29
View File
@@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+13
View File
@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
+188
View File
@@ -0,0 +1,188 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
subprojects { afterEvaluate { android { compileSdkVersion 34 } } }
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.huawei.agconnect'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 34
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.openim.flutter.demo"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 24
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
ndk {
abiFilters "arm64-v8a"//, "armeabi-v7a", "armeabi", "x86", "x86_64", "mips", "mips64"
}
lintOptions {
disable 'InvalidPackage'
disable "Instantiatable"
checkReleaseBuilds false
abortOnError false
}
manifestPlaceholders = [
GETUI_APPID : "",
XIAOMI_APP_ID : "",
XIAOMI_APP_KEY : "",
MEIZU_APP_ID : "",
MEIZU_APP_KEY : "",
HUAWEI_APP_ID : "",
OPPO_APP_KEY : "",
OPPO_APP_SECRET: "",
VIVO_APP_ID : "",
VIVO_APP_KEY : "",
HONOR_APP_ID : "",
]
}
signingConfigs {
release {
keyAlias 'openim'
keyPassword 'openim'
storeFile file('./openim')
storePassword 'openim'
}
}
buildTypes {
debug {
signingConfig signingConfigs.release
}
profile {
signingConfig signingConfigs.release
}
release {
// minifyEnabled false
// useProguard false
// shrinkResources false
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
android.applicationVariants.all {
variant ->
variant.outputs.all {
outputFileName = "F-DEMO_${versionName}(${versionCode})_${buildType.name}_${buildTime()}.apk"
}
}
packagingOptions {
// other options here
/* Fix for ffmpeg-kit-react-native START */
pickFirst 'lib/arm64-v8a/libgojni.so'
pickFirst 'lib/armeabi-v7a/libgojni.so'
pickFirst 'lib/x86/libgojni.so'
pickFirst 'lib/x86_64/libgojni.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libavcodec.so'
pickFirst 'lib/arm64-v8a/libavformat.so'
pickFirst 'lib/arm64-v8a/libavutil.so'
pickFirst 'lib/arm64-v8a/libswscale.so'
pickFirst 'lib/arm64-v8a/libavdevice.so'
pickFirst 'lib/arm64-v8a/libavfilter.so'
pickFirst 'lib/arm64-v8a/libffmpegkit.so'
pickFirst 'lib/arm64-v8a/libffmpegkit_abidetect.so'
pickFirst 'lib/arm64-v8a/libswresample.so'
pickFirst 'lib/arm64-v8a/libswscale.so'
pickFirst 'lib/x86/libavcodec.so'
pickFirst 'lib/x86/libavformat.so'
pickFirst 'lib/x86/libavutil.so'
pickFirst 'lib/x86/libswscale.so'
pickFirst 'lib/x86/libavdevice.so'
pickFirst 'lib/x86/libavfilter.so'
pickFirst 'lib/x86/libffmpegkit.so'
pickFirst 'lib/x86/libffmpegkit_abidetect.so'
pickFirst 'lib/x86/libswresample.so'
pickFirst 'lib/x86/libswscale.so'
pickFirst 'lib/x86_64/libavcodec.so'
pickFirst 'lib/x86_64/libavformat.so'
pickFirst 'lib/x86_64/libavutil.so'
pickFirst 'lib/x86_64/libswscale.so'
pickFirst 'lib/x86_64/libavdevice.so'
pickFirst 'lib/x86_64/libavfilter.so'
pickFirst 'lib/x86_64/libffmpegkit.so'
pickFirst 'lib/x86_64/libffmpegkit_abidetect.so'
pickFirst 'lib/x86_64/libswresample.so'
pickFirst 'lib/x86_64/libswscale.so'
/* Fix for ffmpeg-kit-react-native END */
}
}
flutter {
source '../..'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'com.getui:gtsdk:3.3.9.0'
implementation 'com.getui:gtc:3.2.18.0'
implementation 'com.huawei.hms:push:6.12.0.300'
implementation 'com.huawei.agconnect:agconnect-core:1.5.2.300'
implementation 'com.getui.opt:hwp:3.1.0'
implementation 'com.getui.opt:xmp:3.2.0'
implementation('com.assist-v3:oppo:3.1.0') {
exclude group: 'commons-codec'
}
implementation 'com.assist-v3:vivo:3.1.0'
implementation 'com.getui.opt:mzp:3.2.0'
implementation 'com.getui.opt:ups:3.0.3'
implementation 'com.getui.opt:honor:3.2.0'
implementation 'androidx.multidex:multidex:2.0.1'
implementation platform("com.google.firebase:firebase-bom:33.7.0")
implementation "com.google.firebase:firebase-messaging" // FCM
}
static def buildTime() {
return new Date().format("MMddHHmm", TimeZone.getTimeZone("GMT+08:00"))
}
@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "299075855003",
"project_id": "im-fer-c3347",
"storage_bucket": "im-fer-c3347.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:299075855003:android:292449dc34ad498109dc3e",
"android_client_info": {
"package_name": "io.openim.flutter.demo"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyCw-ohvxFisvm3Yrb4kCzPBuL0YfZkzI9Q"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
Binary file not shown.
+206
View File
@@ -0,0 +1,206 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\COMPETITION\Android Studio\Android Studio SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
#指定代码的压缩级别
-optimizationpasses 5
#包明不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
#优化 不优化输入的类文件
-dontoptimize
#预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保护注解
-keepattributes *Annotation*
# 保持哪些类不被混淆
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep public class * extends android.support.multidex.MultiDexApplication
-keep public class * extends android.view.View
-keep class android.support.** {*;}
#忽略警告
-ignorewarnings
##记录生成的日志数据,gradle build时在本项目根目录输出##
#apk 包内所有 class 的内部结构
-dump proguard/class_files.txt
#未混淆的类和成员
-printseeds proguard/seeds.txt
#列出从 apk 中删除的代码
-printusage proguard/unused.txt
#混淆前后的映射
-printmapping proguard/mapping.txt
########记录生成的日志数据,gradle build时 在本项目根目录输出-end######
#如果引用了v4或者v7包
-dontwarn android.support.**
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
#保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
public void *(android.view.View);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable
#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保持枚举 enum 类不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * {
public void *ButtonClicked(android.view.View);
}
#不混淆资源类
-keepclassmembers class **.R$* {
public static <fields>;
}
#泛型与反射
-keepattributes Signature
-keepattributes EnclosingMethod
-keepattributes *Annotation*
-dontoptimize
-dontpreverify
#############################################################################################
######################## 以上通用 ##################################
#############################################################################################
#------------------ 下方是共性的排除项目 ----------------
# 方法名中含有“JNI”字符的,认定是Java Native Interface方法,自动排除
# 方法名中含有“JRI”字符的,认定是Java Reflection Interface方法,自动排除
-keepclasseswithmembers class * {
... *JNI*(...);
}
-keepclasseswithmembernames class * {
... *JRI*(...);
}
-keep class **JNI* {*;}
# Keep native methods
-keepclassmembers class * {
native <methods>;
}
# UCrop
-dontwarn com.yalantis.ucrop**
-keep class com.yalantis.ucrop** { *; }
-keep interface com.yalantis.ucrop** { *; }
# zxing
-keep class com.google.zxing.** {*;}
-dontwarn com.google.zxing.**
-keep public class **.R$*{
public static final int *;
}
# jpush
-dontoptimize
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.service.JPushMessageReceiver { *; }
-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
#腾讯 Bugly
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
# OpenIM
-keep class io.openim.**{*;}
-keep class open_im_sdk.**{*;}
-keep class open_im_sdk_callback.**{*;}
#getui
-dontwarn com.igexin.**
-keep class com.igexin.** { *; }
@@ -0,0 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.rentsoft.flutter.openim.business">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -0,0 +1,160 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="cn.rentsoft.flutter.openim.business">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!--From Android 12-->
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"/>
<!-- Provide required visibility configuration for API level 30 and above -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application
android:icon="@mipmap/ic_launcher"
android:label="F-DEMO"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
tools:replace="android:label">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:exported="false"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<!-- If you want your foreground service to be stopped if
your app is stopped, set android:stopWithTask to true.
See https://developer.android.com/reference/android/R.attr#stopWithTask -->
<service
android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
android:exported="false"
android:stopWithTask="false" />
<service
android:name="io.openim.live.alert.flutter_openim_live_alert.services.CallService"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
<!-- <provider android:name="com.pichillilorenzo.flutter_inappwebview_android.InAppWebViewFileProvider"
android:authorities="${applicationId}.flutter_inappwebview_android.fileprovider"
android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider> -->
<service android:name="de.julianassmann.flutter_background.IsolateHolderService"
android:foregroundServiceType="mediaProjection"
tools:targetApi="q"
android:enabled="true"
android:exported="false"/>
</application>
</manifest>
@@ -0,0 +1,6 @@
package cn.rentsoft.flutter.openim.business;
import io.flutter.embedding.android.FlutterFragmentActivity;
public class MainActivity extends FlutterFragmentActivity {
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- "/" -->
<!--<root-path
name="rootPath"
path="." />-->
<!--Context.getFilesDir().-->
<files-path
name="filesPath"
path="." />
<!-- getCacheDir().-->
<cache-path
name="cachePath"
path="." />
<!-- Environment.getExternalStorageDirectory().-->
<!-- <external-path
name="externalPath"
path="." />-->
<!--Context#getExternalFilesDir(String) Context.getExternalFilesDir(null). -->
<external-files-path
name="externalFilesPath"
path="." />
<!-- Context.getExternalCacheDir(). -->
<external-cache-path
name="externalCachePath"
path="." />
</paths>
@@ -0,0 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.rentsoft.flutter.openim.business">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
+64
View File
@@ -0,0 +1,64 @@
buildscript {
ext.kotlin_version = '1.9.23'
repositories {
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/gradle-plugin' }
maven { url "https://mvn.gt.getui.com/nexus/content/repositories/releases/" }
maven { url 'https://developer.huawei.com/repo/' } // hms
maven { url "https://dl.google.com/dl/android/maven2/" } // fcm
maven {
url 'https://maven.columbus.heytapmobi.com/repository/releases/'
credentials {
username 'nexus'
password 'c0b08da17e3ec36c3870fed674a0bcb36abc2e23'
}
}
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools:r8:8.3.37")
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.4.2' // fcm
classpath 'com.huawei.agconnect:agcp:1.6.0.300' // hms
}
}
allprojects {
repositories {
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/gradle-plugin' }
maven { url "https://mvn.gt.getui.com/nexus/content/repositories/releases/" }
maven { url 'https://developer.huawei.com/repo/' } // hms
maven { url "https://dl.google.com/dl/android/maven2/" } // fcm
maven {
url 'https://maven.columbus.heytapmobi.com/repository/releases/'
credentials {
username 'nexus'
password 'c0b08da17e3ec36c3870fed674a0bcb36abc2e23'
}
}
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects { afterEvaluate { android { compileSdkVersion 34 } } }
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
+3
View File
@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
+11
View File
@@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
+52
View File
@@ -0,0 +1,52 @@
{
errCode: 0,
errMsg: "",
data: {
userFullInfoList: [
{
userID: "2380124277",
password: "",
account: "11002",
phoneNumber: "",
areaCode: "",
nickname: "林玟书",
englishName: "",
faceURL: "",
gender: 1,
mobileAreaCode: "+86",
mobile: "",
telephone: "",
level: 1,
birth: 288316800000,
email: "",
order: 0,
status: 0,
allowAddFriend: 1,
allowBeep: 1,
allowVibration: 1,
forbidden: 0,
station: "",
departmentList: [
{
departmentID: "936609157",
departmentFaceURL: "",
departmentName: "前端",
departmentParentID: "1852915335",
departmentOrder: 0,
departmentDepartmentType: 0,
departmentRelatedGroupID: "",
departmentCreateTime: 1678095053014,
memberOrder: 0,
memberPosition: "IOS",
memberLeader: 0,
memberStatus: 0,
memberEntryTime: 0,
memberTerminationTime: 0,
memberCreateTime: 1678095467228
}
]
}
],
totalNumber: 1
}
}
+3
View File
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
Binary file not shown.

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

+1
View File
@@ -0,0 +1 @@
{"flutter":{"platforms":{"android":{"default":{"projectId":"im-fer-c3347","appId":"1:299075855003:android:292449dc34ad498109dc3e","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"im-fer-c3347","appId":"1:299075855003:ios:23b06300e33d984309dc3e","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"im-fer-c3347","configurations":{"android":"1:299075855003:android:292449dc34ad498109dc3e","ios":"1:299075855003:ios:23b06300e33d984309dc3e"}}}}}}
+13
View File
@@ -0,0 +1,13 @@
flutter_icons:
android: true
ios: true
remove_alpha_ios: true
image_path: "launcher_icon/app-icon.png"
# flutter pub get
# flutter pub run flutter_launcher_icons:main -f <your config file name here>
# flutter pub get
# flutter pub run flutter_launcher_icons:main
+138
View File
@@ -0,0 +1,138 @@
flutter_native_splash:
# This package generates native code to customize Flutter's default white native splash screen
# with background color and splash image.
# Customize the parameters below, and run the following command in the terminal:
# flutter pub run flutter_native_splash:create
# To restore Flutter's default white splash screen, run the following command in the terminal:
# flutter pub run flutter_native_splash:remove
# color or background_image is the only required parameter. Use color to set the background
# of your splash screen to a solid color. Use background_image to set the background of your
# splash screen to a png image. This is useful for gradients. The image will be stretch to the
# size of the app. Only one parameter can be used, color and background_image cannot both be set.
color: "#42a5f5"
#background_image: "assets/background.png"
# Optional parameters are listed below. To enable a parameter, uncomment the line by removing
# the leading # character.
# The image parameter allows you to specify an image used in the splash screen. It must be a
# png file and should be sized for 4x pixel density.
#image: assets/splash.png
# The branding property allows you to specify an image used as branding in the splash screen.
# It must be a png file. It is supported for Android, iOS and the Web. For Android 12,
# see the Android 12 section below.
#branding: assets/dart.png
# To position the branding image at the bottom of the screen you can use bottom, bottomRight,
# and bottomLeft. The default values is bottom if not specified or specified something else.
#branding_mode: bottom
# The color_dark, background_image_dark, image_dark, branding_dark are parameters that set the background
# and image when the device is in dark mode. If they are not specified, the app will use the
# parameters from above. If the image_dark parameter is specified, color_dark or
# background_image_dark must be specified. color_dark and background_image_dark cannot both be
# set.
#color_dark: "#042a49"
#background_image_dark: "assets/dark-background.png"
#image_dark: assets/splash-invert.png
#branding_dark: assets/dart_dark.png
# Android 12 handles the splash screen differently than previous versions. Please visit
# https://developer.android.com/guide/topics/ui/splash-screen
# Following are Android 12 specific parameter.
android_12:
# The image parameter sets the splash screen icon image. If this parameter is not specified,
# the app's launcher icon will be used instead.
# Please note that the splash screen will be clipped to a circle on the center of the screen.
# App icon with an icon background: This should be 960×960 pixels, and fit within a circle
# 640 pixels in diameter.
# App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle
# 768 pixels in diameter.
#image: assets/android12splash.png
# Splash screen background color.
#color: "#42a5f5"
# App icon background color.
#icon_background_color: "#111111"
# The branding property allows you to specify an image used as branding in the splash screen.
#branding: assets/dart.png
# The image_dark, color_dark, icon_background_color_dark, and branding_dark set values that
# apply when the device is in dark mode. If they are not specified, the app will use the
# parameters from above.
#image_dark: assets/android12splash-invert.png
#color_dark: "#042a49"
#icon_background_color_dark: "#eeeeee"
# The android, ios and web parameters can be used to disable generating a splash screen on a given
# platform.
#android: false
#ios: false
#web: false
# Platform specific images can be specified with the following parameters, which will override
# the respective parameter. You may specify all, selected, or none of these parameters:
#color_android: "#42a5f5"
#color_dark_android: "#042a49"
#color_ios: "#42a5f5"
#color_dark_ios: "#042a49"
#color_web: "#42a5f5"
#color_dark_web: "#042a49"
#image_android: assets/splash-android.png
#image_dark_android: assets/splash-invert-android.png
#image_ios: assets/splash-ios.png
#image_dark_ios: assets/splash-invert-ios.png
#image_web: assets/splash-web.png
#image_dark_web: assets/splash-invert-web.png
#background_image_android: "assets/background-android.png"
#background_image_dark_android: "assets/dark-background-android.png"
#background_image_ios: "assets/background-ios.png"
#background_image_dark_ios: "assets/dark-background-ios.png"
#background_image_web: "assets/background-web.png"
#background_image_dark_web: "assets/dark-background-web.png"
#branding_android: assets/brand-android.png
#branding_dark_android: assets/dart_dark-android.png
#branding_ios: assets/brand-ios.png
#branding_dark_ios: assets/dart_dark-ios.png
# The position of the splash image can be set with android_gravity, ios_content_mode, and
# web_image_mode parameters. All default to center.
#
# android_gravity can be one of the following Android Gravity (see
# https://developer.android.com/reference/android/view/Gravity): bottom, center,
# center_horizontal, center_vertical, clip_horizontal, clip_vertical, end, fill, fill_horizontal,
# fill_vertical, left, right, start, or top.
#android_gravity: center
#
# ios_content_mode can be one of the following iOS UIView.ContentMode (see
# https://developer.apple.com/documentation/uikit/uiview/contentmode): scaleToFill,
# scaleAspectFit, scaleAspectFill, center, top, bottom, left, right, topLeft, topRight,
# bottomLeft, or bottomRight.
#ios_content_mode: center
#
# web_image_mode can be one of the following modes: center, contain, stretch, and cover.
#web_image_mode: center
# The screen orientation can be set in Android with the android_screen_orientation parameter.
# Valid parameters can be found here:
# https://developer.android.com/guide/topics/manifest/activity-element#screen
#android_screen_orientation: sensorLandscape
# To hide the notification bar, use the fullscreen parameter. Has no effect in web since web
# has no notification bar. Defaults to false.
# NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads.
# To show the notification bar, add the following code to your Flutter app:
# WidgetsFlutterBinding.ensureInitialized();
# SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]);
#fullscreen: true
# If you have changed the name(s) of your info.plist file(s), you can specify the filename(s)
# with the info_plist_files parameter. Remove only the # characters in the three lines below,
# do not remove any spaces:
#info_plist_files:
# - 'ios/Runner/Info-Debug.plist'
# - 'ios/Runner/Info-Release.plist'
BIN
View File
Binary file not shown.
+34
View File
@@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>
+2
View File
@@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
+2
View File
@@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
</dict>
</plist>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.cn.rentsoft.openim.flutter.rtc</string>
</array>
</dict>
</plist>
@@ -0,0 +1,33 @@
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
if let userInfo = request.content.userInfo as? [String: Any],
let clientID = userInfo["clientMsgID"] as? String,
!clientID.isEmpty == true
{
let key = "key"
UserDefaults.standard.set(request.identifier, forKey: key)
bestAttemptContent.title = "\(bestAttemptContent.title)"
bestAttemptContent.sound = UNNotificationSound(named: .init(rawValue: "call.caf"))
}
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
+99
View File
@@ -0,0 +1,99 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
# Start of the permission_handler configuration
target.build_configurations.each do |config|
# You can enable the permissions needed here. For example to enable camera
# permission, just remove the `#` character in front so it looks like this:
#
# ## dart: PermissionGroup.camera
# 'PERMISSION_CAMERA=1'
#
# Preprocessor definitions can be found in: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
## dart: PermissionGroup.calendar
# 'PERMISSION_EVENTS=1',
## dart: PermissionGroup.reminders
# 'PERMISSION_REMINDERS=1',
## dart: PermissionGroup.contacts
# 'PERMISSION_CONTACTS=1',
## dart: PermissionGroup.camera
'PERMISSION_CAMERA=1',
## dart: PermissionGroup.microphone
'PERMISSION_MICROPHONE=1',
## dart: PermissionGroup.speech
# 'PERMISSION_SPEECH_RECOGNIZER=1',
## dart: PermissionGroup.photos
'PERMISSION_PHOTOS=1',
## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
'PERMISSION_LOCATION=1',
## dart: PermissionGroup.notification
'PERMISSION_NOTIFICATIONS=1',
## dart: PermissionGroup.mediaLibrary
# 'PERMISSION_MEDIA_LIBRARY=1',
## dart: PermissionGroup.sensors
# 'PERMISSION_SENSORS=1',
## dart: PermissionGroup.bluetooth
# 'PERMISSION_BLUETOOTH=1',
## dart: PermissionGroup.appTrackingTransparency
# 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',
## dart: PermissionGroup.criticalAlerts
# 'PERMISSION_CRITICAL_ALERTS=1'
]
end
end
end
+505
View File
@@ -0,0 +1,505 @@
PODS:
- audio_session (0.0.1):
- Flutter
- camera_avfoundation (0.0.1):
- Flutter
- connectivity_plus (0.0.1):
- Flutter
- FlutterMacOS
- device_info_plus (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
- DKImagePickerController/ImageDataManager (4.3.9)
- DKImagePickerController/PhotoGallery (4.3.9):
- DKImagePickerController/Core
- DKPhotoGallery
- DKImagePickerController/Resource (4.3.9)
- DKPhotoGallery (0.0.19):
- DKPhotoGallery/Core (= 0.0.19)
- DKPhotoGallery/Model (= 0.0.19)
- DKPhotoGallery/Preview (= 0.0.19)
- DKPhotoGallery/Resource (= 0.0.19)
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Core (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Preview
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Model (0.0.19):
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Preview (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Resource
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- emoji_picker_flutter (0.0.1):
- Flutter
- ffmpeg-kit-ios-full-gpl (6.0)
- ffmpeg_kit_flutter_full_gpl (6.0.3):
- ffmpeg_kit_flutter_full_gpl/full-gpl (= 6.0.3)
- Flutter
- ffmpeg_kit_flutter_full_gpl/full-gpl (6.0.3):
- ffmpeg-kit-ios-full-gpl (= 6.0)
- Flutter
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- Firebase/CoreOnly (11.6.0):
- FirebaseCore (~> 11.6.0)
- Firebase/Messaging (11.6.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 11.6.0)
- firebase_core (3.10.0):
- Firebase/CoreOnly (= 11.6.0)
- Flutter
- firebase_messaging (15.2.0):
- Firebase/Messaging (= 11.6.0)
- firebase_core
- Flutter
- FirebaseCore (11.6.0):
- FirebaseCoreInternal (~> 11.6.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Logger (~> 8.0)
- FirebaseCoreInternal (11.6.0):
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- FirebaseInstallations (11.6.0):
- FirebaseCore (~> 11.6.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- FirebaseMessaging (11.6.0):
- FirebaseCore (~> 11.6.0)
- FirebaseInstallations (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Reachability (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- nanopb (~> 3.30910.0)
- Flutter (1.0.0)
- flutter_image_compress_common (1.0.0):
- Flutter
- Mantle
- SDWebImage
- SDWebImageWebPCoder
- flutter_keyboard_visibility (0.0.1):
- Flutter
- flutter_local_notifications (0.0.1):
- Flutter
- flutter_native_splash (2.4.3):
- Flutter
- flutter_new_badger (0.0.1):
- Flutter
- flutter_openim_sdk (0.0.1):
- Flutter
- OpenIMSDKCore (= 3.8.3)
- flutter_webrtc (0.11.3):
- Flutter
- WebRTC-SDK (= 125.6422.04)
- geolocator_apple (1.2.0):
- Flutter
- getuiflut (0.0.1):
- Flutter
- GTSDK
- GoogleDataTransport (10.1.0):
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- GoogleUtilities/AppDelegateSwizzler (8.0.2):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (8.0.2):
- GoogleUtilities/Privacy
- GoogleUtilities/Logger (8.0.2):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/Network (8.0.2):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (8.0.2)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (8.0.2)
- GoogleUtilities/Reachability (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GTCommonSDK (3.1.7.0):
- ZXSDK
- GTSDK (3.0.9.0):
- GTCommonSDK (> 3.0.9.0)
- image_cropper (0.0.4):
- Flutter
- TOCropViewController (~> 2.6.1)
- image_gallery_saver_plus (0.0.1):
- Flutter
- image_picker_ios (0.0.1):
- Flutter
- just_audio (0.0.1):
- Flutter
- libwebp (1.3.2):
- libwebp/demux (= 1.3.2)
- libwebp/mux (= 1.3.2)
- libwebp/sharpyuv (= 1.3.2)
- libwebp/webp (= 1.3.2)
- libwebp/demux (1.3.2):
- libwebp/webp
- libwebp/mux (1.3.2):
- libwebp/demux
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv
- livekit_client (2.2.5):
- Flutter
- WebRTC-SDK (= 125.6422.04)
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
- Mantle (2.2.0):
- Mantle/extobjc (= 2.2.0)
- Mantle/extobjc (2.2.0)
- map_launcher (0.0.1):
- Flutter
- media_kit_libs_ios_video (1.0.4):
- Flutter
- media_kit_native_event_loop (1.0.0):
- Flutter
- media_kit_video (0.0.1):
- Flutter
- MTBBarcodeScanner (5.0.11)
- Mute (0.6.1)
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
- nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0)
- open_filex (0.0.2):
- Flutter
- OpenIMSDKCore (3.8.3)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- photo_manager (2.0.0):
- Flutter
- FlutterMacOS
- PromisesObjC (2.4.0)
- qr_code_scanner_plus (0.2.6):
- Flutter
- MTBBarcodeScanner
- record_darwin (1.0.0):
- Flutter
- scan (0.0.1):
- Flutter
- screen_brightness_ios (0.1.0):
- Flutter
- SDWebImage (5.20.0):
- SDWebImage/Core (= 5.20.0)
- SDWebImage/Core (5.20.0)
- SDWebImageWebPCoder (0.14.6):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.17)
- sensors_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sound_mode (0.0.1):
- Flutter
- Mute (~> 0.6.0)
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.5)
- TOCropViewController (2.6.1)
- url_launcher_ios (0.0.1):
- Flutter
- vibration (1.7.5):
- Flutter
- video_compress (0.3.0):
- Flutter
- video_player_avfoundation (0.0.1):
- Flutter
- FlutterMacOS
- volume_controller (0.0.1):
- Flutter
- wakelock_plus (0.0.1):
- Flutter
- WebRTC-SDK (125.6422.04)
- webview_flutter_wkwebview (0.0.1):
- Flutter
- FlutterMacOS
- ZXSDK (3.3.2)
DEPENDENCIES:
- audio_session (from `.symlinks/plugins/audio_session/ios`)
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- emoji_picker_flutter (from `.symlinks/plugins/emoji_picker_flutter/ios`)
- ffmpeg_kit_flutter_full_gpl (from `.symlinks/plugins/ffmpeg_kit_flutter_full_gpl/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
- flutter_image_compress_common (from `.symlinks/plugins/flutter_image_compress_common/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_new_badger (from `.symlinks/plugins/flutter_new_badger/ios`)
- flutter_openim_sdk (from `.symlinks/plugins/flutter_openim_sdk/ios`)
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`)
- getuiflut (from `.symlinks/plugins/getuiflut/ios`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
- image_gallery_saver_plus (from `.symlinks/plugins/image_gallery_saver_plus/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- just_audio (from `.symlinks/plugins/just_audio/ios`)
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
- map_launcher (from `.symlinks/plugins/map_launcher/ios`)
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
- media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
- open_filex (from `.symlinks/plugins/open_filex/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
- qr_code_scanner_plus (from `.symlinks/plugins/qr_code_scanner_plus/ios`)
- record_darwin (from `.symlinks/plugins/record_darwin/ios`)
- scan (from `.symlinks/plugins/scan/ios`)
- screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
- sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sound_mode (from `.symlinks/plugins/sound_mode/ios`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- vibration (from `.symlinks/plugins/vibration/ios`)
- video_compress (from `.symlinks/plugins/video_compress/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- ffmpeg-kit-ios-full-gpl
- Firebase
- FirebaseCore
- FirebaseCoreInternal
- FirebaseInstallations
- FirebaseMessaging
- GoogleDataTransport
- GoogleUtilities
- GTCommonSDK
- GTSDK
- libwebp
- Mantle
- MTBBarcodeScanner
- Mute
- nanopb
- OpenIMSDKCore
- PromisesObjC
- SDWebImage
- SDWebImageWebPCoder
- SwiftyGif
- TOCropViewController
- WebRTC-SDK
- ZXSDK
EXTERNAL SOURCES:
audio_session:
:path: ".symlinks/plugins/audio_session/ios"
camera_avfoundation:
:path: ".symlinks/plugins/camera_avfoundation/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/darwin"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
emoji_picker_flutter:
:path: ".symlinks/plugins/emoji_picker_flutter/ios"
ffmpeg_kit_flutter_full_gpl:
:path: ".symlinks/plugins/ffmpeg_kit_flutter_full_gpl/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
firebase_core:
:path: ".symlinks/plugins/firebase_core/ios"
firebase_messaging:
:path: ".symlinks/plugins/firebase_messaging/ios"
Flutter:
:path: Flutter
flutter_image_compress_common:
:path: ".symlinks/plugins/flutter_image_compress_common/ios"
flutter_keyboard_visibility:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
flutter_new_badger:
:path: ".symlinks/plugins/flutter_new_badger/ios"
flutter_openim_sdk:
:path: ".symlinks/plugins/flutter_openim_sdk/ios"
flutter_webrtc:
:path: ".symlinks/plugins/flutter_webrtc/ios"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/ios"
getuiflut:
:path: ".symlinks/plugins/getuiflut/ios"
image_cropper:
:path: ".symlinks/plugins/image_cropper/ios"
image_gallery_saver_plus:
:path: ".symlinks/plugins/image_gallery_saver_plus/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
just_audio:
:path: ".symlinks/plugins/just_audio/ios"
livekit_client:
:path: ".symlinks/plugins/livekit_client/ios"
local_auth_darwin:
:path: ".symlinks/plugins/local_auth_darwin/darwin"
map_launcher:
:path: ".symlinks/plugins/map_launcher/ios"
media_kit_libs_ios_video:
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
media_kit_native_event_loop:
:path: ".symlinks/plugins/media_kit_native_event_loop/ios"
media_kit_video:
:path: ".symlinks/plugins/media_kit_video/ios"
open_filex:
:path: ".symlinks/plugins/open_filex/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
photo_manager:
:path: ".symlinks/plugins/photo_manager/ios"
qr_code_scanner_plus:
:path: ".symlinks/plugins/qr_code_scanner_plus/ios"
record_darwin:
:path: ".symlinks/plugins/record_darwin/ios"
scan:
:path: ".symlinks/plugins/scan/ios"
screen_brightness_ios:
:path: ".symlinks/plugins/screen_brightness_ios/ios"
sensors_plus:
:path: ".symlinks/plugins/sensors_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sound_mode:
:path: ".symlinks/plugins/sound_mode/ios"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
vibration:
:path: ".symlinks/plugins/vibration/ios"
video_compress:
:path: ".symlinks/plugins/video_compress/ios"
video_player_avfoundation:
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
volume_controller:
:path: ".symlinks/plugins/volume_controller/ios"
wakelock_plus:
:path: ".symlinks/plugins/wakelock_plus/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
SPEC CHECKSUMS:
audio_session: 088d2483ebd1dc43f51d253d4a1c517d9a2e7207
camera_avfoundation: dd002b0330f4981e1bbcb46ae9b62829237459a4
connectivity_plus: 18382e7311ba19efcaee94442b23b32507b20695
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
emoji_picker_flutter: fe2e6151c5b548e975d546e6eeb567daf0962a58
ffmpeg-kit-ios-full-gpl: 80adc341962e55ef709e36baa8ed9a70cf4ea62b
ffmpeg_kit_flutter_full_gpl: 8d15c14c0c3aba616fac04fe44b3d27d02e3c330
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
Firebase: 374a441a91ead896215703a674d58cdb3e9d772b
firebase_core: feb37e79f775c2bd08dd35e02d83678291317e10
firebase_messaging: e2f0ba891b1509668c07f5099761518a5af8fe3c
FirebaseCore: 48b0dd707581cf9c1a1220da68223fb0a562afaa
FirebaseCoreInternal: d98ab91e2d80a56d7b246856a8885443b302c0c2
FirebaseInstallations: efc0946fc756e4d22d8113f7c761948120322e8c
FirebaseMessaging: e1aca1fcc23e8b9eddb0e33f375ff90944623021
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
flutter_local_notifications: df98d66e515e1ca797af436137b4459b160ad8c9
flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a
flutter_new_badger: e632df3f84b5bbd7f3b37b8122f105edf1b483b3
flutter_openim_sdk: 170b54f6d5c7c287bd9079436d3280197ea27556
flutter_webrtc: 75b868e4f9e817c7a9a42ca4b6169063de4eec9f
geolocator_apple: 9bcea1918ff7f0062d98345d238ae12718acfbc1
getuiflut: 8628ba2b64a738a847a07d2b67e0ac305778e2ee
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
GTCommonSDK: d3299839818ffc2629bf587e096256a7cd0f0dcc
GTSDK: 4392fb9f02e370c8dd3e77fa51ffc511b5ac1ac1
image_cropper: a3291c624a953049bc6a02e1f8c8ceb162a24b25
image_gallery_saver_plus: 782ade975fe6a4600b53e7c1983e3a2979d1e9e5
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
livekit_client: 9c8080879256a0fb16da13c9be4845248209d896
local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
map_launcher: e325db1261d029ff33e08e03baccffe09593ffea
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
Mute: 20135a96076f140cc82bfc8b810e2d6150d8ec7e
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
OpenIMSDKCore: 6fba8ae1b25e33e2d5cfb16f4eab934f3d7c5ee8
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
qr_code_scanner_plus: 3bfe4deb7f28996a63a2a580819d49dae80d5ed3
record_darwin: 3b1a8e7d5c0cbf45ad6165b4d83a6ca643d929c3
scan: aea35bb4aa59ccc8839c576a18cd57c7d492cc86
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
sensors_plus: 7229095999f30740798f0eeef5cd120357a8f4f2
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sound_mode: ef0072f20e7306c1c371984a443156e39be092d5
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
vibration: 7d883d141656a1c1a6d8d238616b2042a51a1241
video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe
video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
WebRTC-SDK: c3d69a87e7185fad3568f6f3cff7c9ac5890acf3
webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4
ZXSDK: 786338c0a18e98e03eda00699c3bfd2700b97117
PODFILE CHECKSUM: 3003a7d95e8a59d1b52038824bad0a4b90bc52ca
COCOAPODS: 1.15.2
@@ -0,0 +1,823 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
173BE1932A67E13300A4D9A9 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173BE1922A67E13300A4D9A9 /* NotificationService.swift */; };
173BE1972A67E13300A4D9A9 /* NotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 173BE1902A67E13200A4D9A9 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
55219944D9DA5CD2EDF4C8C3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E6DB8DF4A03CB207F9CF840 /* Pods_Runner.framework */; };
701BDEDF100D82D14BF9DC9C /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B4A878B5BD9E53AD68260EDF /* GoogleService-Info.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
173BE1952A67E13300A4D9A9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 173BE18F2A67E13200A4D9A9;
remoteInfo = NotificationService;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
173BE19C2A67E13300A4D9A9 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
173BE1972A67E13300A4D9A9 /* NotificationService.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
1706ED5D2AC2917E004FD73C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = "<group>"; };
1706ED5E2AC2917E004FD73C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = "<group>"; };
173BE1902A67E13200A4D9A9 /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
173BE1922A67E13300A4D9A9 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
173BE1942A67E13300A4D9A9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
173BE19D2A67E16300A4D9A9 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
173BE19E2A67E18F00A4D9A9 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; };
176C056E2AA9AAA20006F277 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
1E6DB8DF4A03CB207F9CF840 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
5BB0FD4B4EF99F87CBCBE59A /* 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>"; };
5FF4A91C6E553A5915EBB93E /* 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>"; };
6BADC328EF88768955F7D03E /* 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>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B4A878B5BD9E53AD68260EDF /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
173BE18D2A67E13200A4D9A9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
55219944D9DA5CD2EDF4C8C3 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
173BE1912A67E13300A4D9A9 /* NotificationService */ = {
isa = PBXGroup;
children = (
173BE19E2A67E18F00A4D9A9 /* NotificationService.entitlements */,
173BE1922A67E13300A4D9A9 /* NotificationService.swift */,
173BE1942A67E13300A4D9A9 /* Info.plist */,
);
path = NotificationService;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
173BE1912A67E13300A4D9A9 /* NotificationService */,
97C146EF1CF9000F007C117D /* Products */,
9B5BFEE13D0DBBAB9D1487A5 /* Pods */,
C68B34A13F8B54B6D32ED277 /* Frameworks */,
B4A878B5BD9E53AD68260EDF /* GoogleService-Info.plist */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
173BE1902A67E13200A4D9A9 /* NotificationService.appex */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
173BE19D2A67E16300A4D9A9 /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
9B5BFEE13D0DBBAB9D1487A5 /* Pods */ = {
isa = PBXGroup;
children = (
6BADC328EF88768955F7D03E /* Pods-Runner.debug.xcconfig */,
5BB0FD4B4EF99F87CBCBE59A /* Pods-Runner.release.xcconfig */,
5FF4A91C6E553A5915EBB93E /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
C68B34A13F8B54B6D32ED277 /* Frameworks */ = {
isa = PBXGroup;
children = (
176C056E2AA9AAA20006F277 /* ReplayKit.framework */,
1E6DB8DF4A03CB207F9CF840 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
173BE18F2A67E13200A4D9A9 /* NotificationService */ = {
isa = PBXNativeTarget;
buildConfigurationList = 173BE1982A67E13300A4D9A9 /* Build configuration list for PBXNativeTarget "NotificationService" */;
buildPhases = (
173BE18C2A67E13200A4D9A9 /* Sources */,
173BE18D2A67E13200A4D9A9 /* Frameworks */,
173BE18E2A67E13200A4D9A9 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = NotificationService;
productName = NotificationService;
productReference = 173BE1902A67E13200A4D9A9 /* NotificationService.appex */;
productType = "com.apple.product-type.app-extension";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
6D26B612E7CE061D882E2C44 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
173BE19C2A67E13300A4D9A9 /* Embed Foundation Extensions */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
D93E9AE0652B0DF2EDE1169B /* [CP] Embed Pods Frameworks */,
170C561DA4A2C0A19C3C3AB0 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
173BE1962A67E13300A4D9A9 /* PBXTargetDependency */,
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
173BE18F2A67E13200A4D9A9 = {
CreatedOnToolsVersion = 14.3;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
"zh-Hans",
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
173BE18F2A67E13200A4D9A9 /* NotificationService */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
173BE18E2A67E13200A4D9A9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
701BDEDF100D82D14BF9DC9C /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
170C561DA4A2C0A19C3C3AB0 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
6D26B612E7CE061D882E2C44 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
D93E9AE0652B0DF2EDE1169B /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
173BE18C2A67E13200A4D9A9 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
173BE1932A67E13300A4D9A9 /* NotificationService.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
173BE1962A67E13300A4D9A9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 173BE18F2A67E13200A4D9A9 /* NotificationService */;
targetProxy = 173BE1952A67E13300A4D9A9 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
1706ED5D2AC2917E004FD73C /* zh-Hans */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
1706ED5E2AC2917E004FD73C /* zh-Hans */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
173BE1992A67E13300A4D9A9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 17;
DEVELOPMENT_TEAM = V57RT7LMFH;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NotificationService/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = NotificationService;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.openim.flutter.demoo.NotificationService;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
173BE19A2A67E13300A4D9A9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 17;
DEVELOPMENT_TEAM = V57RT7LMFH;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NotificationService/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = NotificationService;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.1;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.openim.flutter.demoo.NotificationService;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
173BE19B2A67E13300A4D9A9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 17;
DEVELOPMENT_TEAM = V57RT7LMFH;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NotificationService/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = NotificationService;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.1;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.openim.flutter.demoo.NotificationService;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Profile;
};
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = V57RT7LMFH;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.8.2;
PRODUCT_BUNDLE_IDENTIFIER = io.openim.flutter.demoo;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = V57RT7LMFH;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.8.2;
PRODUCT_BUNDLE_IDENTIFIER = io.openim.flutter.demoo;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = V57RT7LMFH;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.8.2;
PRODUCT_BUNDLE_IDENTIFIER = io.openim.flutter.demoo;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
173BE1982A67E13300A4D9A9 /* Build configuration list for PBXNativeTarget "NotificationService" */ = {
isa = XCConfigurationList;
buildConfigurations = (
173BE1992A67E13300A4D9A9 /* Debug */,
173BE19A2A67E13300A4D9A9 /* Release */,
173BE19B2A67E13300A4D9A9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
+74
View File
@@ -0,0 +1,74 @@
import UIKit
import Flutter
import FirebaseCore
@main
@objc class AppDelegate: FlutterAppDelegate {
var replayKitChannel: FlutterMethodChannel! = nil
var observeTimer: Timer?
var hasEmittedFirstSample = false;
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
guard let controller = window?.rootViewController as? FlutterViewController else {
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
FirebaseApp.configure()
replayKitChannel = FlutterMethodChannel(name: "io.livekit.example.flutter/replaykit-channel",binaryMessenger: controller.binaryMessenger)
replayKitChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
self.handleReplayKitFromFlutter(result: result, call:call)
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func handleReplayKitFromFlutter(result:FlutterResult, call: FlutterMethodCall){
switch (call.method) {
case "startReplayKit":
self.hasEmittedFirstSample = false
let group=UserDefaults(suiteName: "group.io.livekit.example.flutter")
group!.set(false, forKey: "closeReplayKitFromNative")
group!.set(false, forKey: "closeReplayKitFromFlutter")
self.observeReplayKitStateChanged()
break
case "closeReplayKit":
let group=UserDefaults(suiteName: "group.io.livekit.example.flutter")
group!.set(true,forKey: "closeReplayKitFromFlutter")
result(true)
break
default:
return result(FlutterMethodNotImplemented)
}
}
func observeReplayKitStateChanged(){
if (self.observeTimer != nil) {
return
}
let group=UserDefaults(suiteName: "group.io.livekit.example.flutter")
self.observeTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
let closeReplayKitFromNative=group!.bool(forKey: "closeReplayKitFromNative")
let hasSampleBroadcast=group!.bool(forKey: "hasSampleBroadcast")
if (closeReplayKitFromNative) {
self.hasEmittedFirstSample = false
self.replayKitChannel.invokeMethod("closeReplayKitFromNative", arguments: true)
} else if (hasSampleBroadcast) {
if (!self.hasEmittedFirstSample) {
self.hasEmittedFirstSample = true
self.replayKitChannel.invokeMethod("hasSampleBroadcast", arguments: true)
}
}
}
}
}
@@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyC0BhV-mo84LvOuqWf2bS966jlf0f8mh74</string>
<key>GCM_SENDER_ID</key>
<string>299075855003</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>io.openim.flutter.base</string>
<key>PROJECT_ID</key>
<string>im-fer-c3347</string>
<key>STORAGE_BUCKET</key>
<string>im-fer-c3347.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:299075855003:ios:23b06300e33d984309dc3e</string>
</dict>
</plist>
+99
View File
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<array>
<string>zh-CN</string>
<string>en-US</string>
</array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>F-DEMO</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>comgooglemaps</string>
<string>baidumap</string>
<string>iosamap</string>
<string>waze</string>
<string>yandexmaps</string>
<string>yandexnavi</string>
<string>citymapper</string>
<string>mapswithme</string>
<string>osmandmaps</string>
<string>dgis</string>
<string>qqmap</string>
<string>here-location</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSAppleMusicUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法给好友发送或者上传本地相册图片及视频内容。</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>App requires access to Bluetooth to connect to devices.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>App requires access to Bluetooth to communicate with peripheral devices.</string>
<key>NSCameraUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法使用拍照、录制视频、扫一扫等功能。</string>
<key>NSFaceIDUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法使用Touch ID 或 Face ID解锁功能。</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法使用聊天时发送定位等功能。</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法使用聊天时发送定位等功能。</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法使用聊天时发送定位等功能。</string>
<key>NSMicrophoneUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法使用视频通话、发送语音消息或录制视频等功能。</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法给好友发送或者上传本地相册图片及视频内容。</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>请点击“好”以允许访问。若不允许,你将无法给好友发送或者上传本地相册图片及视频内容。</string>
<key>RTCAppGroupIdentifier</key>
<string>group.cn.rentsoft.openim.flutter.rtc</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden</key>
<false/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportsDocumentBrowser</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
</dict>
</plist>
@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.security.application-groups</key>
<array>
<string>group.cn.rentsoft.openim.flutter.rtc</string>
</array>
</dict>
</plist>
@@ -0,0 +1 @@
@@ -0,0 +1 @@
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

+113
View File
@@ -0,0 +1,113 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:openim_common/openim_common.dart';
import 'core/controller/im_controller.dart';
import 'routes/app_pages.dart';
import 'widgets/app_view.dart';
class ChatApp extends StatelessWidget {
const ChatApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AppView(
builder: (locale, builder) => GetMaterialApp(
debugShowCheckedModeBanner: false,
enableLog: true,
builder: builder,
logWriterCallback: Logger.print,
translations: TranslationService(),
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
fallbackLocale: TranslationService.fallbackLocale,
locale: locale,
localeResolutionCallback: (locale, list) {
Get.locale ??= locale;
return locale;
},
supportedLocales: const [Locale('zh', 'CN'), Locale('en', 'US')],
getPages: AppPages.routes,
initialBinding: InitBinding(),
initialRoute: AppRoutes.splash,
theme: _themeData,
),
);
}
ThemeData get _themeData => ThemeData.light().copyWith(
scaffoldBackgroundColor: Colors.grey.shade50,
canvasColor: Colors.white,
appBarTheme: const AppBarTheme(color: Colors.white),
textSelectionTheme: const TextSelectionThemeData().copyWith(cursorColor: Colors.blue),
checkboxTheme: const CheckboxThemeData().copyWith(
checkColor: WidgetStateProperty.all(Colors.white),
fillColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.disabled)) {
return Colors.grey;
}
if (states.contains(WidgetState.selected)) {
return Colors.blue;
}
return Colors.white;
}),
side: BorderSide(color: Colors.grey.shade500, width: 1),
),
dialogTheme: const DialogTheme().copyWith(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4.0),
),
),
textStyle: WidgetStatePropertyAll(
TextStyle(
fontSize: 16.sp,
color: Colors.black,
),
),
foregroundColor: const WidgetStatePropertyAll(Colors.black),
),
),
progressIndicatorTheme: const ProgressIndicatorThemeData()
.copyWith(color: Colors.white, linearTrackColor: Colors.grey[300], circularTrackColor: Colors.grey[300]),
cupertinoOverrideTheme: CupertinoThemeData(
brightness: Brightness.light,
primaryColor: CupertinoColors.systemBlue,
barBackgroundColor: Colors.white,
applyThemeToAll: true,
textTheme: const CupertinoTextThemeData().copyWith(
navActionTextStyle: TextStyle(color: CupertinoColors.label, fontSize: 17.sp),
actionTextStyle: TextStyle(color: CupertinoColors.systemBlue, fontSize: 17.sp),
textStyle: TextStyle(color: CupertinoColors.label, fontSize: 17.sp),
navLargeTitleTextStyle: TextStyle(color: CupertinoColors.label, fontSize: 20.sp),
navTitleTextStyle: TextStyle(color: CupertinoColors.label, fontSize: 17.sp),
pickerTextStyle: TextStyle(color: CupertinoColors.label, fontSize: 17.sp),
tabLabelTextStyle: TextStyle(color: CupertinoColors.label, fontSize: 17.sp),
dateTimePickerTextStyle: TextStyle(color: CupertinoColors.label, fontSize: 17.sp),
),
),
);
}
class InitBinding extends Bindings {
@override
void dependencies() {
Get.put<IMController>(IMController());
Get.put<PushController>(PushController());
Get.put<CacheController>(CacheController());
Get.put<DownloadController>(DownloadController());
}
}
@@ -0,0 +1,288 @@
import 'dart:io';
import 'package:audio_session/audio_session.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_new_badger/flutter_new_badger.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart' as im;
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
import 'package:get/get.dart';
import 'package:just_audio/just_audio.dart';
import 'package:openim/core/im_callback.dart';
import 'package:openim_common/openim_common.dart';
import 'package:sound_mode/sound_mode.dart';
import 'package:sound_mode/utils/ringer_mode_statuses.dart';
import 'package:vibration/vibration.dart';
import '../../utils/upgrade_manager.dart';
import 'im_controller.dart';
class AppController extends GetxController with UpgradeManger {
var isRunningBackground = false;
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
final initializationSettingsAndroid = const AndroidInitializationSettings('@mipmap/ic_launcher');
final DarwinInitializationSettings initializationSettingsDarwin = const DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
);
RTCBridge? get rtcBridge => PackageBridge.rtcBridge;
bool get shouldMuted =>
rtcBridge?.hasConnection == true ||
Get.find<IMController>().imSdkStatusSubject.values.last.status != IMSdkStatus.syncEnded;
final _ring = 'assets/audio/message_ring.wav';
final _audioPlayer = AudioPlayer();
final configuration = const AudioSessionConfiguration(
avAudioSessionCategory: AVAudioSessionCategory.ambient,
avAudioSessionCategoryOptions: AVAudioSessionCategoryOptions.mixWithOthers,
androidAudioFocusGainType: AndroidAudioFocusGainType.gainTransientMayDuck,
androidAudioAttributes: AndroidAudioAttributes(
contentType: AndroidAudioContentType.sonification,
usage: AndroidAudioUsage.notification,
),
);
late AudioSession session;
late BaseDeviceInfo deviceInfo;
final clientConfigMap = <String, dynamic>{}.obs;
Future<void> runningBackground(bool run) async {
Logger.print('-----App running background : $run-------------');
if (isRunningBackground && !run) {}
isRunningBackground = run;
if (!run) {
_cancelAllNotifications();
}
}
@override
void onInit() async {
_initPlayer();
final initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (notificationResponse) {},
);
autoCheckVersionUpgrade();
super.onInit();
}
void _requestPermissions() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.requestNotificationsPermission();
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
Future<void> showNotification(im.Message message, {bool showNotification = true}) async {
if (_isGlobalNotDisturb() ||
message.attachedInfoElem?.notSenderNotificationPush == true ||
message.contentType == im.MessageType.typing ||
message.sendID == OpenIM.iMManager.userID ||
(message.contentType! >= 1000 && message.contentType != 1400)) return;
var sourceID = message.sessionType == ConversationType.single ? message.sendID : message.groupID;
if (sourceID != null && message.sessionType != null) {
var i = await OpenIM.iMManager.conversationManager.getOneConversation(
sourceID: sourceID,
sessionType: message.sessionType!,
);
if (i.recvMsgOpt != 0) return;
}
if (showNotification) {
promptSoundOrNotification(message.seq!);
}
}
Future<void> promptSoundOrNotification(int seq) async {
if (Get.find<IMController>().imSdkStatusSubject.values.lastOrNull?.status != IMSdkStatus.syncEnded) {
return;
}
if (!isRunningBackground) {
_playMessageSound();
} else {
if (Platform.isAndroid) {
final id = seq;
const androidPlatformChannelSpecifics = AndroidNotificationDetails('chat', 'OpenIM聊天消息',
channelDescription: '来自OpenIM的信息', importance: Importance.max, priority: Priority.high, ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(id, '您收到了一条新消息', '消息内容:.....', platformChannelSpecifics,
payload: '');
}
}
}
Future<void> _cancelAllNotifications() async {
await flutterLocalNotificationsPlugin.cancelAll();
}
Future<void> _startForegroundService() async {
await getAppInfo();
const androidPlatformChannelSpecifics = AndroidNotificationDetails('pro', 'OpenIM后台进程',
channelDescription: '保证app能收到信息', importance: Importance.max, priority: Priority.high, ticker: 'ticker');
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.startForegroundService(1, packageInfo!.appName, '正在运行...',
notificationDetails: androidPlatformChannelSpecifics, payload: '');
}
Future<void> _stopForegroundService() async {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.stopForegroundService();
}
void showBadge(count) {
OpenIM.iMManager.messageManager.setAppBadge(count);
if (count == 0) {
removeBadge();
PushController.resetBadge();
} else {
FlutterNewBadger.setBadge(count);
PushController.setBadge(count);
}
}
void removeBadge() {
FlutterNewBadger.removeBadge();
}
@override
void onClose() {
closeSubject();
_audioPlayer.dispose();
super.onClose();
}
Locale? getLocale() {
var local = Get.locale;
var index = DataSp.getLanguage() ?? 0;
switch (index) {
case 1:
local = const Locale('zh', 'CN');
break;
case 2:
local = const Locale('en', 'US');
break;
}
return local;
}
@override
void onReady() {
queryClientConfig();
_getDeviceInfo();
_cancelAllNotifications();
super.onReady();
}
bool _isGlobalNotDisturb() {
bool isRegistered = Get.isRegistered<IMController>();
if (isRegistered) {
var logic = Get.find<IMController>();
return logic.userInfo.value.globalRecvMsgOpt == 2;
}
return false;
}
void _initPlayer() async {
session = await AudioSession.instance;
await session.configure(configuration);
_audioPlayer.setAsset(_ring, package: 'openim_common');
_audioPlayer.playerStateStream.listen((state) {
switch (state.processingState) {
case ProcessingState.idle:
case ProcessingState.loading:
case ProcessingState.buffering:
case ProcessingState.ready:
break;
case ProcessingState.completed:
_stopMessageSound();
break;
}
});
}
void _playMessageSound() async {
if (shouldMuted) {
return;
}
bool isRegistered = Get.isRegistered<IMController>();
bool isAllowVibration = true;
bool isAllowBeep = true;
if (isRegistered) {
var logic = Get.find<IMController>();
isAllowVibration = logic.userInfo.value.allowVibration == 1;
isAllowBeep = logic.userInfo.value.allowBeep == 1;
}
RingerModeStatus ringerStatus = await SoundMode.ringerModeStatus;
Logger.print('System ringer status: $ringerStatus, user is allow beep: $isAllowBeep',
fileName: 'app_controller.dart');
if (!_audioPlayer.playerState.playing &&
isAllowBeep &&
(ringerStatus == RingerModeStatus.normal || ringerStatus == RingerModeStatus.unknown)) {
await session.setActive(true);
_audioPlayer.setAsset(_ring, package: 'openim_common');
_audioPlayer.setLoopMode(LoopMode.off);
_audioPlayer.setVolume(1.0);
_audioPlayer.play();
}
if (isAllowVibration &&
(ringerStatus == RingerModeStatus.normal ||
ringerStatus == RingerModeStatus.vibrate ||
ringerStatus == RingerModeStatus.unknown)) {
if (await Vibration.hasVibrator() == true) {
Vibration.vibrate();
}
}
}
void _stopMessageSound() async {
if (_audioPlayer.playerState.playing) {
_audioPlayer.stop();
}
await session.setActive(false);
}
void _getDeviceInfo() async {
final deviceInfoPlugin = DeviceInfoPlugin();
deviceInfo = await deviceInfoPlugin.deviceInfo;
}
Future queryClientConfig() async {
final map = await Apis.getClientConfig();
clientConfigMap.assignAll(map);
return clientConfigMap;
}
}
@@ -0,0 +1,214 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
import 'package:get/get.dart';
import 'package:openim_common/openim_common.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:openim_live/openim_live.dart';
import '../im_callback.dart';
class IMController extends GetxController with IMCallback, OpenIMLive {
late Rx<UserFullInfo> userInfo;
late String atAllTag;
@override
void onClose() {
super.close();
onCloseLive();
super.onClose();
}
@override
void onInit() async {
super.onInit();
onInitLive();
WidgetsBinding.instance.addPostFrameCallback((_) => initOpenIM());
}
void initOpenIM() async {
final initialized = await OpenIM.iMManager.initSDK(
platformID: IMUtils.getPlatform(),
apiAddr: Config.imApiUrl,
wsAddr: Config.imWsUrl,
dataDir: Config.cachePath,
logLevel: Config.logLevel,
logFilePath: Config.cachePath,
listener: OnConnectListener(
onConnecting: () {
imSdkStatus(IMSdkStatus.connecting);
},
onConnectFailed: (code, error) {
imSdkStatus(IMSdkStatus.connectionFailed);
},
onConnectSuccess: () {
imSdkStatus(IMSdkStatus.connectionSucceeded);
},
onKickedOffline: kickedOffline,
onUserTokenExpired: kickedOffline,
onUserTokenInvalid: userTokenInvalid,
),
);
OpenIM.iMManager
..setUploadLogsListener(OnUploadLogsListener(onUploadProgress: uploadLogsProgress))
..userManager.setUserListener(OnUserListener(
onSelfInfoUpdated: (u) {
selfInfoUpdated(u);
userInfo.update((val) {
val?.nickname = u.nickname;
val?.faceURL = u.faceURL;
val?.remark = u.remark;
val?.ex = u.ex;
val?.globalRecvMsgOpt = u.globalRecvMsgOpt;
});
},
onUserStatusChanged: userStausChanged))
..messageManager.setAdvancedMsgListener(OnAdvancedMsgListener(
onRecvC2CReadReceipt: recvC2CMessageReadReceipt,
onRecvNewMessage: recvNewMessage,
onNewRecvMessageRevoked: recvMessageRevoked,
onRecvOfflineNewMessage: recvOfflineMessage,
onRecvOnlineOnlyMessage: (msg) {
if (msg.isCustomType) {
final data = msg.customElem!.data;
final map = jsonDecode(data!);
final customType = map['customType'];
if (customType == CustomMessageType.callingInvite ||
customType == CustomMessageType.callingAccept ||
customType == CustomMessageType.callingReject ||
customType == CustomMessageType.callingCancel ||
customType == CustomMessageType.callingHungup) {
final signaling = SignalingInfo(invitation: InvitationInfo.fromJson(map['data']));
signaling.userID = signaling.invitation?.inviterUserID;
switch (customType) {
case CustomMessageType.callingInvite:
receiveNewInvitation(signaling);
break;
case CustomMessageType.callingAccept:
inviteeAccepted(signaling);
break;
case CustomMessageType.callingReject:
inviteeRejected(signaling);
break;
case CustomMessageType.callingCancel:
invitationCancelled(signaling);
break;
case CustomMessageType.callingHungup:
beHangup(signaling);
break;
}
}
}
},
))
..messageManager.setMsgSendProgressListener(OnMsgSendProgressListener(
onProgress: progressCallback,
))
..messageManager.setCustomBusinessListener(OnCustomBusinessListener(
onRecvCustomBusinessMessage: recvCustomBusinessMessage,
))
..friendshipManager.setFriendshipListener(OnFriendshipListener(
onBlackAdded: blacklistAdded,
onBlackDeleted: blacklistDeleted,
onFriendApplicationAccepted: friendApplicationAccepted,
onFriendApplicationAdded: friendApplicationAdded,
onFriendApplicationDeleted: friendApplicationDeleted,
onFriendApplicationRejected: friendApplicationRejected,
onFriendInfoChanged: friendInfoChanged,
onFriendAdded: friendAdded,
onFriendDeleted: friendDeleted,
))
..conversationManager.setConversationListener(OnConversationListener(
onConversationChanged: conversationChanged,
onNewConversation: newConversation,
onTotalUnreadMessageCountChanged: totalUnreadMsgCountChanged,
onInputStatusChanged: inputStateChanged,
onSyncServerFailed: (reInstall) {
imSdkStatus(IMSdkStatus.syncFailed, reInstall: reInstall ?? false);
},
onSyncServerFinish: (reInstall) {
imSdkStatus(IMSdkStatus.syncEnded, reInstall: reInstall ?? false);
if (Platform.isAndroid) {
Permissions.request([Permission.systemAlertWindow]);
}
},
onSyncServerStart: (reInstall) {
imSdkStatus(IMSdkStatus.syncStart, reInstall: reInstall ?? false);
},
onSyncServerProgress: (progress) {
imSdkStatus(IMSdkStatus.syncProgress, progress: progress);
}))
..groupManager.setGroupListener(OnGroupListener(
onGroupApplicationAccepted: groupApplicationAccepted,
onGroupApplicationAdded: groupApplicationAdded,
onGroupApplicationDeleted: groupApplicationDeleted,
onGroupApplicationRejected: groupApplicationRejected,
onGroupInfoChanged: groupInfoChanged,
onGroupMemberAdded: groupMemberAdded,
onGroupMemberDeleted: groupMemberDeleted,
onGroupMemberInfoChanged: groupMemberInfoChanged,
onJoinedGroupAdded: joinedGroupAdded,
onJoinedGroupDeleted: joinedGroupDeleted,
));
initializedSubject.sink.add(initialized);
}
Future login(String userID, String token) async {
try {
var user = await OpenIM.iMManager.login(
userID: userID,
token: token,
defaultValue: () async => UserInfo(userID: userID),
);
ApiService().setToken(token);
userInfo = UserFullInfo.fromJson(user.toJson()).obs;
_queryMyFullInfo();
_queryAtAllTag();
} catch (e, s) {
Logger.print('e: $e s:$s');
await _handleLoginRepeatError(e);
return Future.error(e, s);
}
}
Future logout() {
return OpenIM.iMManager.logout();
}
void _queryAtAllTag() async {
atAllTag = OpenIM.iMManager.conversationManager.atAllTag;
}
void _queryMyFullInfo() async {
final data = await Apis.queryMyFullInfo();
if (data is UserFullInfo) {
userInfo.update((val) {
val?.allowAddFriend = data.allowAddFriend;
val?.allowBeep = data.allowBeep;
val?.allowVibration = data.allowVibration;
val?.nickname = data.nickname;
val?.faceURL = data.faceURL;
val?.phoneNumber = data.phoneNumber;
val?.email = data.email;
val?.birth = data.birth;
val?.gender = data.gender;
});
}
}
_handleLoginRepeatError(e) async {
if (e is PlatformException && (e.code == "13002" || e.code == '1507')) {
await logout();
await DataSp.removeLoginCertificate();
}
}
}

Some files were not shown because too many files have changed in this diff Show More