diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index fd4636f..c629d41 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -11,8 +11,8 @@ android { applicationId = "cn.ilapage.goauto.agent" minSdk = 23 targetSdk = 34 - versionCode = 27 - versionName = "0.9.14" + versionCode = 28 + versionName = "0.9.15" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/android/app/src/main/java/cn/ilapage/goauto/agent/service/AgentForegroundService.kt b/android/app/src/main/java/cn/ilapage/goauto/agent/service/AgentForegroundService.kt index 5ea88bb..d8fb337 100644 --- a/android/app/src/main/java/cn/ilapage/goauto/agent/service/AgentForegroundService.kt +++ b/android/app/src/main/java/cn/ilapage/goauto/agent/service/AgentForegroundService.kt @@ -739,6 +739,7 @@ class AgentForegroundService : Service() { private fun beginIdleReturnCooldown() { val accessibility = GoAutoAccessibilityService.instance ?: return + val cooldownSeconds = IdleReturnCoordinator.DEFAULT_COOLDOWN_SECONDS val armed = idleReturn.arm( nowMillis = SystemClock.elapsedRealtime(), packageName = accessibility.currentPackage(), @@ -746,7 +747,7 @@ class AgentForegroundService : Service() { ) if (!armed) return acquireCooldownWakeLock() - stateStore.update("ONLINE", "任务已结束,15 秒内无新任务将返回 Agent", tokenStored = true) + stateStore.update("ONLINE", "任务已结束,${cooldownSeconds} 秒内无新任务将返回 Agent", tokenStored = true) updateNotification("任务已结束 · 等待新任务") publishScreenPolicy() executor.schedule(::triggerSync, IdleReturnCoordinator.DEFAULT_COOLDOWN_MILLIS, TimeUnit.MILLISECONDS) @@ -849,7 +850,7 @@ class AgentForegroundService : Service() { if (launched) SystemClock.sleep(RETURN_CONFIRM_DELAY_MILLIS) val returned = launched && accessibility.currentPackage() == packageName finishIdleReturn( - if (returned) "15 秒内无新任务,已返回 Agent" + if (returned) "${IdleReturnCoordinator.DEFAULT_COOLDOWN_SECONDS} 秒内无新任务,已返回 Agent" else "任务已结束;系统限制自动返回,请手动打开 Agent", ) } diff --git a/android/app/src/main/java/cn/ilapage/goauto/agent/service/IdleReturnCoordinator.kt b/android/app/src/main/java/cn/ilapage/goauto/agent/service/IdleReturnCoordinator.kt index c4043a4..5c419bc 100644 --- a/android/app/src/main/java/cn/ilapage/goauto/agent/service/IdleReturnCoordinator.kt +++ b/android/app/src/main/java/cn/ilapage/goauto/agent/service/IdleReturnCoordinator.kt @@ -66,7 +66,8 @@ class IdleReturnCoordinator( ) companion object { - const val DEFAULT_COOLDOWN_MILLIS = 15_000L + const val DEFAULT_COOLDOWN_SECONDS = 5L + const val DEFAULT_COOLDOWN_MILLIS = DEFAULT_COOLDOWN_SECONDS * 1_000L } } diff --git a/android/app/src/test/java/cn/ilapage/goauto/agent/AgentStatusTextPolicyTest.kt b/android/app/src/test/java/cn/ilapage/goauto/agent/AgentStatusTextPolicyTest.kt index 1e166fe..50ac289 100644 --- a/android/app/src/test/java/cn/ilapage/goauto/agent/AgentStatusTextPolicyTest.kt +++ b/android/app/src/test/java/cn/ilapage/goauto/agent/AgentStatusTextPolicyTest.kt @@ -13,8 +13,8 @@ class AgentStatusTextPolicyTest { AgentStatusTextPolicy.connectionDetail("ONLINE", "设备在线空闲", "刚刚"), ) assertEquals( - "任务已结束,15 秒内无新任务将返回 Agent\n最近心跳:刚刚", - AgentStatusTextPolicy.connectionDetail("ONLINE", "任务已结束,15 秒内无新任务将返回 Agent", "刚刚"), + "任务已结束,5 秒内无新任务将返回 Agent\n最近心跳:刚刚", + AgentStatusTextPolicy.connectionDetail("ONLINE", "任务已结束,5 秒内无新任务将返回 Agent", "刚刚"), ) assertEquals( "设备在线空闲\n最近心跳:刚刚", diff --git a/android/app/src/test/java/cn/ilapage/goauto/agent/IdleReturnCoordinatorTest.kt b/android/app/src/test/java/cn/ilapage/goauto/agent/IdleReturnCoordinatorTest.kt index e93feb9..1bbec85 100644 --- a/android/app/src/test/java/cn/ilapage/goauto/agent/IdleReturnCoordinatorTest.kt +++ b/android/app/src/test/java/cn/ilapage/goauto/agent/IdleReturnCoordinatorTest.kt @@ -12,14 +12,15 @@ class IdleReturnCoordinatorTest { @Test fun `returns only after cooldown and successful empty queue confirmation`() { val coordinator = IdleReturnCoordinator() + assertEquals(5_000L, IdleReturnCoordinator.DEFAULT_COOLDOWN_MILLIS) assertTrue(coordinator.arm(1_000L, "com.xunmeng.pinduoduo", 7L)) assertEquals( IdleReturnDecision.WAITING, - coordinator.evaluate(15_999L, true, true, "com.xunmeng.pinduoduo", 7L), + coordinator.evaluate(5_999L, true, true, "com.xunmeng.pinduoduo", 7L), ) assertEquals( IdleReturnDecision.READY, - coordinator.evaluate(16_000L, true, true, "com.xunmeng.pinduoduo", 7L), + coordinator.evaluate(6_000L, true, true, "com.xunmeng.pinduoduo", 7L), ) assertFalse(coordinator.isArmed()) } @@ -30,7 +31,7 @@ class IdleReturnCoordinatorTest { coordinator.arm(0L, "com.xunmeng.pinduoduo", 3L) assertEquals( IdleReturnDecision.CANCELLED, - coordinator.evaluate(15_000L, true, true, "com.xunmeng.pinduoduo", 5L), + coordinator.evaluate(5_000L, true, true, "com.xunmeng.pinduoduo", 5L), ) } @@ -39,12 +40,12 @@ class IdleReturnCoordinatorTest { val withTask = IdleReturnCoordinator().apply { arm(0L, "com.android.chrome", 1L) } assertEquals( IdleReturnDecision.CANCELLED, - withTask.evaluate(15_000L, false, true, "com.android.chrome", 1L), + withTask.evaluate(5_000L, false, true, "com.android.chrome", 1L), ) val unsafe = IdleReturnCoordinator().apply { arm(0L, "com.android.chrome", 1L) } assertEquals( IdleReturnDecision.CANCELLED, - unsafe.evaluate(15_000L, true, false, "com.android.chrome", 1L), + unsafe.evaluate(5_000L, true, false, "com.android.chrome", 1L), ) } diff --git a/docs/02-architecture-and-code-map.md b/docs/02-architecture-and-code-map.md index e0304ce..34850a5 100644 --- a/docs/02-architecture-and-code-map.md +++ b/docs/02-architecture-and-code-map.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Architecture-and-Code-Map wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Architecture-and-Code-Map.- -wiki_revision: 6ed5b970878ff0211946fbba02c64eaccfe8d8bb -synchronized_at: 2026-08-28T02:17:40Z +wiki_revision: 340505ae259dc7bfae74f991e0fb72ad0daeabe9 +synchronized_at: 2026-08-28T06:14:21Z # 架构与代码地图 @@ -161,7 +161,7 @@ Android Portal/Agent ## Android Agent 任务结束冷却与返回(#89) -- `AgentForegroundService` 在采集结果已提交,或采购结果与 Outbox 已在同一事务安全保存后,建立 15 秒任务结束冷却;不新增第二套队列轮询器。 +- `AgentForegroundService` 在采集结果已提交,或采购结果与 Outbox 已在同一事务安全保存后,建立 5 秒任务结束冷却;不新增第二套队列轮询器。 - 冷却到期仍由现有任务轮询按“采购优先、再采集”依次确认两个队列都为空。任何新任务、网络/服务端异常或本地未解除的不可逆采购边界都会取消返回。 - `IdleReturnCoordinator` 只保存冷却时间、自动化前台包名与无障碍前台切换序号,不保存控件树或截图。用户切换到其他 App 后,即使又返回 PDD,也不会被强制拉回 Agent。 - 返回请求只允许从 Agent 本次自动化停留的 PDD 或受支持浏览器页面发起,并由无障碍服务打开 `MainActivity` 状态 Tab;Android 后台 Activity 启动限制导致失败时只提示手动打开,不重复强拉。 @@ -189,7 +189,7 @@ Android Portal/Agent ## Android 系统辅助功能按钮(#97) - Android 8.0 及以上的 `GoAutoAccessibilityService` 请求系统 `flagRequestAccessibilityButton`,服务连接后向 `AccessibilityButtonController` 注册单一回调,销毁时注销;服务重连不会叠加回调。 -- 单击由系统分配给 GoAuto 的辅助功能按钮时,只调用既有 `openAgentStatus()`,以前台 `MainActivity` 打开“状态”Tab;不领取、创建、重置或重试任务,不打开 PDD,也不改变 15 秒空闲返回规则。 +- 单击由系统分配给 GoAuto 的辅助功能按钮时,只调用既有 `openAgentStatus()`,以前台 `MainActivity` 打开“状态”Tab;不领取、创建、重置或重试任务,不打开 PDD,也不改变 5 秒空闲返回规则。 - 不支持或未分配系统辅助功能按钮的 ROM 保持安全降级;项目不创建自定义悬浮窗。 ## Android Agent 状态页手动检查(#98) diff --git a/docs/03-business-rules-and-glossary.md b/docs/03-business-rules-and-glossary.md index aa29517..a380dca 100644 --- a/docs/03-business-rules-and-glossary.md +++ b/docs/03-business-rules-and-glossary.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Business-Rules-and-Glossary wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Business-Rules-and-Glossary.- -wiki_revision: b330f2be68cb2eddb929db2cb6021cf9f9b527ad -synchronized_at: 2026-08-28T04:02:59Z +wiki_revision: 0798ea888bbc55fd434e9ac31c539da7a4efea5a +synchronized_at: 2026-08-28T06:14:23Z # 业务规则与术语 @@ -273,7 +273,7 @@ synchronized_at: 2026-08-28T04:02:59Z - 间隔只阻止下一次采集任务的请求、领取和开始;心跳、采购任务优先领取与执行、采购 Outbox、历史刷新和同步继续运行。间隔结束只触发现有调度器一次,不新增轮询器。 - 状态页下拉检查和采集记录“重新采集”不得绕过间隔,统一提示“采集间隔中,还需 N 秒”。 - 本次抽中的秒数、开始时间和截止时间作为同一间隔票据持久保存在设备本地;Agent 进程或前台服务重启、设置修改都只恢复剩余时间,不重新随机。系统时间回拨时最多按该次已抽中的原始秒数截断,避免无限等待。 -- 间隔期间保持屏幕常亮;既有“任务结束 15 秒后返回 Agent”是独立机制,返回 Agent 不清除采集间隔。采购任务接管执行时不重复持有间隔亮屏锁,采购完成后若间隔尚未结束则恢复。 +- 间隔期间保持屏幕常亮;既有“任务结束 5 秒后返回 Agent”是独立机制,返回 Agent 不清除采集间隔。采购任务接管执行时不重复持有间隔亮屏锁,采购完成后若间隔尚未结束则恢复。 - 该设置不上传服务端,不改变采集任务状态、租约、规则快照或服务端接口,不打开 PDD、不修改地址、不创建订单、不支付。 ## Agent 当前 PDD 商品页临时采集 diff --git a/docs/04-local-development-and-verification.md b/docs/04-local-development-and-verification.md index ffacf74..8e588fd 100644 --- a/docs/04-local-development-and-verification.md +++ b/docs/04-local-development-and-verification.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Local-Development-and-Verification wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Local-Development-and-Verification.- -wiki_revision: 2fe9eeb9f4ac985423e02701108d2fac07377503 -synchronized_at: 2026-08-27T09:38:25Z +wiki_revision: bc940a7a8eaf2aa785ece5f031ae81aa6c217a4b +synchronized_at: 2026-08-28T06:14:26Z # 本地开发与验证 @@ -253,8 +253,8 @@ adb shell am start -n cn.ilapage.goauto.agent/.MainActivity 真机验证应至少覆盖: -- 完成一个不会支付的采集或演练任务,确认结果已提交后约 15 秒返回 Agent“状态”Tab;记录 ROM 是否限制后台 Activity 启动。 -- 冷却 15 秒内创建任一类型新任务,确认 Agent 取消返回并继续按采购优先、采集其次执行。 +- 完成一个不会支付的采集或演练任务,确认结果已提交后约 5 秒返回 Agent“状态”Tab;记录 ROM 是否限制后台 Activity 启动。 +- 冷却 5 秒内创建任一类型新任务,确认 Agent 取消返回并继续按采购优先、采集其次执行。 - 冷却期间断网,确认不会把网络失败当成空队列,也不会返回。 - 冷却期间人工切换到其他 App,确认 Agent 不会强拉回;即使再切回 PDD,前台切换序号变化也会取消本次返回。 - 使用 `adb shell dumpsys power` 或屏幕实际状态确认任务执行与冷却期间亮屏;返回、取消或服务停止后不再持有 `cn.ilapage.goauto.agent:collection-task` / `:idle-return` WakeLock。