Agent 更新(二):Agent 端检查、下载与安装引导 #144

Open
opened 2026-08-29 09:12:42 +08:00 by ila · 3 comments
Owner

所属与来源

  • 关联工单:#143 版本发布与查询(前置)。
  • 来源:用户于 2026-08-29 提出「增加 Agent App 更新功能」,并要求方案最简单易用。
  • 类型:Android Agent / 应用更新检查、下载与安装引导。
  • 设计证据:在既有设置页新增一块版本信息与一个按钮,不新增页面与导航;提供标注截图或复用现有规范即可,不需要完整原型。
  • 工具回退说明:本工单通过 Gitea API 创建;当前会话未提供 Gitea MCP 工具,按 AGENTS.md「Gitea 交互与工单最小读取」记录回退原因。

当前事实(提交 30d8238 复核)

  • android/app/src/main/AndroidManifest.xml 现有权限为 INTERNET、ACCESS_NETWORK_STATE、FOREGROUND_SERVICE、FOREGROUND_SERVICE_DATA_SYNC、WAKE_LOCK、POST_NOTIFICATIONS,没有 REQUEST_INSTALL_PACKAGES,也没有配置 FileProvider。
  • minSdk = 23、targetSdk = 34、当前 versionName = 0.9.12(android/app/build.gradle.kts)。
  • Agent 已有设置页 AgentSettingsFragment 与设备忙判断(AgentStateStore 的活动任务、采集冷却)。

关键前提:无法静默安装

Android 上静默安装需要系统签名或 root,普通 APK 做不到。可实现的上限是:下载 APK 后调起系统安装确认界面,由用户点击「安装」。

既然最后一步必须由人确认,后台自动下载、定时检查、强制更新等自动化的收益有限,反而增加状态与失败模式。因此更新采用手动触发。

目标

  1. 用户可在设置页主动检查更新,有新版本时下载并进入系统安装流程。
  2. App 启动时静默检查一次,有新版本仅以轻量标记提示,不弹窗、不打扰。
  3. 设备正在执行任务时不提示、不允许下载安装。
  4. 下载包完整性可校验。

非目标

  • 不做自动/静默安装、强制更新、后台自动下载。
  • 不做灰度发布、按设备分组、差分包更新。
  • 不做「更新失败自动回滚」——回滚由 Admin 将当前版本指针指回旧版本实现(#143)。
  • 不修改心跳、任务调度、采集与采购逻辑。
  • 不新增页面与导航。

实施方案

一、Manifest 与权限

  1. 新增 REQUEST_INSTALL_PACKAGES 权限。
  2. 配置 FileProvider:Android 7+ 不允许以 file:// 传递 APK 路径,必须通过 FileProvider 授予临时读权限。
  3. 首次安装时系统会要求用户允许「安装未知应用」,需在界面上明确引导;被拒绝时给出可读提示并允许重试,不得静默失败。

二、检查更新

  1. 调用 #143 的 GET /api/agent/v1/app/latest(设备 token 鉴权)。
  2. 版本比较一律使用 versionCode(整数),不得使用 versionName 字符串比较——字符串比较会在 0.9.9 与 0.9.10 上得出错误结论。
  3. 触发时机:
    • 设置页「检查更新」按钮,手动触发,展示结果;
    • App 启动时静默检查一次,有新版本仅在设置页对应条目显示轻量标记(如小红点),不弹窗。
  4. 服务端返回无发布版本或请求失败时,静默检查不打扰用户;手动检查给出可读提示。

三、下载与安装

  1. 下载到应用私有目录,显示进度,可取消。
  2. 下载完成后校验 SHA-256,与接口返回值不一致时删除文件并明确失败,不得安装。
  3. 校验通过后经 FileProvider 调起系统安装界面。
  4. 安装结果由系统与用户决定;Agent 不追踪安装是否成功,也不重复弹出。

四、业务约束

  1. 设备正在执行任务时不提示更新、不允许下载与安装,复用既有的活动任务判断。采集或采购执行到一半被安装中断会导致任务失败。
  2. 更新相关操作不得影响前台服务、任务租约与心跳。

五、界面

  1. 设置页新增一块,内容为:当前版本号、「检查更新」按钮。
  2. 有新版本时展示新版本号与更新说明,并提供「下载并安装」按钮。
  3. 文案保持简短,不新增引导页与说明块。

安全边界

  • 只安装从服务端下载并通过 SHA-256 校验的包,不接受任何其他来源。
  • 下载请求携带设备 token;不在日志中记录 token 与下载地址明文。
  • 不请求与更新无关的新权限。
  • 设备执行任务期间禁止安装,避免中断任务与租约异常。

验收标准

  • 设置页可手动检查更新,已是最新时提示明确。
  • 有新版本时展示版本号与更新说明,可下载并进入系统安装界面。
  • 版本比较使用 versionCode;构造 0.9.9 → 0.9.10 场景验证结论正确。
  • SHA-256 不一致时删除文件并明确失败,不进入安装流程。
  • 未授予「安装未知应用」权限时给出可读引导,授予后可继续,不静默失败。
  • 设备有进行中的任务时,不显示更新入口或明确拒绝,且不影响任务执行。
  • App 启动时的静默检查不弹窗;服务端无发布版本或请求失败时不打扰用户。
  • 更新过程不影响前台服务、心跳与任务租约。
  • 低于 Android 8 的设备上权限与安装流程行为明确(可用或明确不支持,实施时说明)。

验证方式

  • cd android && .\gradlew.bat :app:testDebugUnitTest :app:assembleDebug
  • 版本比较与 SHA-256 校验的纯函数单元测试。
  • 真机 PKG110:完整走一次「检查 → 下载 → 校验 → 安装」;另验证校验失败、权限未授予、设备忙三条异常路径。
  • 真机、多设备、不同 Android 版本与异常路径未覆盖部分如实回写。

依赖、并行与风险

  • 前置依赖 #143:接口定稿后实施;UI 部分可先行开发。
  • 风险:部分 ROM 对未知来源安装有额外限制。缓解:失败时给出可读提示,不静默;真机验证覆盖当前设备。
  • 风险:安装过程会重启 App,进行中的任务会中断。缓解:第 12 项的设备忙约束。
  • 回退:还原提交即可;服务端发布记录不受影响。

文档影响

  • Wiki Local-Development-and-Verification 或 Deployment-and-Operations:Agent 更新的操作步骤与权限前提。
  • Wiki Android-Agent-API-Contract:如 #143 已完整记录查询接口,本工单只补充客户端行为说明。
  • 按 Wiki-first 门禁:如需更新,先改线上页面并回读 revision,再执行一轮 sync 与一轮 sync --check,把页面与 revision 写回本工单。

状态

待实施(前置 #143)。

## 所属与来源 - 关联工单:#143 版本发布与查询(前置)。 - 来源:用户于 2026-08-29 提出「增加 Agent App 更新功能」,并要求方案最简单易用。 - 类型:Android Agent / 应用更新检查、下载与安装引导。 - 设计证据:在既有设置页新增一块版本信息与一个按钮,不新增页面与导航;提供标注截图或复用现有规范即可,不需要完整原型。 - 工具回退说明:本工单通过 Gitea API 创建;当前会话未提供 Gitea MCP 工具,按 `AGENTS.md`「Gitea 交互与工单最小读取」记录回退原因。 ## 当前事实(提交 30d8238 复核) - `android/app/src/main/AndroidManifest.xml` 现有权限为 INTERNET、ACCESS_NETWORK_STATE、FOREGROUND_SERVICE、FOREGROUND_SERVICE_DATA_SYNC、WAKE_LOCK、POST_NOTIFICATIONS,**没有 `REQUEST_INSTALL_PACKAGES`,也没有配置 FileProvider**。 - `minSdk = 23`、`targetSdk = 34`、当前 `versionName = 0.9.12`(`android/app/build.gradle.kts`)。 - Agent 已有设置页 `AgentSettingsFragment` 与设备忙判断(`AgentStateStore` 的活动任务、采集冷却)。 ## 关键前提:无法静默安装 Android 上静默安装需要系统签名或 root,普通 APK 做不到。可实现的上限是:下载 APK 后调起系统安装确认界面,由用户点击「安装」。 既然最后一步必须由人确认,后台自动下载、定时检查、强制更新等自动化的收益有限,反而增加状态与失败模式。**因此更新采用手动触发。** ## 目标 1. 用户可在设置页主动检查更新,有新版本时下载并进入系统安装流程。 2. App 启动时静默检查一次,有新版本仅以轻量标记提示,不弹窗、不打扰。 3. 设备正在执行任务时不提示、不允许下载安装。 4. 下载包完整性可校验。 ## 非目标 - 不做自动/静默安装、强制更新、后台自动下载。 - 不做灰度发布、按设备分组、差分包更新。 - 不做「更新失败自动回滚」——回滚由 Admin 将当前版本指针指回旧版本实现(#143)。 - 不修改心跳、任务调度、采集与采购逻辑。 - 不新增页面与导航。 ## 实施方案 ### 一、Manifest 与权限 1. 新增 `REQUEST_INSTALL_PACKAGES` 权限。 2. 配置 FileProvider:Android 7+ 不允许以 `file://` 传递 APK 路径,必须通过 FileProvider 授予临时读权限。 3. 首次安装时系统会要求用户允许「安装未知应用」,需在界面上明确引导;被拒绝时给出可读提示并允许重试,不得静默失败。 ### 二、检查更新 4. 调用 #143 的 `GET /api/agent/v1/app/latest`(设备 token 鉴权)。 5. **版本比较一律使用 `versionCode`(整数),不得使用 `versionName` 字符串比较**——字符串比较会在 `0.9.9` 与 `0.9.10` 上得出错误结论。 6. 触发时机: - 设置页「检查更新」按钮,手动触发,展示结果; - App 启动时静默检查一次,有新版本仅在设置页对应条目显示轻量标记(如小红点),不弹窗。 7. 服务端返回无发布版本或请求失败时,静默检查不打扰用户;手动检查给出可读提示。 ### 三、下载与安装 8. 下载到应用私有目录,显示进度,可取消。 9. **下载完成后校验 SHA-256**,与接口返回值不一致时删除文件并明确失败,不得安装。 10. 校验通过后经 FileProvider 调起系统安装界面。 11. 安装结果由系统与用户决定;Agent 不追踪安装是否成功,也不重复弹出。 ### 四、业务约束 12. **设备正在执行任务时不提示更新、不允许下载与安装**,复用既有的活动任务判断。采集或采购执行到一半被安装中断会导致任务失败。 13. 更新相关操作不得影响前台服务、任务租约与心跳。 ### 五、界面 14. 设置页新增一块,内容为:当前版本号、「检查更新」按钮。 15. 有新版本时展示新版本号与更新说明,并提供「下载并安装」按钮。 16. 文案保持简短,不新增引导页与说明块。 ## 安全边界 - 只安装从服务端下载并通过 SHA-256 校验的包,不接受任何其他来源。 - 下载请求携带设备 token;不在日志中记录 token 与下载地址明文。 - 不请求与更新无关的新权限。 - 设备执行任务期间禁止安装,避免中断任务与租约异常。 ## 验收标准 - [ ] 设置页可手动检查更新,已是最新时提示明确。 - [ ] 有新版本时展示版本号与更新说明,可下载并进入系统安装界面。 - [ ] 版本比较使用 `versionCode`;构造 `0.9.9` → `0.9.10` 场景验证结论正确。 - [ ] SHA-256 不一致时删除文件并明确失败,不进入安装流程。 - [ ] 未授予「安装未知应用」权限时给出可读引导,授予后可继续,不静默失败。 - [ ] 设备有进行中的任务时,不显示更新入口或明确拒绝,且不影响任务执行。 - [ ] App 启动时的静默检查不弹窗;服务端无发布版本或请求失败时不打扰用户。 - [ ] 更新过程不影响前台服务、心跳与任务租约。 - [ ] 低于 Android 8 的设备上权限与安装流程行为明确(可用或明确不支持,实施时说明)。 ## 验证方式 - `cd android && .\gradlew.bat :app:testDebugUnitTest :app:assembleDebug` - 版本比较与 SHA-256 校验的纯函数单元测试。 - 真机 PKG110:完整走一次「检查 → 下载 → 校验 → 安装」;另验证校验失败、权限未授予、设备忙三条异常路径。 - 真机、多设备、不同 Android 版本与异常路径未覆盖部分如实回写。 ## 依赖、并行与风险 - **前置依赖 #143**:接口定稿后实施;UI 部分可先行开发。 - 风险:部分 ROM 对未知来源安装有额外限制。缓解:失败时给出可读提示,不静默;真机验证覆盖当前设备。 - 风险:安装过程会重启 App,进行中的任务会中断。缓解:第 12 项的设备忙约束。 - 回退:还原提交即可;服务端发布记录不受影响。 ## 文档影响 - Wiki `Local-Development-and-Verification` 或 `Deployment-and-Operations`:Agent 更新的操作步骤与权限前提。 - Wiki `Android-Agent-API-Contract`:如 #143 已完整记录查询接口,本工单只补充客户端行为说明。 - 按 Wiki-first 门禁:如需更新,先改线上页面并回读 revision,再执行一轮 `sync` 与一轮 `sync --check`,把页面与 revision 写回本工单。 ## 状态 待实施(前置 #143)。
Author
Owner

#144 v1 标注稿待确认(依赖 #143)

本版复用 Agent 现有设置页卡片和 ≥48dp 按钮规范,覆盖手动检查、静默提示、新版本、下载进度/取消、设备忙禁用、SHA-256 校验失败和未知来源安装权限引导。#143 接口和迁移尚未实施,因此本工单保持待实施。

## #144 v1 标注稿待确认(依赖 #143) - 设计证据:[查看 #143 + #144 v1 标注稿](https://git.ilapage.cn/attachments/62bcf714-0522-42b0-905a-8f98b9fe7547) - 版本识别:`GoAuto #143 + #144 v1` - 状态:待用户确认 本版复用 Agent 现有设置页卡片和 ≥48dp 按钮规范,覆盖手动检查、静默提示、新版本、下载进度/取消、设备忙禁用、SHA-256 校验失败和未知来源安装权限引导。#143 接口和迁移尚未实施,因此本工单保持待实施。
Author
Owner

用户于 2026-08-29 明确确认 #143 + #144 v1 标注稿。#144 在 #143 接口完成后实施 Agent 设置页手动检查、校验下载和系统安装引导;任务执行中禁止更新,不做静默安装或强制更新。

用户于 2026-08-29 明确确认 `#143 + #144 v1` 标注稿。#144 在 #143 接口完成后实施 Agent 设置页手动检查、校验下载和系统安装引导;任务执行中禁止更新,不做静默安装或强制更新。
Author
Owner

已按已确认的 #143+#144 v1 实施并推送,现转待验收。

实现:

  • Agent 升级为 versionCode 41 / versionName 0.9.28。
  • 启动后每版本静默检查一次;设置页支持手动检查、显示可用版本、鉴权下载进度/取消及发起系统安装确认。
  • 下载完成强制校验期望大小与 SHA-256,任何失败都会删除临时 APK。
  • 采集/采购忙碌或存在 currentTaskId 时禁止检查、下载和安装;未知来源权限缺失时跳转系统授权页。
  • 仅通过 Android 系统安装确认,不支持静默安装;启动检查不影响前台服务和心跳。

提交:5684510;共享文档:1ec895b。
验证:Android testDebugUnitTest assembleDebug 通过,升级策略单测通过;Server/API 相关测试、Web 生产构建及 DevHarness strict check 通过。

边界:未发布或安装 APK,未做真机升级链路验证;需要先由 #143 完成迁移、上传并设为当前版本,再单独授权安装/真机验收。

已按已确认的 #143+#144 v1 实施并推送,现转待验收。 实现: - Agent 升级为 versionCode 41 / versionName 0.9.28。 - 启动后每版本静默检查一次;设置页支持手动检查、显示可用版本、鉴权下载进度/取消及发起系统安装确认。 - 下载完成强制校验期望大小与 SHA-256,任何失败都会删除临时 APK。 - 采集/采购忙碌或存在 currentTaskId 时禁止检查、下载和安装;未知来源权限缺失时跳转系统授权页。 - 仅通过 Android 系统安装确认,不支持静默安装;启动检查不影响前台服务和心跳。 提交:5684510;共享文档:1ec895b。 验证:Android testDebugUnitTest assembleDebug 通过,升级策略单测通过;Server/API 相关测试、Web 生产构建及 DevHarness strict check 通过。 边界:未发布或安装 APK,未做真机升级链路验证;需要先由 #143 完成迁移、上传并设为当前版本,再单独授权安装/真机验收。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#144