文档版本:v1.0.72(对应
app/build.gradle.kts) 修订日期:2026-09-01 适用范围:Android 应用com.ai.assistance.quro(品牌 ZorvAI)内置网页浏览器,以及独立 ACI 受控浏览器模块aidl-aci-browser(包名com.ai.assistance.quro.browser) 说明:浏览器能力由两套并行实现 组成------主 App 内的「对话/工具流浏览器」(AI 用browser_act操控),与独立分发的「ACI 受控浏览器」(主程序经 AIDL 远程操控)。本文档同时覆盖两者。 开源地址:ZorvAI GitHub 仓库
0. 项目简介
ZorvAI 是一个开源的 Android AI 助手应用(包名 com.ai.assistance.quro),其内置浏览器模块让 AI 不仅能"读懂"网页,还能像真人一样操作 网页------点击、填表、滚动、截图、执行 JS,甚至通过 Linux uinput 注入拟人化触摸。本文档基于源码(v1.0.72)整理,系统讲解其技术架构、双实现设计、自动化控制协议与关键配置,帮助开发者快速理解并二次开发。
- 开源地址 :ZorvAI GitHub 仓库
- 核心亮点:AI 感知页面 + 自动化操作 + 控制台/网络捕获 + 原生输入注入
- 适用读者:Android 开发者、AI Agent 研究者、对"AI 操控浏览器"感兴趣的工程师
1. 概述
Zorv AI 浏览器让 AI 助手能「看到并操作」网页,核心是:
- AI 感知页面:读取当前网页的 DOM/正文/链接/截图/可见文本,作为多模态上下文喂给模型;
- AI 自动化操作 :
browser_act工具 + ACI 受控端能力,支持打开、点击、填表、滚动、查找、前进/后退、截图、执行 JS; - 控制台与网络捕获 :抓取
console.*、网络请求、页面事件,供 AI 诊断; - 原生输入注入 :通过 Linux
uinput虚拟多点触摸屏,向系统注入拟人化触摸/按键(操控页面/表单,需 root 或系统签名); - 底层引擎:系统 Android WebView(Chromium/WebKit 内核),非自编译内核。
2. 整体架构(两套实现)
scss
┌──────────────────────────────────────────────────────────────────────┐
│ Zorv AI 主程序(com.ai.assistance.quro) │
│ │
│ AI 工具层 │
│ ├─ QuroBrowserActTool.kt (name="browser_act") ── 主 App 浏览器操控 │
│ ├─ QuroWebCrawlerTool.kt ── 网页爬取 │
│ └─ QuroToolsAiBrowser.kt ── AI 浏览器相关工具集合 │
│ │
│ 浏览器控制器 / 桥 │
│ ├─ QuroBrowserController.kt (object) ── 持有当前 WebView,eval/snapshot/click/fill │
│ └─ QuroBrowserBridge.kt (object) ── Channel<String> open(url) 事件总线 │
│ │
│ UI │
│ └─ QuroBrowserScreen.kt (Composable) ── AndroidView 内嵌 WebView │
│ │
│ ACI 控制端(调用独立受控浏览器) │
│ └─ QuroAidlAciTools / QuroAciHttpServer ── aci_call <browser pkg> │
└───────────────┬───────────────────────────────┬──────────────────────┘
│ 对话内 open / browser_act │ AIDL bindService (aci_call)
▼ ▼
┌───────────────────────────────┐ ┌────────────────────────────────────────┐
│ 主 App 内 WebView(ChatScreen) │ │ 独立模块 aidl-aci-browser │
│ (进程内,AI 直接 evaluateJS) │ │ com.ai.assistance.quro.browser │
│ │ │ ├─ BrowserActivity.kt (可见界面) │
│ │ │ ├─ BrowserCore.kt (object, 常驻 WebView)│
│ │ │ ├─ ConsoleBackend.kt (AciConsoleContract)│
│ │ │ ├─ DiagBuffer.kt (诊断缓冲) │
│ │ │ ├─ UinputBridge.kt (JNI uinput) │
│ │ │ ├─ QuroControlledAidlAciService.kt (≈50 能力)│
│ │ │ └─ uinput_bridge.c (native 触摸注入) │
└───────────────────────────────┘ └────────────────────────────────────────┘
两套实现互不依赖 (不同包/不同进程),底层都是系统 WebView +
evaluateJavascript。
3. 引擎与渲染
- 使用系统 Android WebView(Chromium/WebKit)。注释明确:自编译 Chromium 无法作为库嵌入,故落地系统 WebView;
BrowserCore.getEngineInfo()经WebView.getCurrentWebViewPackage()取package/version/androidApi/ua;QuroBrowserScreen配置:MIXED_CONTENT_ALWAYS_ALLOW、allowFileAccess=true、javaScriptEnabled=true、domStorageEnabled=true、loadsImagesAutomatically=true、useWideViewPort/loadWithOverviewMode=true;- 未强制单进程;主 App 用
AndroidView内嵌并注册WebViewClient/WebChromeClient,factory中QuroBrowserController.attach(this)、onRelease调detach。
4. 地址栏与关键词搜索
三处逻辑不一致(已知不一致点,需注意):
| 入口 | 非 URL 输入处理 | 默认搜索引擎 |
|---|---|---|
BrowserActivity.smartNavigate() |
含空格/无点 → searchUrl();带点无空格补 https:// |
Bing https://www.bing.com/search?q= |
QuroBrowserController.resolveBrowserInput() |
无 scheme 且含点或空格 → 补 https://;纯词 → 搜索 |
百度 https://www.baidu.com/s?wd= |
ACI browser_search(受控端) |
engine 参数 |
默认 bing ,支持 google/baidu/ddg(ddg 由 bing 兜底) |
- 无关键词联想/历史 (仅固定种子书签 + 手动收藏,
quro_browserSharedPreferences); - ACI
browser_open经startActivity拉起BrowserActivity(singleTask),并用awaitWebView/armPageReady+notifyPageFinished解决异步竞态。
5. AI 感知页面(读取 DOM / 文本 / 截图)
两套实现:
主 App(QuroBrowserController,eval 关键修复)
- 直接把表达式包进 IIFE 调
QuroBridge.onEvalResult(token, ...),不使用eval(),兼容 CSP(unsafe-eval被禁的页面也能跑); pageHtml():documentElement.outerHTML;pageText():body.innerText;collectLinks():所有外链;snapshot():注入data-quro-id稳定 ID + 简化 DOM + 元素列表(tag/type/name/href/text),供 AI 按 id 决策;screenshot():PixelCopy 截整个 Activity 窗口存 PNG。
受控端(BrowserCore)
readHtml()(outerHTML切片 1MB +body.innerHTML兜底);readCleanDom()(去 script/style、打data-ai-id、标data-in-viewport);crawlPage()(title/text/links,正文 200k 截断);getTitle()/getUrl();scanResources()(video/audio/img/adownload 资源直链);uiSnapshot()/uiDiff()(屏幕坐标元素树 + 锚点可靠性 + 差分流)。
无专门 CSP 规避 ,靠
evaluateJavascript与 IIFE 桥接规避unsafe-eval限制。
6. 控制台与网络捕获
Console(console.*)
BrowserCore在registerDisplayWebView挂的WebChromeClient.onConsoleMessage调reportConsole(level,text,source,line)→ 写入ConsoleBuffer(环形 1000);- ACI
browser_console能力可 enable/disable/clear/读取。
网络请求抓包
BrowserActivity.WebViewClient.shouldInterceptRequest调BrowserCore.captureRequest(url,method,headers,isMainFrame)→CaptureBuffer(环形 800,只记元数据/不读响应体,返回 null 放行);- ACI
browser_capture能力启停/读取/清空。
页面事件 / 审计
EventBuffer(page_started/finished/request/load_resource);AuditBuffer(每次 ACI 调用一条);- 数据流向:全部进
BrowserCore各环形 Buffer 供 ACI 回读给 AI,同时经DiagBuffer写 Logcat(不落盘,除非DiagBuffer.persist)。
7. 自动化控制(browser_act)
主 App AI 工具 BrowserActTool(name="browser_act")。推荐组合: open → status(确认 loaded) → snapshot(拿 quro-id) → click/fill → read(回读) → 必要时 scroll/wait。
action 枚举(逐字):
open / status / snapshot / click / fill / click_selector / fill_selector / read / html / text / links / eval / wait / scroll / find / back / forward / reload / stop / screenshot
| action | 参数 | 行为 |
|---|---|---|
open(url) |
url | 网址或关键词(自动搜索);已 attach 调 navigate,否则 QuroBrowserBridge.open |
status |
--- | 返回 attached+loaded+url+title,先调它确认页面就绪 |
snapshot |
--- | url/title/ready + 带 data-quro-id 的元素列表 + 简化 DOM(前 2k) |
click(id) |
id | 按 data-quro-id 点击 |
fill(id,value) |
id,value | 按 data-quro-id 输入(原生 value setter + 派发 input/change,兼容 React/Vue) |
click_selector(sel) |
selector | 按 CSS 选择器点击 |
fill_selector(sel,value) |
selector,value | 按 CSS 选择器输入 |
read(selector) |
selector | querySelector.outerHTML(最多 8k) |
html |
--- | 整页 HTML(最多 16k) |
text |
--- | 页面正文(最多 8k) |
links |
--- | 所有外链(最多 8k) |
eval(code) |
code | 执行任意 JS(字符串化返回) |
wait(ms) |
ms | 等 readyState(默认 1500,最大 15000) |
| `scroll(dy | to)` | dy,to |
find(text) |
text | window.find 高亮,返回是否命中 |
back/forward/reload/stop |
--- | 导航控制 |
screenshot |
--- | PixelCopy 截当前窗口存 PNG,返回路径 |
强制约定 :必须先用
snapshot拿quro-id,再按 id 操作;不要靠 CSS 选择器(页面结构易变)。本工具不打开新窗口,仅操控当前活跃 WebView;若浏览器未在前台先action=open。
受控端 ACI 能力(另套命名,语义对应)
browser_action的op:click/type/scroll_to/select(按data-aci-eid或selector二选一);browser_mouse:move/click/dblclick/right/down/up/drag/scroll(click/drag 拟人化:贝塞尔 + 亚像素抖动 + 可变压力 0.4~0.62);- 受控端约 50 能力(见 §9):
browser_open/read/crawl/search/script/list/info/capture/find/nav/screenshot/console_ui/console_action/elements/action/wait/snapshot/restore/events/audit/media/share/console/query/tabnew/tabs/tab/tabclose/mouse等 +http_request/workspace_*/ui_snapshot/ui_diff/tap/inject_touch。
8. 输入注入(uinput)
UinputBridge(libLoaded 标志,System.loadLibrary("uinput_bridge") 失败则 false)+ JNI: nativeOpen(maxX,maxY) / nativeClose / nativeDown(slot,tid,x,y,pressure,major) / nativeMove / nativeUp。
uinput_bridge.c:open("/dev/uinput",O_WRONLY) 注册虚拟多点触摸屏 "QuroAciVirtualTouch" (vendor 0x04E8),设 ABS_MT_*+ABS_X/Y+BTN_TOUCH,MT Protocol B(SLOT+TRACKING_ID),坐标 1:1 映射屏幕分辨率。
权限限制 :仅在 root 或系统签名(priv-app + SELinux 放行 uinput_device) 构建时 /dev/uinput 可写;否则 nativeOpen 返回 false,优雅降级------上层明确报错「需 root/系统签名」,绝不假装成功。普通分发版不可用。
9. ACI 受控端协议(QuroControlledAidlAciService)
QuroControlledAidlAciService : BaseAidlAciService(独立模块 aidl-aci-browser,包 com.ai.assistance.quro.browser)------ 作为 ACI 受控端,被 ZorvAI 主程序经 AIDL 远程控制:
onCreateCapabilities注册约 50 能力(详见 §7 受控端列表);onCall(req)按capability分发,调用前reportAiActivity(点亮「AI 眼睛」)+audit记日志;- 鉴权 :无共享 secret token 字符串校验,依赖 Android 组件权限 ------
<service android:permission="ai.aci.permission.CALL">+android:exported="true",仅持有ai.aci.permission.CALL的调用方(ZorvAI 主程序com.ai.assistance.quro,常量ZORV_PKG)可绑定;<queries>声明ACTION_BIND/ACTION_WAKE与包com.ai.assistance.quro; - WakeReceiver :
QuroAidlAciWakeReceiver(exported)收ai.aci.core.ACTION_WAKE广播 → 拉起主 Activity,使停止态进程变活跃以便bindService成功;并写quro_browser_diag.log; BrowserCore.heldWv进程级常驻 WebView,ActivityonDestroy仅 detach 不销毁(避免 Activity 回收后读取 500)。
10. 与终端 / ACI 体系的关系
- 浏览器复用 ACI 跨进程协议 作为受控端(controlled side) ,ZorvAI 主程序是控制端(controller);
BrowserCore/ConsoleBackend不主动调用控制端,仅经 ACI 被远程驱动;BrowserActivity的「发给 AI」按钮(shareToAi)反向经ACTION_SEND把页内容推回com.ai.assistance.quro;- 终端侧的
QuroTerminalAciService与浏览器的QuroControlledAidlAciService同属 ACI 受控端体系,但独立进程、独立权限声明。
11. 关键配置与默认值
| 配置项 | 默认值 |
|---|---|
| 默认搜索引擎 | BrowserActivity→Bing;QuroBrowserController→百度;browser_search→bing(可 google/baidu/ddg) |
| WebView 设置 | javaScriptEnabled=true、domStorageEnabled=true、MIXED_CONTENT_ALWAYS_ALLOW、allowFileAccess=true |
| 进程常驻 | BrowserCore.heldWv 进程级常驻,Activity destroy 仅 detach |
| 超时 | browser_open 页面就绪 15s 闸门(armPageReady 3s 快速命中);eval/read 等 8s latch;Service HARD_TIMEOUT_S=14(主程序 callTimeoutMs=15000) |
| 截断 | HTML 1MB、crawl 正文 200k、links 200、uiSnapshot 元素上限 400 |
| 缓冲上限 | ConsoleBuffer1000 / CaptureBuffer800 / EventBuffer/AuditBuffer500 / 快照 20 / 标签 20 |
| 模块构建 | aidl-aci-browser:compileSdk=36、minSdk=26、targetSdk=34、versionName=1.0.14、ABI arm64-v8a、NDK r27,依赖 :aidl-aci-core 与 okhttp |
| 代理设置 | QuroBrowserScreen 弹窗仅存 SharedPreferences(proxy_enabled/type/host/port/...),注释称「Android 11+ 经 ProxyController」,代码未实际注入 WebView |
12. 已知差异 / 待澄清
- 搜索引擎不一致 :主 App 内(
QuroBrowserController)默认百度,受控端BrowserActivity默认 Bing,browser_search默认 bing。三处不统一,如需一致应在resolveBrowserInput与smartNavigate收敛到同一常量; - 无关键词联想/历史:地址栏仅做「含点即网址、否则搜索」的粗判;
- uinput 注入依赖 root/系统签名:普通分发版不可用,调用方需显式报错;
- 受控端无显式 token 字符串校验 :安全边界完全依赖 Android 权限模型(
ai.aci.permission.CALL); - 代理设置未实际生效 :
SharedPreferences已存但未注入 WebView; - 未发现
open_browser/close_browser动作名(仅reference-projects/Eta资源里有action_open_browser字符串,与本浏览器无关);browser_act是主 App AI 工具,browser_*是受控端 ACI 能力,二者命名不同但语义对应。
13. 快速上手与源码导航
想直接跑起来或深入源码?推荐按下面顺序阅读:
- 克隆仓库:
bash
git clone https://github.com/Quor-a/ZorvAI.git
cd ZorvAI
- 主 App 浏览器入口 :
app/src/main/java/com/ai/assistance/quro/下的QuroBrowserController.kt、QuroBrowserBridge.kt、QuroBrowserScreen.kt、QuroBrowserActTool.kt; - 受控端浏览器模块 :
aidl-aci-browser/src/main/java/com/ai/assistance/quro/browser/下的BrowserCore.kt、BrowserActivity.kt、QuroControlledAidlAciService.kt、UinputBridge.kt; - 原生触摸注入 :
aidl-aci-browser/src/main/cpp/uinput_bridge.c(JNI 实现); - 构建受控端模块 :
compileSdk=36、minSdk=26、targetSdk=34、ABIarm64-v8a、NDK r27。
提示:
browser_act是主 App 的 AI 工具,browser_*是受控端 ACI 能力,二者命名不同但语义一一对应,阅读时注意区分。
本文档由源码(v1.0.72)实际结构整理,关键类名/方法名/常量均可在 app/src/main/java/com/ai/assistance/quro/(主 App 浏览器)与 aidl-aci-browser/src/main/java/com/ai/assistance/quro/browser/(受控端)下核对。
14. 总结与展望
ZorvAI 内置浏览器通过两套并行实现(主 App 内 WebView + 独立 ACI 受控浏览器),覆盖了从"AI 感知页面"到"AI 自动化操作"的完整链路。其设计亮点在于:
- 双实现解耦 :主 App 内浏览器与独立受控端互不依赖,底层统一基于系统 WebView +
evaluateJavascript,兼顾灵活性与稳定性; - AI 友好接口 :
browser_act工具 + 约 50 项 ACI 能力,让 AI 能像人一样"看、点、填、滚、截"; - 拟人化输入 :
uinput注入贝塞尔轨迹 + 亚像素抖动 + 可变压力,模拟真实触摸; - 可观测性:Console/网络/事件/审计四类环形缓冲,为 AI 诊断提供完整上下文。
后续可探索方向:
- 统一搜索引擎:将三处默认搜索逻辑收敛到同一常量,消除行为不一致;
- 代理设置落地 :将已存储的
SharedPreferences代理配置真正注入 WebView; - 关键词联想:为地址栏补充搜索建议与历史记录;
- 安全加固:在 Android 权限模型基础上,增加可选的 token 校验层。
欢迎 Star / Fork / PR,一起完善 ZorvAI 的浏览器能力!
本文档由源码(v1.0.72)实际结构整理,关键类名/方法名/常量均可在 app/src/main/java/com/ai/assistance/quro/(主 App 浏览器)与 aidl-aci-browser/src/main/java/com/ai/assistance/quro/browser/(受控端)下核对。