摘要
Android 开放生态的核心矛盾是:系统厂商为了续航与安全不断"收权",而智能体(Agent)类应用天然需要常驻、需要后台执行、需要系统级感知能力。对于没有大厂资源和白名单合作的个人独立开发者,这一矛盾尤为尖锐。
本文以个人开发的安卓移动智能体 Nyral(开源仓库 aixtin/Nyral,包名 io.github.aixtin.nyral)为对象,系统复盘其在国产 ROM(ColorOS / HyperOS / MIUI)环境下存活与进化的完整工程实践,涵盖四个方面:
- 软地基架构:以"能力与通道解耦"为原则,构建六类半官方通道(无障碍服务、隐形输入法、悬浮窗、本地调试服务、通知/气泡确认壳、前台服务)组成的后台生存底座;
- 定时岗位机制:基于
AlarmManager.setExactAndAllowWhileIdle的精确闹钟穿透 Doze 模式,配合续期重排、任务会话绑定、预授权白名单与审计日志,实现"AI 每日自我唤醒静默执行"的无人值守闭环; - 灵动岛(Live Updates)接入:通过升级 targetSdk 36、遵循 Android 16 原生 Live Updates API(promoted notifications),让 Agent 任务进度以标准通知通道上屏系统状态栏胶囊,跨厂商自动适配(ColorOS 流体云、HyperOS 超级岛),无需悬浮窗权限与厂商白名单;
- 真机验证方法论:以"改 cron + UI 停用/启用触发真实闹钟"和"DebugServer 注入 + 通知/db 三方取证"两套方法,在不依赖厂商测试体系的前提下完成端到端可信验证。
本文同时对比了 arXiv:2607.13027(PalmClaw)“API over GUI"的运维路线,指出个人开发者构建移动 Agent 时应优先选择"标准协议穿透 + 自建云侧运维通道"而非"全栈 GUI 自动化"的工程判断。
1 引言与背景
1.1 移动 Agent 的现实困境
智能体(Agent)类应用与普通应用的本质区别在于:它需要"持续存在、随时被唤醒、有能力触达系统其他部分”。而在 Android 生态中,这三者恰好全部处于厂商的限制射程之内:
- 持续存在:Doze、App Standby、厂商激进回收(ColorOS 的"纯净后台"、MIUI 的"神隐模式")会杀死后台进程;
- 随时被唤醒:
setExactAndAllowWhileIdle等精确闹钟被限制频率,厂商还会拦截系统广播(BOOT_COMPLETED、MY_PACKAGE_REPLACED); - 触达系统:无障碍(AccessibilityService)、输入法(IME)、悬浮窗(SYSTEM_ALERT_WINDOW)等"半官方通道"均需用户授权,且厂商可能针对特定应用收窄权限。
对独立开发者而言,问题还要再加三层:没有厂商白名单资格、没有海量设备适配预算、项目由单人维护(本文作者为一人开发、一人运维、零资本投入的非科班开发者,约 8 年软硬件折腾经验,无营业执照与公司主体)。
1.2 Nyral 简介
Nyral 是一个运行在 Android 手机上的个人移动智能体:支持自然语言对话、工具调用(文件、浏览器、终端、应用操作)、知识库沉淀、定时任务(本文称为"定时岗位")、远程运维(DebugServer + SSH/ADB)等能力。它不依赖云端常驻进程,核心逻辑全部跑在用户的手机上,云侧(VPS)仅作为可选运维通道。
这一形态决定了它必须解决"在手机上活下去"的问题,也使其成为研究个人 Agent 后台生存架构的理想样本。
1.3 论文结构
第 2 节给出威胁模型与通道分层;第 3 节介绍软地基架构;第 4 节详细展开定时岗位机制;第 5 节介绍灵动岛/Live Updates 接入;第 6 节讨论安全与信任边界;第 7 节给出真机验证方法论;第 8 节与既有工作对比;第 9 节总结。
2 威胁模型与通道分层
2.1 厂商收权的层级结构
在长期实践中,我们将移动 Agent 的能力触达按"权限强度"分为五层,越上层越不可剥夺,越下层越接近厂商控制:
| 层级 | 通道 | 可剥夺性 | 说明 |
|---|---|---|---|
| L1 云侧 | VPS / 云函数 | 不可剥夺 | 数据与大脑在云端,手机端只是执行器 |
| L2 系统运维 | SSH / ADB / shell | 极难剥夺 | 需 root 或 adb 授权,是最后兜底 |
| L3 超级权限 | root / 解锁 Bootloader | 难剥夺 | 厂商可保修拒保,用户主动选择 |
| L4 半官方通道 | 无障碍 / IME / 悬浮窗 | 可收窄 | 厂商会定向收紧,但有标准协议保护 |
| L5 普通通道 | 前台服务 / 通知 / 闹钟 | 可限制 | Doze、Standby、厂商省电策略层层加码 |
关键结论(也是 Nyral 的路线依据):命脉在厂商,但标准协议不可关。厂商可以收紧应用调用频次,却不能关闭无障碍服务、输入法、通知、闹钟这些 Android 标准框架能力——否则整个系统生态都会崩溃。因此,Agent 的存活策略必须建立在"标准协议 + 半官方通道"的组合上,而不是赌某一家厂商的私有接口。
2.2 能力与通道解耦原则
Nyral 的架构铁律:能力与通道解耦,通道只做一层适配,不赌未来变。
- 能力(Ability):读剪贴板、点屏幕、发通知、执行定时任务……这些是 Agent 的核心诉求,与通道无关;
- 通道(Channel):无障碍、IME、悬浮窗、通知、闹钟……这些是会随厂商策略变化的"皮肤"。
当某个通道被厂商收紧时,只替换该通道的适配层,能力层完全不动。这一原则在 2026 年 9-10 月的多轮改造中反复验证(见第 3、4 节)。
3 软地基架构:六类半官方通道
Nyral 的"软地基"是一组经过长期踩坑后沉淀的通道清单,它们共同构成了 Agent 在国产 ROM 上"不死、能醒、能触达"的底座:
3.1 通道清单
| 通道 | 实现 | 用途 | 保活价值 |
|---|---|---|---|
| 无障碍服务 | UiControlService | 读取界面、模拟点击、感知前台 | 系统级常驻通道,用户主动授权,厂商无法单方面关闭 |
| 隐形输入法 | InvisibleIME(InvisImeService) | 后台读剪贴板、无痕输入 | IME 进程被系统视为"正在输入",存活优先级高 |
| 悬浮窗 | SYSTEM_ALERT_WINDOW | 悬浮主页、慢放球、悬浮终端 | 可见即活,用户感知度高 |
| 本地调试服务 | DebugServer(端口 8765) | 远程注入指令、会话管理、SSE 流式回传 | 运维通道,配合 adb forward 可达 |
| 通知/气泡确认壳 | Notification + 气泡 | 危险操作的确认交互 | 前台可见的决策入口 |
| 前台服务 | TaskService / TimerKeepAliveService | 定时任务执行、闹钟保活 | 可见通知的持久服务,降低被杀概率 |
3.2 InvisibleIME 的实战踩坑(以 ColorOS 为例)
隐形输入法在 OPPO ColorOS 上有一个典型坑:系统会按窗口高度门控隐藏 IME 底栏(chevron/九宫格切换器/手势条),导致用户无法收键盘或切换输入法。
最终方案(2026-10-12 定稿)完全基于公开 API、零反射:
onCreateInputView中匿名 View 强制测量高度 900px,骗过 OPPO 窗口高度门控,保留底栏布局;onComputeInsets把 contentTopInsets 设为全高、touchableRegion 只给 navbar 实际区域,实现"IME source frame 高度为 0,所有 App 零推移;透明区触摸直穿";- 用 OnPreDrawListener 做底栏守护,每帧检查 visibility/alpha 并扳回(OPPO 的
InputMethodServiceExtImpl.updateNavigationBarVisibility会藏整个 NavigationBarView,不只是两个子按钮,守护目标必须含三个 view)。
这条踩坑的价值在于:厂商私有行为(隐藏底栏)与标准框架行为(IME insets)的解耦——我们不反射、不 hook 厂商内部 API,只改自己的标准 API 调用,因此即使厂商升级策略也大概率不会破坏。
3.3 通道的存活优先级排序
实测经验(三品牌真机:OPPO ColorOS / 红米 HyperOS / 一加 ColorOS):当系统开始杀后台时,存活优先级大致为:IME ≥ 悬浮窗 > 前台服务(带可见通知)> 无障碍 > 普通后台进程。因此 Nyral 将"隐形输入法 + 悬浮窗"作为最低限度保活组合,前台服务作为任务执行载体,无障碍作为触达工具而非存活依赖。
4 定时岗位:无人值守的自我唤醒闭环
“定时岗位"是 Nyral 的核心功能之一:用户用自然语言让 AI 创建一个定时任务(如"每天早上九点给我推送科技新闻早报”),到点后手机上的 Agent 静默唤醒、执行工具链、把结果写回绑定的会话并发通知。
4.1 四模块实现链路(2026-10-11 MVP)
| 模块 | 职责 |
|---|---|
| TimerTaskDb | 独立 timer.db 任务表,含 session_id/mode 列(v2 迁移) |
| TimerScheduler | 用 AlarmManager.setExactAndAllowWhileIdle 注册精确闹钟 |
| TimerWakeReceiver | 到点接收广播,拉起 TaskService |
| TaskService.runTimerTask | 复用 LocalEngine.chat 无 UI 链路执行任务,落库 + 审计 |
任务创建时自动创建专属会话并绑定,执行结果写回绑定会话;聊天模式与 Agent 模式双模式隔离不串扰。
4.2 穿透 Doze 的关键:setExactAndAllowWhileIdle + 续期重排
setExactAndAllowWhileIdle 是 Android 允许应用在 Doze 模式下精确唤醒的少数 API 之一(单次闹钟,非重复闹钟)。它有一个致命缺陷:单次闹钟触发后不会自动续期。
2026-10-13 真机验证发现两个缺陷并修复:
- 单次无续期:第一次触发后后续不再唤醒 → 在
onDone/onError回调中补调用 schedule 续排下一周期; - 静默场景危险工具门禁挂起:静默执行时危险工具确认弹窗无人响应,挂起 2 分钟 → 静默模式自动拒绝危险工具。
4.3 完成通知与真实闹钟链路验证
新增 notifyTaskDone()(NOTIF_DONE_ID=1005,channel=task_running,低重要性,点击进 MainActivity,setAutoCancel)。
真机验证(一加 PJX110 ColorOS 16.0.5.701 + 小米 HyperOS 双机)全链路通过:
改 cron 到 21:36 → UI 停用/启用触发 AlarmManager 重排
→ 21:36:00 真实闹钟触发 TimerWakeReceiver
→ TaskService 静默执行
→ 完成续期重排
→ 通知上屏「定时任务完成: WakeAutoTest」
alarm tag 形如 *walarm*:io.github.aixtin.nyral.action.TIMER_WAKE;Logcat 链路 TimerWakeReceiver → TaskService 完整。
4.4 通知组折叠:跨品牌可见性
三个后台服务(DebugService 1002 / TaskService 1001 / TimerKeepAliveService 1003)的通知整合为通知组(key nyral_services,父通知 1004)。
踩坑记录:初版用 getActiveNotifications() 统计活跃子通知数,ColorOS(Android 16)恒返回空数组,导致父通知不发布。改为 ServiceNotifGroup 静态 AtomicInteger 计数(register / onDestroy unregister / publishSummary),三服务 onDestroy 互补。
跨品牌验证结论:OPPO(ColorOS)/ 红米(HyperOS)/ 一加(ColorOS)三台真机状态栏通知组折叠显示均正常。
4.5 停止机制:进程组治理(2026-10-31)
与保活对称的另一面是"能停干净"。停止机制改造(P0–P3 全量落地并真机验证):
- 取消域:activeConns 逐连接断流 + 剪枝剩余 tool_calls + 可中断退避;
- 停止按钮三态:软停 / 硬停 / 结束;
- ProcGuard 进程组治理:setsid + procs.json + TERM→KILL + 120s 时限夹紧 + 启动巡检清僵尸;
- SSH 三层远端清理:pid 文件 / environ 标记 / pgrep 兜底。
实测停止 2 秒内进程组清零。
5 灵动岛:从通知到系统级状态胶囊
5.1 调研结论(2026-09-21)
针对"手机系统灵动胶囊是厂商适配应用,还是应用适配胶囊"的调研结论:
- 主流模式是应用适配胶囊:应用按系统 API/SDK 上报持续活动,系统统一渲染胶囊/实况窗;
- ColorOS 16 起流体云完整接入原生 Android 16 的 Live Updates API(谷歌实时活动 API),采用 OPPO + 谷歌"双兼容"方案:应用遵循谷歌实时活动 API 规范即可直接适配流体云,无需 OPPO 白名单或单独 SDK;
- 流体云三种卡片形态:notification_sm(胶囊/气泡)、notification_md(通知大胶囊)、notification_lg(展开面板);
- 支持场景类型(entityName)含 TASK——TASK 类型适合 Agent 上报任务执行进度。
对独立开发者而言这是重大利好:不需要厂商商务合作,只靠标准 API 就能上岛。
5.2 SDK 36 升级路径(2026-09-23)
Live Updates API 需要 targetSdk 36+。升级内容:
| 项 | 原值 | 新值 |
|---|---|---|
| Gradle | 8.5 | 8.13 |
| AGP | 8.2.2 | 8.13.0 |
| compileSdk | 34 | 36 |
| targetSdk | 34 | 36 |
| Kotlin / Java / minSdk | 1.9.22 / 17 / 24 | 不变 |
关键决策:选 AGP 8.13.0 而非 AGP 9.x(AGP 9 引入内置 Kotlin 变更风险大);升 36 而非 37(36 已满足 Live Updates + Play 合规,37 生态未稳缓升)。
真机验收:一加 ColorOS 16.0.5.701(V16.0.0)edge-to-edge 强制(targetSdk 35+ 行为)无遮挡问题。
5.3 上屏机制
Live Updates 走标准通知通道(promoted notifications),系统自动将通知转成状态栏胶囊,不需要悬浮窗权限。代码证据:TaskControlReceiver.kt 注释"Live Updates 胶囊交互卡动作接收器",Manifest 声明 POST_PROMOTED_NOTIFICATIONS 权限。
这意味着 Agent 的任务进度(后台执行/SSH/下载)可以以 TASK 场景实时上报,跨厂商通用:ColorOS 流体云自动识别,HyperOS 3.1+ 的超级岛顺带打通,老设备不强求。
6 安全与信任边界:静默执行的授权模型
定时岗位在"无人值守"和"危险操作"之间存在天然张力。Nyral 的解法是预授权模型(2026-10-13 方案定稿):
- 废弃全局静默放权:AI 创建定时任务时,检测任务所需权限,打包为一次性授权(all-or-nothing);
- 权限生命周期 = 任务生命周期:任务删除即回收权限;
- 严格 key 白名单:ToolExecutor 对非法 key 严格报错,LocalEngine ToolSpec 补全 17 项白名单;
- 弹窗底座泛化:SecurityUi 支持 template/title/body/decision 四要素,壳模板含 task_create/tool_exec/question/confirm/raw;
- 审计日志:
nyral_security_audit.log记录 approvedBy=channels 等决策来源,真机拉库可证; - 静默模式强制拒绝:静默执行场景下危险工具直接拒绝,不挂起等待(修复了挂起 2 分钟的死锁缺陷)。
真机验证闭环(2026-10-15):id=12 创建→删除验证通过;id=11 早报 09:00 静默执行写文件成功;allow_tools=workdir:write 正确落库。
7 真机验证方法论:无厂商测试体系的端到端可信验证
独立开发者没有厂商测试团队,验证全靠真机自证。两套沉淀方法:
7.1 真实闹钟链路验证(改 cron + UI 停用/启用)
1. adb exec-out run-as 拉 timer.db 到本地
2. 改目标任务 cron_desc 为几分钟后(如"每天 21:36")
3. adb push 到 /data/local/tmp + chmod 777 + run-as cp 覆盖回 databases/
4. 进定时任务页点任务卡片 → 菜单「停用」→ 再点「启用」,
enable() 调用 TimerScheduler.schedule 触发 AlarmManager 重排
5. dumpsys alarm 确认 *walarm* TIMER_WAKE 的 origWhen
6. sleep 到点后 logcat 抓 TimerWakeReceiver/TaskService/notifyTaskDone,
并 cmd statusbar expand-notifications 看通知栏
比 runNow 覆盖更真实的端到端链路(灭屏→闹钟→唤醒→静默执行→通知上屏)。
7.2 DebugServer 注入 + 三方取证
1. monkey 拉起 App 初始化 DebugServer(8765),
adb forward tcp:18765 tcp:8765,
curl POST /v1/chat 带 X-Auth-Token 注入自然语言指令
2. logcat 抓 toolCalls=[(timer_task_create,...)] 确认 AI 调用与参数
3. 截屏/uiautomator 确认确认壳(气泡或通知)渲染清单
4. 用户在手机上点击允许/删除完成决策
5. run-as exec-out cat databases/timer.db 经中转拉回,
sqlite 读 timer_tasks 确认 allow_tools 等字段真实落库
6. 读 files/nyral_security_audit.log 确认 approvedBy=channels 决策来源
原则:避免只看 AI 回复文本误判成功,保证"调用→确认→落库→审计"全链路真机可见可证。
7.3 覆盖安装不丢配置
迭代开发装机用 adb install -r 覆盖安装 debug 包,装机前备份 shared_prefs,测试后还原,保证用户配置不丢。
8 与既有工作的对比:为什么选"API over GUI"
arXiv:2607.13027(PalmClaw)提出 “API over GUI” 范式——优先通过 API/协议而非 GUI 自动化来完成 Agent 任务。Nyral 的运维路线与之一致,且是在没有阅读该论文的情况下独立得出的工程判断(后查证发现思路撞车):
| 维度 | PalmClaw(API over GUI) | Nyral 实践 |
|---|---|---|
| 核心主张 | API 优先于 GUI 操作 | 标准协议(通知/闹钟/Live Updates)优先于悬浮窗/无障碍模拟 |
| 理由 | GUI 脆弱、慢、不可审计 | 标准协议穿透力强、厂商难关、可审计(通知有系统担保) |
| 落地差异 | 面向通用 Agent | 面向个人开发者的单机 Agent + 云侧运维通道 |
具体到"上岛"场景:GUI 自动化上不了系统状态栏胶囊,但 Live Updates 标准通知通道可以——这是"标准协议穿透"优于"GUI 模拟"的直观证据。
9 结论与展望
本文完整复盘了个人移动智能体 Nyral 在厂商收权时代下的后台生存架构:
- 软地基原则:能力与通道解耦、通道只做一层适配、不赌未来变,让 Agent 在六类半官方通道上获得可维护的存活底座;
- 定时岗位:以
setExactAndAllowWhileIdle+ 续期重排穿透 Doze,以预授权白名单 + 审计日志平衡静默与安全,形成"自我唤醒→执行→落库→通知"的无人值守闭环; - 灵动岛:依赖 Android 16 原生 Live Updates 标准 API 上屏系统状态栏,避开厂商白名单与悬浮窗权限,跨品牌自动适配;
- 验证方法论:两套真机自证链路让独立开发者在无厂商测试体系下获得可信的端到端证据。
展望:随着 Android 17(API 37)成熟,Live Updates 生态会进一步开放;Agent 类应用的后台能力将逐步从"对抗厂商回收"转向"标准 API 表达持续活动"。Nyral 的下一步包括:Live Updates 胶囊交互卡深度化(点击动作回传)、端侧本地 AI 推理(OpenCL 路线)、以及知识库自动沉淀的持续迭代。
参考文献
[1] PalmClaw: API over GUI for Generalist Agents. arXiv:2607.13027. [2] Android 16 Developer Preview: Live Updates (Promoted Notifications) API. Google Developer Documentation. [3] OPPO 泛在服务框架(流体云)开发文档. open.oppomobile.com. [4] Android 官方文档: AlarmManager / setExactAndAllowWhileIdle. [5] Nyral 开源仓库: github.com/aixtin/Nyral(本文全部工程实践的代码载体)
附录 A:核心验证数据
| 日期 | 事项 | 结论 |
|---|---|---|
| 2026-09-23 | SDK 34→36 升级 | 构建通过,edge-to-edge 无遮挡 |
| 2026-10-11 | 定时岗位 MVP 四模块 | 手动立即执行全链路闭环 |
| 2026-10-12 | InvisibleIME 底栏修复 | 竖屏/横屏底栏稳定,透明区触摸直穿 |
| 2026-10-13 | 真实闹钟链路 + 完成通知 | 21:36 触发→静默执行→续期→通知上屏 |
| 2026-10-15 | 预授权三阶段 | id=12 创建删除闭环,id=11 静默执行写文件成功 |
| 2026-10-11 | 通知组折叠 | OPPO/红米/一加三真机正常 |
| 2026-10-31 | 停止机制 P0–P3 | 停止 2s 内进程组清零 |