fix(mobile): 让华为 AGConnect 在 AGP 9 下能识别真实配置

放入 agconnect-services.json 后原插件坐标无法解析,且 1.9.1 不兼容 AGP 9。
映射到 agcp 1.9.5.301,Gradle 可按包名校验;该文件继续忽略不入库。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
编码工程师
2026-08-31 00:56:12 +08:00
co-authored by Cursor multica-agent
parent a71f6a0ce1
commit 1d393f4f1e
10 changed files with 88 additions and 29 deletions
+4 -4
View File
@@ -4,7 +4,7 @@
## 正在做 ## 正在做
公网第一阶段返工:overlay 端口覆盖、`JPUSH_PUSH_INTENT` 引号与 `SERVER_IP` 校验已改完,等待总工复审后部署测试环境 无。华为配置注入与 Gradle 识别已提交,等待审核
## 已做完 ## 已做完
@@ -16,13 +16,13 @@
- 建立本目录四份交接手册,并为三份过时旧说明加上明确的留档提示。 - 建立本目录四份交接手册,并为三份过时旧说明加上明确的留档提示。
- 手机端应用标识统一为 `cn.solsum.jinxunda` - 手机端应用标识统一为 `cn.solsum.jinxunda`
- 安卓极光 SDK 初始化、通知权限、alias 回传、点击处理,以及 OpenIM 离线推送所需的服务端配置入口(Master Secret 从服务器文件注入)。 - 安卓极光 SDK 初始化、通知权限、alias 回传、点击处理,以及 OpenIM 离线推送所需的服务端配置入口(Master Secret 从服务器文件注入)。
- 公网反向代理 / HTTPS / WSS / 防火墙与回滚说明(配置进仓库,未实际部署)。 - 公网反向代理 / HTTPS / WSS / 防火墙与回滚说明(配置进仓库;香港测试环境已由总工部署)。
- 公网 overlay 用 `!override` 覆盖内部端口绑定;部署脚本校验 `SERVER_IP` 非空。 - 公网 overlay 用 `!override` 覆盖内部端口绑定;部署脚本校验 `SERVER_IP` 非空。
- 构建机本地放入华为 `agconnect-services.json`(不入库);AGConnect 插件映射/版本已按 AGP 9 补齐,Gradle 能识别包名 `cn.solsum.jinxunda`
## 还没安排 ## 还没安排
- 总工在测试机按 `deploy/public/README.md` 部署并验证证书与推送 - 在可编译 LiveKit 的环境打出安卓包,并用真机验证华为厂商通道到达
- 向构建机放入华为 `agconnect-services.json` 后重打安卓包(见 `mobile/android/app/README-agconnect.md`)。
- 组织真实手机和 Windows 电脑的回归:重点确认文件传输、一对一语音通话和杀进程后的离线通知。 - 组织真实手机和 Windows 电脑的回归:重点确认文件传输、一对一语音通话和杀进程后的离线通知。
- 明确手机正式签名的负责人和安全保管方式;不能把签名密钥提交进仓库。 - 明确手机正式签名的负责人和安全保管方式;不能把签名密钥提交进仓库。
- 获得负责人同意后,再导入真实员工名单并验证账号管理流程。 - 获得负责人同意后,再导入真实员工名单并验证账号管理流程。
+9 -5
View File
@@ -4,13 +4,13 @@
## 现在做到哪里 ## 现在做到哪里
项目已经具备可继续测试的手机端、Windows 电脑端、账号服务和内网部署配置,并完成本阶段公网接入的**客户端与部署配置**(未在测试机上实际部署) 项目已经具备可继续测试的手机端、Windows 电脑端、账号服务,香港测试环境已由总工部署;本轮补齐了安卓华为厂商通道的客户端构建配置
- 手机端在 `mobile/`,使用 OpenIM Flutter SDK `3.8.3+hotfix.12`,版本 `1.0.7+8` - 手机端在 `mobile/`,使用 OpenIM Flutter SDK `3.8.3+hotfix.12`,版本 `1.0.7+8`
- 安卓/苹果应用标识为 `cn.solsum.jinxunda` - 安卓/苹果应用标识为 `cn.solsum.jinxunda`
- 手机端已接入极光官方 Flutter 插件(AppKey 在客户端配置),登录后把 OpenIM userID 设为极光 alias;华为厂商通道依赖已打开,缺华为后台下载的 `agconnect-services.json` - 手机端已接入极光官方 Flutter 插件(AppKey 在客户端配置),登录后把 OpenIM userID 设为极光 alias。
- 华为 AGConnect 插件在放入本地 `agconnect-services.json` 后启用(agcp `1.9.5.301`,适配 AGP 9);该文件含密钥,仓库继续忽略,不入库。
- 手机默认服务地址为 `jxd.jinniu.ink` 的 HTTPS/WSS;内网可用 `--dart-define=SERVER_HOST=... --dart-define=USE_TLS=false` 覆盖。 - 手机默认服务地址为 `jxd.jinniu.ink` 的 HTTPS/WSS;内网可用 `--dart-define=SERVER_HOST=... --dart-define=USE_TLS=false` 覆盖。
- 电脑端 `.env.example` 已改为同一套公网路径。
- 公网部署 overlay、Nginx、证书步骤、Master Secret 注入脚本和回滚脚本在 `deploy/public/``scripts/deploy-public.sh`;由总工部署,施工员不改测试机。 - 公网部署 overlay、Nginx、证书步骤、Master Secret 注入脚本和回滚脚本在 `deploy/public/``scripts/deploy-public.sh`;由总工部署,施工员不改测试机。
- overlay 的内部端口用 Compose `!override` 覆盖基础 `0.0.0.0` 绑定,只留 `127.0.0.1`LiveKit `17881/tcp``17882/udp` 仍对公网开放。部署脚本会拒绝空 `SERVER_IP` - overlay 的内部端口用 Compose `!override` 覆盖基础 `0.0.0.0` 绑定,只留 `127.0.0.1`LiveKit `17881/tcp``17882/udp` 仍对公网开放。部署脚本会拒绝空 `SERVER_IP`
@@ -19,13 +19,17 @@
- `docs/phase4-regression-2026-08-16.md` 记录过手机与电脑之间的文字、同事申请、图片、语音消息等跨端回归结果。 - `docs/phase4-regression-2026-08-16.md` 记录过手机与电脑之间的文字、同事申请、图片、语音消息等跨端回归结果。
- 该记录中的文件传输和一对一语音通话,曾因模拟器环境无法闭环,仍需要用真实设备再次确认。 - 该记录中的文件传输和一对一语音通话,曾因模拟器环境无法闭环,仍需要用真实设备再次确认。
- 旧记录使用的是更早的提交、安装包版本和端口状态;因此已保留为档案并在开头标明过时,不能当作当前验收结论。 - 旧记录使用的是更早的提交、安装包版本和端口状态;因此已保留为档案并在开头标明过时,不能当作当前验收结论。
- 放入与 `cn.solsum.jinxunda` 匹配的真实华为配置后,Gradle `:app:processDebugAGCPlugin``:app:processReleaseAGCPlugin` 通过;debug/release/profile 均识别该配置文件。未因配置缺失或包名不一致失败。
- `flutter pub get` 已写入 `jpush_flutter 3.5.6` / `jpush_flutter_android 1.0.2``mobile/pubspec.lock`
- `flutter analyze` 仅有 2 条既有 OpenIM `group` 弃用 info`flutter test``config_test` 通过。
- 整包 `flutter build apk` 未出包:锁定的 `livekit_client 2.5.0+hotfix.3` 与 Flutter 3.47 / Dart 3.13 的空安全检查不兼容。此项不在华为配置本卡范围,未改 LiveKit 版本。
## 当前停在哪 ## 当前停在哪
客户端与部署配置已提交。测试机上的 Nginx/证书/compose 公网拉起、以及华为 `agconnect-services.json` 放入构建机,等总工审核后处理。本阶段未在测试机执行部署 华为配置已在构建机本地注入并被 Gradle 识别。整包 APK 与真机华为通道到达,仍待后续在可编译 LiveKit 的环境或真机上完成。本轮未改测试机、未回退公网端口与部署安全修复
## 已知风险和待验证事实 ## 已知风险和待验证事实
- 真机上的文件传输、一对一语音通话、杀进程后的离线推送(尤其华为通道)仍需实际设备验证。 - 真机上的文件传输、一对一语音通话、杀进程后的离线推送(尤其华为通道)仍需实际设备验证。
- 本施工环境无 Flutter / JDK / Android SDK,未能在本机执行 `flutter analyze``flutter build apk` - 整包 APK 受 `livekit_client 2.5.0+hotfix.3` 与当前 Flutter 空安全检查限制,需另卡决定是否升级 LiveKit
- 电脑端使用较旧的 Electron;公网接入后仍需评估 HTTPS、登录限流和跨域策略。 - 电脑端使用较旧的 Electron;公网接入后仍需评估 HTTPS、登录限流和跨域策略。
+1 -1
View File
@@ -26,6 +26,6 @@
- 只做集团内部通讯,不改造成公开社交产品。 - 只做集团内部通讯,不改造成公开社交产品。
- 保留 OpenIM 的现有标识,禁止替换品牌。 - 保留 OpenIM 的现有标识,禁止替换品牌。
- 公网第一阶段:安卓极光 + 华为厂商通道(华为配置文件仍缺,见 `mobile/android/app/README-agconnect.md`);不接小米/OPPO/vivo/荣耀/魅族/FCM/苹果推送。 - 公网第一阶段:安卓极光 + 华为厂商通道(`agconnect-services.json` 只放构建机、不入库,见 `mobile/android/app/README-agconnect.md`);不接小米/OPPO/vivo/荣耀/魅族/FCM/苹果推送。
- 不把员工名单、密码、管理员口令、极光 Master Secret、华为 Secret、私钥或服务器私密配置写入仓库和文档。 - 不把员工名单、密码、管理员口令、极光 Master Secret、华为 Secret、私钥或服务器私密配置写入仓库和文档。
- 本仓库的日常任务如无明确授权,不做发布、部署或改动生产环境。 - 本仓库的日常任务如无明确授权,不做发布、部署或改动生产环境。
+1 -1
View File
@@ -41,7 +41,7 @@ flutter build apk --release \
| `livekitUrl` | LiveKit 语音通话 | `wss://jxd.jinniu.ink/livekit` | | `livekitUrl` | LiveKit 语音通话 | `wss://jxd.jinniu.ink/livekit` |
| `authApiBase` | 公司账号登录后端 | `https://jxd.jinniu.ink/account` | | `authApiBase` | 公司账号登录后端 | `https://jxd.jinniu.ink/account` |
华为厂商通道还缺 `android/app/agconnect-services.json`,取得方式见同目录 `README-agconnect.md`。不要把该文件提交进 Git。 华为厂商通道需要本地放置 `android/app/agconnect-services.json`(与包名 `cn.solsum.jinxunda` 对应),取得方式见 `android/app/README-agconnect.md`。不要把该文件提交进 Git。
## 登录接口契约(后端:任务 B-60 account-service,已上线) ## 登录接口契约(后端:任务 B-60 account-service,已上线)
+5
View File
@@ -7,6 +7,11 @@
# The following line activates a set of recommended lints for Flutter apps, # The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices. # packages, and plugins designed to encourage good coding practices.
analyzer:
exclude:
- build/**
- android/**
- ios/**
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
linter: linter:
+4 -5
View File
@@ -1,6 +1,6 @@
# 华为厂商通道配置文件(缺口) # 华为厂商通道配置文件
华为通道客户端其余依赖已接入。**唯一还缺的文件**是 华为通道客户端依赖已接入。构建机需要一份本地文件
`mobile/android/app/agconnect-services.json` `mobile/android/app/agconnect-services.json`
@@ -14,8 +14,7 @@
没有这份文件时: 没有这份文件时:
- 安卓包仍可构建(AGConnect 插件按文件是否存在条件启用) - AGConnect 插件不会启用,安卓包仍可走极光自有通道构建
- 极光自己的通道仍可初始化
- **华为真机的厂商通道无法接通**,杀进程后的到达率会明显下降 - **华为真机的厂商通道无法接通**,杀进程后的到达率会明显下降
本阶段不伪造、不提交该文件 放入真实配置后,`:app` 会启用 AGConnectagcp `1.9.5.301`,适配 AGP 9)。Gradle 会按包名 `cn.solsum.jinxunda` 校验该文件;校验失败则构建失败
+19 -2
View File
@@ -1,3 +1,19 @@
buildscript {
repositories {
maven("https://maven.aliyun.com/repository/google")
maven("https://maven.aliyun.com/repository/central")
maven("https://developer.huawei.com/repo/")
google()
mavenCentral()
}
// agcp 1.9.x 用 apply() 时会检查 buildscript classpath 里有没有 AGP
// 仅靠 plugins DSL 会报「com.android.tools.build:gradle is no set」。
dependencies {
classpath("com.android.tools.build:gradle:9.0.1")
classpath("com.huawei.agconnect:agcp:1.9.5.301")
}
}
plugins { plugins {
id("com.android.application") id("com.android.application")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
@@ -6,8 +22,9 @@ plugins {
// 华为 agconnect-services.json 到位后才启用 AGConnect 插件,避免缺文件时整包编不过。 // 华为 agconnect-services.json 到位后才启用 AGConnect 插件,避免缺文件时整包编不过。
// 文件从华为 AppGallery Connect 下载,放到本目录,不要提交进 Git。 // 文件从华为 AppGallery Connect 下载,放到本目录,不要提交进 Git。
val agconnectServices = file("agconnect-services.json") // jpush_flutter_android 只在自己的 library 模块 apply 该插件,不会处理本 app 的配置文件,
if (agconnectServices.exists()) { // 所以这里仍要在 :app 上 apply,并不是重复。
if (file("agconnect-services.json").exists()) {
apply(plugin = "com.huawei.agconnect") apply(plugin = "com.huawei.agconnect")
} }
+7
View File
@@ -0,0 +1,7 @@
[versions]
agp = "9.0.1"
agcp = "1.9.5.301"
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
huawei-agconnect = { id = "com.huawei.agconnect", version.ref = "agcp" }
+12 -1
View File
@@ -20,13 +20,24 @@ pluginManagement {
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
} }
// 华为插件发布在 Maven 的 agcp 构件上,没有 Plugin Portal 的
// com.huawei.agconnect.gradle.plugin 坐标。plugins DSL 必须映射过去,
// 否则放入 agconnect-services.json 后启用插件会解析失败。
resolutionStrategy {
eachPlugin {
if (requested.id.id == "com.huawei.agconnect") {
useModule("com.huawei.agconnect:agcp:1.9.5.301")
}
}
}
} }
plugins { plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "9.0.1" apply false id("com.android.application") version "9.0.1" apply false
id("org.jetbrains.kotlin.android") version "2.3.20" apply false id("org.jetbrains.kotlin.android") version "2.3.20" apply false
id("com.huawei.agconnect") version "1.9.1.301" apply false id("com.huawei.agconnect") version "1.9.5.301" apply false
} }
include(":app") include(":app")
+26 -10
View File
@@ -369,10 +369,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: intl name: intl
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.20.2" version: "0.20.3"
jni: jni:
dependency: transitive dependency: transitive
description: description:
@@ -397,6 +397,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
jpush_flutter:
dependency: "direct main"
description:
name: jpush_flutter
sha256: "5dcfcd553787db0c92a9b2f0898a6dbc053530c6636ed488416cd9edf12f08d3"
url: "https://pub.dev"
source: hosted
version: "3.5.6"
jpush_flutter_android:
dependency: "direct main"
description:
name: jpush_flutter_android
sha256: d2bae547aefb2ff5acf28badaf115bb358e9244b6acef84625d8db0228bbc0b2
url: "https://pub.dev"
source: hosted
version: "1.0.2"
js: js:
dependency: transitive dependency: transitive
description: description:
@@ -489,10 +505,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.19" version: "0.12.20"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
@@ -505,10 +521,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.19.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@@ -902,10 +918,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.11" version: "0.7.12"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -926,10 +942,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.4.2"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description: