chatapp3-flutter/需求进度.md
2026-04-14 14:49:28 +08:00

197 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 需求进度
## 当前总目标
- 控制当前 Flutter Android 发包体积,持续定位冗余组件、超大资源和不合理构建配置,并把每一步处理结果落盘记录。
## 已完成模块
- 创建并持续维护进度跟踪文件。
- 已修复首页房间封面显示链路:兼容接口 `roomCover/cover` 双字段,并补齐编辑房间成功后的封面内存回写。
- 完成仓库结构、依赖引用、资源体积和 APK 组成的第一轮排查。
- 移除 4 个当前未在业务层直接使用的插件依赖:`loading_indicator_view_plus``social_sharing_plus``flutter_foreground_task``on_audio_query`,并清理相关平台声明。
- 修补 `image_cropper 5.0.1` Android 兼容问题,切换到本地 path 依赖以恢复构建。
- 完成 Android release 签名回退配置,解决仓库缺少 `yumi.jks` / `yumi_debug.jks` 时无法继续本地构建分析的问题。
- 完成 release 包体分析,确认 universal APK 过大主要由多 ABI 与 Agora/Tencent 原生 so 导致。
- 去除 Gradle 中与 Flutter 冲突的硬编码 `abiFilters`,确认 `--split-per-abi` 可以正常产出分架构 APK。
- 完成 TinyPNG 环境核查,并接入可执行的 Ruby 批量压缩脚本。
- 已完成 TinyPNG 第一轮批量压缩,`sc_images + assets` 总量已从 `47.25 MB` 降到 `22.54 MB`
- 已增强 TinyPNG 脚本,支持断点续跑、单文件目标和失败项重试。
- 已完成 TinyPNG 网络失败项补跑6 张 `SSL_connect` 异常图片已全部压缩成功。
- 已完成图片压缩后的 release 复测,确认分 ABI APK 体积继续显著下降。
- 已切换 Android `release` 为真正的瘦身模式:开启 `minify``shrinkResources``zipAlign`
- 已完成开启瘦身配置后的 Android release 复测,并接入 `split-debug-info` 保存 Dart symbols。
- 已生成统一的 Python 打包脚本 `scripts/build_release.py`,开始接管 `AAB`、分 ABI APK 与 iOS 包流程。
- 已完成 `scripts/build_release.py` 的 Android / iOS 真机冒烟验证,产物归档目录与 manifest 均已生成。
- 已按当前需求再次完成正式 `AAB` 出包。
- 已定位 Google Play 上传阻塞点:当前 `AAB` 使用的是 `Android Debug` 证书签名,不是正式 upload key。
- 已确认当前项目属于“首次上架的新应用”,后续应走 Play App Signing 首发流程,而不是兼容老签名迁移流程。
- 已梳理 Google Play 首次上架所需的 `Play App Signing``upload key`、重新打包与提审步骤。
- 已澄清首次生成 `upload keystore` 时的“密钥库口令”是本地自行设置的密码,与 Google 提供的 `deployment_cert.der` 证书文件无关。
- 已为新应用生成正式 `upload keystore`,并接入工程的 release 签名配置。
- 已重新打出正式 `AAB`,并确认其签名已经从 `Android Debug` 切换到新的 upload key。
- 已定位 `FOREGROUND_SERVICE_MEDIA_PROJECTION` 的来源为 Agora `full-screen-sharing` 依赖,并开始从主 Manifest 覆盖移除。
- 已移除 `FOREGROUND_SERVICE_MEDIA_PROJECTION` 相关声明并重新打出正式 `AAB`
- 已按当前需求打出正式 `arm64-v8a` 单架构 `APK`
- 已将新的 `google-services.json` 替换进工程,准备重新打包验证。
## 进行中模块
- 评估 iOS 正式签名参数接入后导出 `.ipa` 的流程。
- 继续评估 Agora 扩展 so 与 release shrink 策略是否还能进一步裁剪。
- 评估 12 张 TinyPNG 不支持解码的特殊 `webp` 是否需要改格式或换工具处理。
## 关键技术决策
- 先做高置信度瘦身优先清理未使用插件、ABI 配置和超大图片,暂不贸然删除核心业务能力。
- 避开仓库中用户已有未提交改动,只改必要文件并持续把结果写入本文件。
- 包体分析聚焦 release 产物,不被 `build/`、iOS 中间产物等本地缓存误导。
- Android 架构裁剪交给 Flutter 构建命令驱动,不再在 Gradle 中硬编码 `abiFilters`
-`image_cropper` 采用本地 path 依赖加最小补丁策略,避免升级带来的业务回归面。
- Android 签名配置采用条件回退:正式 keystore 不存在时自动回退到 debug 签名,仅用于本地分析验证。
- 图片压缩优先走 TinyPNG以尽量保持画质稳定失败项按原因分流处理。
- TinyPNG 的 `SSL_connect` 视为可重试网络抖动;`Image could not be decoded` 视为 TinyPNG 对特殊/动图 WebP 的能力边界,先记录不阻塞其余压缩。
## 已改动文件
- `需求进度.md`
- `lib/services/room/rc_room_manager.dart`
- `lib/shared/business_logic/models/res/room_res.dart`
- `lib/shared/business_logic/models/res/follow_room_res.dart`
- `lib/shared/business_logic/models/res/my_room_res.dart`
- `lib/shared/business_logic/models/res/sc_edit_room_info_res.dart`
- `lib/shared/business_logic/models/res/join_room_res.dart`
- `.gitignore`
- `android/key.properties`
- `pubspec.yaml`
- `pubspec.lock`
- `lib/ui_kit/components/dialog/dialog.dart`
- `android/app/src/main/AndroidManifest.xml`
- `android/app/google-services.json`
- `ios/Runner/Info.plist`
- `scripts/tinypng_batch.rb`
- `scripts/build_release.py`
- `tinypng-progress.json`
- `tinypng-report.json`
- `local_packages/image_cropper-5.0.1-patched/android/src/main/java/vn/hunghd/flutter/plugins/imagecropper/ImageCropperPlugin.java`
- `local_packages/image_cropper-5.0.1-patched/`
- `android/app/build.gradle.kts`
- `android/app/upload-keystore.jks`
- `android/app/upload_certificate.pem`
- `build/symbols/android/`
- `build/symbols/ios/`
- `dist/release/smoke-android/`
- `dist/release/smoke-ios/`
- `sc_images/`
- `assets/`
## 已验证结果
- 当前工作区存在用户已有未提交改动,后续处理均避开覆盖。
- 首页 `party/follow/history/mine` 以及房间详情使用的房间封面模型已兼容 `roomCover``cover` 两种返回字段,上传封面后不会再因为字段名不一致掉回空占位。
- 目录体积排查显示:`build/``4.7G``.dart_tool/``347M``ios/``250M``sc_images/``48M``local_packages/``6.1M`
- 当前包体过大的主要原因已经确认:
- universal APK 带入了 `arm64-v8a``armeabi-v7a``x86_64` 三套 ABI。
- Agora 与腾讯 IM 原生 so 很大,其中 `libagora-rtc-sdk.so` 合计约 `79.4MB``libImSDK.so` 合计约 `10.2MB`
- 资源目录中 `sc_images/index``sc_images/room``sc_images/person``sc_images/splash` 是最主要的大图来源。
- `flutter build apk --release --target-platform android-arm64 --analyze-size` 已成功执行,当前 universal release APK 约 `271MB`
- `flutter build apk --release --split-per-abi` 已成功执行,压缩前分架构 APK 约为:
- `app-arm64-v8a-release.apk``161.4MB`
- `app-armeabi-v7a-release.apk``138.8MB`
- `app-x86_64-release.apk``148.6MB`
- `loading_indicator_view_plus``social_sharing_plus``flutter_foreground_task``on_audio_query` 已从当前依赖链路中移除。
- 当前图片资源统计为 `412`TinyPNG 两轮处理后总量已从 `47.25 MB` 降到 `22.27 MB`,累计节省约 `24.99 MB`
- 当前 TinyPNG 已成功压缩 `400` 张图片,剩余失败 `12` 张。
- 当前压缩收益最大的图片包括:
- `sc_images/person/sc_icon_edit_userinfo_bg.png``2640776 -> 436823`,节省约 `2.10 MB`
- `sc_images/splash/sc_splash.png``2373335 -> 379804`,节省约 `1.90 MB`
- `sc_images/room/sc_icon_room_defaut_bg.png``2243222 -> 704696`,节省约 `1.47 MB`
- `sc_images/index/sc_icon_index_bg.png``1422169 -> 420635`,节省约 `0.96 MB`
- 失败项已分型:
- `12` 张为 TinyPNG 无法解码的特殊/动图 `webp`
- 当前 TinyPNG 进度与统计文件已落盘:`tinypng-progress.json``tinypng-report.json`
- 图片压缩后再次执行 `flutter build apk --release --split-per-abi`,当前分架构 APK 已下降到:
- `app-arm64-v8a-release.apk``135.2MB`,比压缩前少 `26.2MB`
- `app-armeabi-v7a-release.apk``112.6MB`,比压缩前少 `26.2MB`
- `app-x86_64-release.apk``122.4MB`,比压缩前少 `26.2MB`
- 可以确认:这轮图片压缩带来的资源收益已经真实反映到最终 APK 体积中。
- 在开启 `minify``shrinkResources``zipAlign` 并追加 `--split-debug-info=build/symbols/android`Android release 继续下降为:
- `app-release.aab``181.8MB`
- `app-arm64-v8a-release.apk``128.7MB`,比上一轮 `135.2MB` 再少 `6.5MB`
- `app-armeabi-v7a-release.apk``105.8MB`,比上一轮 `112.6MB` 再少 `6.8MB`
- `app-x86_64-release.apk``115.8MB`,比上一轮 `122.4MB` 再少 `6.6MB`
- `build/symbols/android` 已生成 3 份符号文件,总计约 `14MB`,后续可用于 Dart 堆栈还原。
- `scripts/build_release.py --platform android --output-dir dist/release/smoke-android` 已验证通过,归档结果为:
- `android/google-play/` 下输出 `yumi-v1.0.0-b1-google-play.aab` 与 Dart symbols
- `android/local/` 下输出 `arm64-v8a.apk``armeabi-v7a.apk`
- `android/testing/` 下单独输出 `x86_64-test.apk`
- 同时生成 `build_manifest.json`,已记录产物路径、大小和 `sha256`
- `scripts/build_release.py --platform ios --output-dir dist/release/smoke-ios` 已验证通过,当前无签名模式下输出:
- `ios/archive/yumi-v1.0.0-b1.xcarchive`
- `ios/symbols/app.ios-arm64.symbols`
- 当前 iOS 无签名构建会跳过 `.ipa` 导出;如需正式 `.ipa`,脚本需追加 `--ios-codesign`
- 已将 `dist/` 加入 `.gitignore`,避免打包产物持续污染工作区状态
- 本轮按需执行 `flutter build appbundle --release --split-debug-info=build/symbols/android` 已成功,产物为:
- `build/app/outputs/bundle/release/app-release.aab`
- 当前 AAB 体积约 `181.8MB`
- 本地校验 `app-release.aab` 证书后确认:
- 证书所有者为 `C=US, O=Android, CN=Android Debug`
- 当前 AAB 的 `SHA1``6B:72:BF:6F:D1:7A:F2:99:CD:F3:14:EE:18:A6:29:67:F8:05:E6:B4`
- 这说明当前 release 构建仍在回退使用 debug signing无法直接作为 Google Play 正式发布包
- 已生成新的 upload 证书文件:
- `android/app/upload-keystore.jks`
- `android/app/upload_certificate.pem`
- 新 upload key 当前指纹为:
- `SHA1: C1:80:AF:BF:6E:1F:F2:F4:49:58:72:87:A2:BC:54:07:E7:D2:D9:A3`
- `SHA256: 81:D6:3A:43:31:FA:83:87:0E:C3:5B:52:B8:C1:05:7C:3A:32:EC:24:37:0B:11:E4:2F:8C:62:4E:D4:AC:0C:3B`
- release 构建已改为从 `android/key.properties` 读取正式 upload keystore不再依赖当前的 debug 回退配置
- `flutter build appbundle --release --split-debug-info=build/symbols/android` 已重新执行,当前正式产物仍为:
- `build/app/outputs/bundle/release/app-release.aab`
- 当前 AAB 体积约 `181.8MB`
- 重新校验该 AAB 后,签名者已变为:
- `CN=Yumi Upload, OU=Mobile, O=Yumi, L=Shanghai, ST=Shanghai, C=CN`
- `deployment_cert.der` 已核实为 Google 侧 app signing 证书,指纹为:
- `SHA1: 3F:E1:78:DC:C3:29:4F:74:20:DF:27:54:CF:AF:46:46:D6:A1:94:78`
- `SHA256: F9:BF:D0:89:F9:D7:FD:B2:53:24:A7:DB:59:E1:52:6F:54:A3:93:95:4E:88:7F:1C:4B:D6:03:66:E7:1A:1F:85`
- 已确认当前存在两套不同证书:
- 本地 `upload key`:用于你上传 AAB 到 Google Play
- Google `app signing key`:用于 Google Play 最终给用户分发签名包
- `FOREGROUND_SERVICE_MEDIA_PROJECTION` 在当前 release 合并报告中的来源已确认是 `io.agora.rtc:full-screen-sharing:4.5.2`
- 该依赖同时还带入了:
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity`
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenSharingService`
- 主 Manifest 已添加 `tools:node="remove"` 覆盖规则,准备重新打包验证最终合并结果
- 重新打包后release manifest merger 报告已显示:
- `uses-permission#android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION`
- `REJECTED from [io.agora.rtc:full-screen-sharing:4.5.2]`
- 当前 release 中已不再检测到以下声明:
- `android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION`
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity`
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenSharingService`
- 新的正式产物已重新生成:
- `build/app/outputs/bundle/release/app-release.aab`
- 当前 AAB 体积仍约 `181.8MB`
- 新 AAB 证书仍为本地 upload key
- `SHA1: C1:80:AF:BF:6E:1F:F2:F4:49:58:72:87:A2:BC:54:07:E7:D2:D9:A3`
- 本轮按需执行 `flutter build apk --release --split-per-abi --target-platform android-arm64 --split-debug-info=build/symbols/android` 已成功,产物为:
- `build/app/outputs/flutter-apk/app-arm64-v8a-release.apk`
- 当前 `arm64-v8a` APK 体积约 `128.7MB`
- 已核对新旧 `google-services.json`
- 原文件与新文件都匹配包名 `com.org.yumi`
- 下载文件已成功覆盖到 `android/app/google-services.json`
- 当前工程内文件 `SHA256` 为:
- `a1706496a01f74d27e6c60598144cecc978934b02a87567e1ced887b5b0185d5`
## 已知问题
- `ios/Podfile.lock` 还保留旧插件记录,因为本轮未执行 `pod install`;但 Flutter 当前依赖链路已经不再包含已移除插件。
- universal APK 仍然会非常大;当前正确发包方式应优先使用 `--split-per-abi` 或直接产出 `aab`
- 仍有 `12``webp` 被 TinyPNG 拒绝解码,推测是动画或特殊编码格式,不能继续直接走 TinyPNG 常规压缩。
- `split-debug-info` 会把 Dart symbols 额外落到构建目录,发包时需要和正式包一起留档,不能丢。
- iOS 当前验证走的是 `--no-codesign`,因此只产出 `.xcarchive`,不会自动导出可直接分发的 `.ipa`
- Flutter/Xcode 当前给出两条 iOS 提醒:
- 未来 iOS 版本将要求 `UIScene` 生命周期支持
- Launch image 仍是默认占位资源,提交前建议替换
- `android/key.properties` 保存了本地 upload keystore 口令,必须自行妥善备份,且不要提交到仓库
- 由于已显式移除 Agora 本地屏幕共享相关组件,如果业务后续要启用“屏幕共享/录屏推流”,需要再单独恢复相关 manifest 声明
## 下一步要做什么
- 将新的 `AAB` 上传到 Play Console并在首发流程中继续使用 Google 管理的 app signing key。
- 在需要配置 Google 登录、Firebase、支付等生产环境指纹时优先登记 Google 的 `deployment_cert.der` 指纹;如平台要求上传者证书,再额外登记本地 upload key 指纹。
- 如果需要正式 iOS 分发包,为 `scripts/build_release.py` 补入 `--ios-codesign` 所需签名参数并导出 `.ipa`
- 继续评估 Agora 扩展库是否都需要,优先核查 `lip sync``spatial audio``clear vision``segmentation``face capture` 等扩展 so 能否裁剪。
- 决定是否处理剩余 12 张特殊 `webp`:改格式、换压缩工具,或维持现状。