夜雨聆风学习资料网

ARTICLE · 1021767

ZorvAI APK 插件框架 · 技术架构与功能介绍

ZorvAI APK 插件框架 · 技术架构与功能介绍

文档类型:技术架构说明 | 架构介绍 | 功能介绍适用宿主:Zorv AI(com.ai.assistance.quro)≥ 1.0.89框架版本:v1.0.90代码位置:plugin-contract(契约层)· :plugin-engine(引擎层)· app/core/plugin + app/core/tools + app/ui(宿主接入层)示例插件:plugin-devkit:plugin-express:plugin-todo:plugin-units:plugin-sysinfo:plugin-zorvweb

开源地址

平台
仓库地址
GitHub
(主仓库 · Release / Issues)
github.com/Quor-a/ZorvAI
Giteegitee.com/ZorvAI/ZorvAI
GitLab
(极狐)
jihulab.com/quor-a-group/ZorvAI
常用入口
链接
最新 Release(免登录下载 APK)
github.com/Quor-a/ZorvAI/releases
问题反馈 / 需求建议
github.com/Quor-a/ZorvAI/issues
开发手册(apk-plugin-arch 分支)
docs/APK_PLUGIN_DEVELOPMENT_MANUAL.md
克隆仓库
git clone https://github.com/Quor-a/ZorvAI

本项目完全开源(Apache-2.0),多平台托管;插件框架的源码就在上面的仓库里—— 契约层 plugin-contract/、引擎层 plugin-engine/、6 个示例插件 plugin-*/ 可直接编译运行。


目录

章节
内容
为什么需要 APK 插件框架
核心思想(一句话)
分层架构
四个关键机制
加载全流程
AI 工具链
界面体系
安全模型
可靠性设计
功能介绍
十一
内置示例插件
十二
方案对比
十三
设计原则与边界

一、为什么需要 APK 插件框架

ZorvAI 是一个能力密度很高的 AI 助理:终端、浏览器、ACI、TTS、可视化和 14 类扩展能力都长在宿主里。 传统做法下,每加一个能力都要动宿主源码——改工具注册表、改系统提示、改设置页、重新发版。 这条路径有三个绕不开的成本:

成本
具体表现
发布耦合
一个小工具也要走完整 App 发版流程(构建 383MB APK、上传、用户下载安装)
源码耦合
第三方想在 ZorvAI 里加能力,必须拿到宿主源码并编译整个工程
能力上限 = 团队上限
宿主团队写多少,AI 就有多少能力,无法外部扩展

APK 插件的目标:把「给 AI 加能力」从「改宿主」变成「装一个 APK」。

设计目标四条:

  1. 宿主零改动
     —— 宿主不认识任何具体插件,只认识「扩展点」这一个抽象;
  2. 能力可分发
     —— 插件是标准 APK,可签名、可版本管理、可从任意渠道分发;
  3. AI 原生
     —— 插件注册的工具自动进入 LLM 工具集,装完立刻可用,无需重启;
  4. 可控安全
     —— 插件与宿主同进程、同权限,因此必须有明确的信任边界(同签名)。

二、核心思想(一句话)

宿主不认识任何具体插件,只认识「扩展点」这一个抽象。 插件往槽里放实现,宿主负责调度。

// 插件作者写的全部代码,本质上就是「往槽里放东西」class HelloEntry : PluginEntry {    override funonCreate(ctx: PluginContext) {        plugin(ctx) {            aiTool("hello_greet""向某人打招呼。当用户说「跟某人打招呼」时调用。") {                param("who", ParamType.STRING, "要打招呼的对象名字")                execute { args -> ToolResult.text("你好,${args.string("who")}!") }            }        }    }}

这段代码不进宿主、不改宿主、不重新编译宿主。装进宿主后,LLM 的工具集里立刻多出一个 hello_greet

这就是「神经-代码一体化」在宿主侧的具体形态:宿主提供稳定的骨架(扩展点 + 调度), 插件提供可替换的血肉(实现),两者通过签名互相担保。


三、分层架构

框架是严格的四层结构,依赖方向单向向下,上层不知道下层的具体实现:

┌──────────────── 宿主 App(:app)· 调度层 ────────────────────────────┐│                                                                      ││  QuroApplication.onCreate()                                          ││      └── QuroPluginHost.attach(this)      ← 宿主唯一一次性接线点       ││               ├── QuroPluginEngine.init(app, HOST_CAPS)              ││               ├── AciBridge 双向注入                                  ││               └── QuroPluginEngine.loadAllInstalled()                ││                                                                      ││  AI 工具链                                                            ││    QuroToolRegistry.coreSpecs()                                      ││        └── pluginHostToolSpecs()                                     ││              ├── QuroPluginTools        → 单入口工具 apk_plugin       ││              └── QuroPluginHost.toolSpecs() → 插件贡献的 AI 工具       ││                                                                      ││  QuroToolEngine.execute()                                            ││      ├── 命中插件工具 → QuroPluginHost.executePluginTool()(suspend)  ││      └── 否则走内置注册表派发                                          ││                                                                      ││  界面                                                                 ││    PluginManagerScreen    ← 启动器式插件桌面(网格/搜索/长按菜单/Dock)││    PluginSurfaceActivity  ← 通用界面承载 Activity                     │└──────────────────────────────────────────────────────────────────────┘                              ▲               HostToolBridge / AciBridge(宿主取用桥)                              │┌────────────── :plugin-engine(引擎层)· 能力层 ───────────────────────┐│  QuroPluginEngine     加载 / 卸载 / 热重载(DexClassLoader)           ││  PluginInstaller      清单解析 · 同签名校验 · 原子替换 · .so 提取       ││  PluginClassLoader    隔离类加载器(宿主 ClassLoader 作父)             ││  PluginContextImpl    插件运行时上下文(存储 / 日志 / 互调)            ││  ExtensionRegistry    14 个扩展点「收纳槽」                            ││  HostToolBridge       扩展点 → 宿主工具规格                            ││  AciBridge            ACI 能力双向桥                                  │└──────────────────────────────────────────────────────────────────────┘                              ▲┌──────────── :plugin-contract(契约层|compileOnly)· 约定层 ──────────┐│  PluginEntry   PluginContext   ExtensionType   PluginDsl   ToolSpec…  │└──────────────────────────────────────────────────────────────────────┘                              ▲┌──────────────── 你的插件 APK(独立签名 APK)· 实现层 ─────────────────┐│  YourEntry : PluginEntry  →  onCreate 里 plugin(ctx) { ... }          │└──────────────────────────────────────────────────────────────────────┘

各层职责

模块 / 位置
谁依赖它
职责
契约层:plugin-contract
插件 compileOnly、引擎 implementation
只放接口与数据类,不含任何实现。插件编译期可见、运行期由宿主提供
引擎层:plugin-engine
宿主 implementation
安装、加载、卸载、热重载、扩展点收纳、桥接
调度层:app
宿主本体
决定「什么时候、用哪个扩展点、给谁看」,接进 AI 工具链与 UI
实现层
你的插件 APK
只依赖契约层,提供扩展点实现

为什么契约层必须是 compileOnly 若用 implementation 把契约层打进插件 APK,插件与宿主会各持有一份 PluginEntry 类的副本。 宿主用自己的 ClassLoader 加载插件时,ClassCastException 会立刻出现—— 这是本框架第一大坑,也是新人最常踩的坑。


四、四个关键机制

4.1 扩展点收纳槽(ExtensionRegistry)

框架的灵魂是一个只有 14 个格子的注册表。每个格子对应一类可插入的能力:

#
ExtensionType
用途
宿主消费方
1
AI_TOOL
给 LLM 加一个可调用工具 ★ 最常用
HostToolBridge
 → QuroToolRegistry
2
ACI_CAPABILITY
把能力暴露给其他 App / Agent
AciBridge
 → ACI 服务端清单
3
UI_SURFACE
插件自带的完整界面(View 树)
PluginSurfaceActivity
4
CHAT_CARD
聊天气泡内自定义结构化卡片
聊天渲染层
5
UI_WIDGET
气泡内可交互内联组件
内联组件渲染
6
MODEL_PROVIDER
新增一种大模型接入
模型配置层
7
RAG_SOURCE
新增一种知识库来源
知识库层
8
COMMAND
输入框 /斜杠指令
输入框解析
9
SETTING
设置页新增配置项
设置页
10
SCHEDULE_TASK
新增周期任务执行体
定时任务调度
11
CHANNEL
新增一个 IM 接入
消息渠道层
12
FILE_HANDLER
新增文件类型的打开/预览
文件打开分发
13
CODE_RUNTIME
新增脚本语言引擎
脚本执行层
14
SPEECH
新增 TTS / STT 引擎
语音层

收纳槽的索引键是 (ExtensionType, id)

  • 同名同类的扩展后注册者覆盖先注册者 —— 所以工具名必须加插件前缀(如 express_queryweb_open);
  • 插件卸载时 unregisterAll() 一次性清空该插件的全部格子,不留悬挂引用。

4.2 类加载与资源挂载

插件 APK 不是系统安装的应用,它用 DexClassLoader 在宿主进程内加载:

PluginClassLoader(    dexPath          = <host>/files/plugins/<id>/active/base.apk,    optimizedDir     = <host>/files/plugins/.odex/<id>,    nativeLibraryDir = <host>/files/plugins/<id>/active/lib,   ← 按设备 ABI 提取的 .so    parent           = 宿主 ClassLoader                          ← 关键)

两个设计细节:

  • 父加载器 = 宿主 ClassLoader
    :插件因此能拿到宿主的 Class,也能被宿主反射实例化;
  • 资源挂载 = 宿主资源路径 + 插件资源路径
    :新建 Android.Resources 时把两边都挂上, 插件里的 R.string.xxx 能用,同时插件的 View 也能继承宿主主题(不会出现样式割裂)。

因为跑在宿主进程内,插件不能有自己的 Activity / Service / BroadcastReceiver—— 要界面请注册 UI_SURFACE,由宿主用通用 Activity 承载。

4.3 双向桥(HostToolBridge / AciBridge)

桥的作用是把插件的能力翻译成宿主认识的形态,两个方向:

方向一(插件 → 宿主)  AiToolExtension  →  HostToolBridge.collectToolSpecs()                   →  ToolParamSpec → OpenAI function-callingJSONSchema                   →  QuroToolRegistry.coreSpecs()  →  LLM tools 字段方向二(ACI 双向)  AciCapabilityExtension  →  AciBridge.capabilitySink                          →  QuroPluginAciRegistry.publish()  →  对外能力清单  AciBridge.externalCapabilities + aciInvoker      →  refreshAciMirror()(宿主定期刷新)      →  外部 ACI 能力镜像成 AI 工具 aci_list / aci_call

结果:插件既是能力的提供方,也是能力的消费方,且两条链路都收敛到「AI 工具」这一个出口。

4.4 单入口工具 apk_plugin

框架只暴露 1 个 AI 工具给 LLM,而不是十几个零散管理工具。这样做的原因:

  • 工具集里工具越少,LLM 选错工具的概率越低;
  • 管理类动作(装/卸/查)不该进入日常工具集,只在需要时由同一入口分发。
action
必填参数
作用
status
框架状态(engine_ready 等)
list
已装插件清单
infoplugin_id
插件明细(含扩展点构成)
tools
插件贡献的全部 AI 工具
surfaces
插件界面清单
opensurface_id
打开插件界面
installpath
(可选 skip_signature_check
从 APK 安装
install_builtin
装宿主内置示例插件
uninstallplugin_id
卸载
reloadplugin_id
(不传=全部)
热重载
callname
(可选 args
★ 直接调用插件 AI 工具

call 是关键的兜底通道:工具集被裁剪、或插件刚装完还没轮到下一轮时, AI 仍可用 apk_plugin(action="call", name="...", args="{...}") 调用插件工具。 宿主侧等价于直接调 QuroPluginHost.executePluginTool不经过工具集—— 所以「插件装了但 AI 用不了」这个死角不存在。

历史说明:早期版本曾用 6 个独立工具(plugin_list / plugin_info / plugin_install /plugin_uninstall / plugin_reload / plugin_surface_open)实现同样的功能, 现已全部删除,统一收敛为 apk_plugin


五、加载全流程

5.1 安装(install(apk)

install(apk)  ├─ 1. PackageManager 读清单 → 校验 meta-data quro.plugin.entry,缺失即拒  ├─ 2. 校验 APK 签名 SHA-256 == 宿主签名,不一致即拒  ├─ 3. 取 pluginId / versionCode / versionName / label(桌面显示名)  ├─ 4. 原子替换写入 /data/data/<host>/files/plugins/<pluginId>/active/base.apk  ├─ 5. 从 APK 提取 lib/<abi>/*.so → active/lib/  ├─ 6. 写 SharedPreferences 记录(quro_plugins/record_<pluginId>)  └─ 7. load(pluginId)        ├─ 新建 PluginClassLoader(宿主 ClassLoader 作父)        ├─ Android.Resources 挂「宿主资源路径 + 插件资源路径」        ├─ 反射 newInstance() → YourEntry        └─ YourEntry.onCreate(ctx)   ← 你在这里注册扩展点

七步里前两步是信任闸门,任何一步不过,安装直接失败并给出明确原因(见手册「调试与排错」)。

5.2 启动(宿主冷启动)

QuroApplication.onCreate()  └── QuroPluginHost.attach(app)        ├── QuroPluginEngine.init(app, HOST_CAPS)        │      HOST_CAPS = {llm, memory, tts, stt, aci, terminal, file, web, screen, shell}        ├── AciBridge 双向注入        ├── QuroPluginEngine.loadAllInstalled()   ← 已装插件的 onCreate 在此跑        ├── refreshAciMirror()                    ← 外部 ACI 能力镜像成 AI 工具        └── QuroPluginAciRegistry.publish(...)    ← 插件能力对外发布

性能约束onCreate 在 Application.onCreate 的 loadAllInstalled() 里同步执行, 所以插件必须保持轻量——耗时的初始化放到首次 execute 时惰性执行,或自己开后台线程。


六、AI 工具链(让 LLM 自己找到插件)

这是整个框架最核心的价值链路。插件注册完,AI 不用被通知就知道新工具存在

YourEntry.onCreate   └─ ctx.register(AiToolExtension)        └─ ExtensionRegistry(收纳槽)             └─ HostToolBridge.collectToolSpecs()                  └─ QuroPluginHost.toolSpecs()        ← ToolParamSpec → JSON Schema                       └─ pluginHostToolSpecs() → QuroToolRegistry.coreSpecs()                            └─ LLM tools 字段(下一轮 functioncalling 即可见)执行:QuroToolEngine.execute(call)   └─ QuroPluginHost.executePluginTool(name, args)     ← suspend 桥接        └─ HostToolBridge.executeTool → YourExecutor.execute(ToolArgs)

三个设计要点:

  1. 自动进工具集
    :不需要重启宿主,不需要手动刷新注册表;
  2. 契约是 JSON Schema
    ToolParamSpec(含 enumdefaultrequired)被宿主翻译成 标准 function-calling schema,LLM 侧零特殊处理;
  3. 执行体是 suspend
    :插件可以直接 withContext(Dispatchers.IO) 发网络请求、读数据库, 不会阻塞主线程(这是 Android 侧最容易被忽略的一条)。

决定调用率的是 description

宿主的系统提示里有一整章讲插件框架,但真正决定 LLM 会不会调用你的是工具描述

做法
效果
❌ "快递查询工具"
AI 不知道什么时候该用
✅ "根据快递单号查询物流轨迹。当用户询问快递到哪了、物流状态、包裹进度时调用。"
AI 能把口语映射过来
❌ param("no", STRING, "单号")
AI 可能传错格式
✅ param("no", STRING, "快递单号,如 SF1234567890")
有示例,命中率高
✅ 用 enum 约束有限取值集合
避免 AI 自由发挥传错值

七、界面体系

7.1 为什么插件不能写 Activity

插件 APK 没有真实的系统安装记录,startActivity 一个插件里的 Activity 会直接失败。 宿主提供通用承载 Activity解决这个问题:

PluginManagerScreen(插件桌面)        │  单击图标 / 长按「打开界面」/ 详情「打开界面」        │  AI: apk_plugin(action="open", surface_id="...")        ▼PluginSurfaceActivity(宿主通用承载)        │  调用插件的 UiSurfaceExtension.build(activityContext, host)        ▼插件返回的 View 树(由插件负责构建,可用 WebView 做完整前端)

7.2 交给插件的三个回调

interface SurfaceHost {    val pluginId: String    funclose()                    // 关闭当前界面    funtoast(message: String)     // 宿主 Toast    funrunOnUi(block: () -> Unit) // 切主线程}
回调
时机
插件该做什么
build(actCtx, host)
界面打开
返回 View 树(拿到的是 Activity Context,可直接 WebView(actCtx)
SurfaceBackHandler.onSurfaceBack()
返回键/手势
true
 = 自己消费(如先退一层内部页面);false = 交宿主关闭
onRelease()
界面关闭
释放资源
:detach WebView、注销监听、停计时器

7.3 插件桌面(PluginManagerScreen)

启动器形态的插件管理界面,是插件能力的可视化入口

  • 网格布局 + 搜索 + 长按菜单(打开界面 / 重载 / 卸载 / 详情)
  • 底部 Dock →「导入 APK」直接装
  • 图标取插件 APK 的 launcher 图标(没配则显示首字母色块)
  • 显示 v1.0.0 (1) 形式的版本信息

已废弃:早期 JS 演示壳 PluginsScreen 已更名 LegacyJsPluginRuntimeScreen,打开即空白,不要把它当成插件入口。现役插件桌面就是 PluginManagerScreen


八、安全模型

插件跑在宿主进程内、拥有与宿主完全相同的权限——这本质上等同于「代码注入」 因此框架的安全边界不是「限制插件能做什么」,而是「保证插件是我信任的代码」:

边界
机制
为什么必须
同签名
宿主比对 APK 证书 SHA-256
插件与宿主同进程同权限;不同签名 = 不可信代码
只放私有目录/data/data/<host>/files/plugins/
外置存储可被其他 App 篡改
必须是声明了 entry 的 APK
清单解析 quro.plugin.entry
防止误装普通 APK
原子替换.tmp
 → .bak → active,失败回滚
避免安装中断导致插件损坏
卸载即注销unregisterAll()
不留悬挂扩展点

宿主 Release 证书 SHA-256(插件必须使用同一份 keystore):

D9:5B:1B:EC:57:B9:D5:EE:88:96:05:9C:0F:3C:B5:09:E5:E9:CE:7C:CD:AE:DB:9C:6B:2E:98:49:BA:10:C7:99

调试期可用 apk_plugin(action="install", path=..., skip_signature_check=true) 跳过校验,正式分发绝不能跳过


九、可靠性设计

机制
实现
解决的问题
原子替换安装
先写 .tmp → 旧版改名 .bak → .tmp 改名 active → 删 .bak;任一步失败回滚
不会出现「装一半坏掉」
热重载apk_plugin(action="reload", plugin_id=...)
 = unload + load
改完插件立刻生效,不需要重启宿主 App
卸载即清理unload
onDestroy + unregisterAll)→ 删 plugins/<id>/ → 清记录
不留垃圾、不留悬挂扩展点
失败降级
安装失败给出明确原因(缺 entry / 签名不符 / 写入失败…)
排错不靠猜
原生库自动适配
安装时按设备 ABI 提取 lib/<abi>/*.so 到 active/lib/,作为 librarySearchPath 传入
一个 APK 适配多 ABI 设备

热重载会丢状态reload = unload + load,插件实例重建。 需要持久化的东西放 ctx.putString() 或 ctx.getFilesDir()


十、功能介绍

10.1 面向用户:装了插件之后,AI 多了什么能力

能力域
用户可说的话
背后是谁在干活
给 AI 加工具
「帮我算一下 base64 解码」「查一下我的快递」
插件的 AI_TOOL 扩展点
完整的插件界面
插件桌面点图标打开「ZorvWeb 浏览器」
插件的 UI_SURFACE 扩展点
斜杠指令/express SF1234567890
插件的 COMMAND 扩展点
对话卡片
聊天里出现插件渲染的结构化卡片
插件的 CHAT_CARD 扩展点
跨 App 能力开放
其他 App / 其他 Agent 通过 ACI 调我的能力
插件的 ACI_CAPABILITY 扩展点
新模型 / 新知识源
在模型列表里多一个自建服务商
MODEL_PROVIDER
 / RAG_SOURCE
新文件类型支持
点开 .xyz 文件由插件预览
FILE_HANDLER
新语音 / 脚本引擎
换一个 TTS,或多一种脚本语言
SPEECH
 / CODE_RUNTIME

关键点:这些能力全部由插件提供,宿主代码零改动。

10.2 面向开发者:你能往哪些槽里放东西

你想做的
用哪个扩展点
难度
给 AI 加一个可调用工具
AI_TOOL
★ 最常用,10 行代码
做一个插件自己的完整界面
UI_SURFACE
★★ 会写 View / WebView 即可
加一条 /斜杠指令
COMMAND
把能力暴露给别的 App
ACI_CAPABILITY
★★
加配置项 / 定时任务 / 文件处理
SETTING
 / SCHEDULE_TASK / FILE_HANDLER
★★
接新模型 / 新知识库 / 新渠道 / 新语音
MODEL_PROVIDER
 / RAG_SOURCE / CHANNEL / SPEECH
★★★

10.3 框架给开发者提供的便利

便利
具体体现
声明式 DSLplugin(ctx) { aiTool(...) { param(...); execute {...} } }
,不用手写注册样板
参数宽松解析
LLM 把数字传成字符串也能取到(args.int() / args.number() 兜底转换)
宿主能力探测ctx.hasHostCapability("llm")
 做可选依赖判断,有则增强、无则降级
安全的键值存储ctx.getString / putString / getBool / putBool
,底层按插件隔离
私有文件目录ctx.getFilesDir()
 → <host>/files/plugins/<pluginId>/
日志归集ctx.log(tag, msg)
 → logcat TAG 为 QuroPlugin/[<pluginId>],一眼分清是哪个插件
插件互调ctx.callCapability(id, args)
,先找插件能力、再找外部 ACI 能力
AI 兜底调用apk_plugin(action="call")
 绕过工具集裁剪

十一、内置示例插件

仓库内置 6 个可直接编译、可直接安装的示例插件,本身就是框架能力的规格说明

插件
显示名
注册了哪些扩展点
演示了什么
:plugin-express
快递查询插件
AI_TOOL + 1 ACI_CAPABILITY + 1 COMMAND
最小完整范式
:一个插件同时贡献 AI 工具、对外能力、斜杠指令
:plugin-devkit
开发工具箱
AI_TOOL + 1 ACI_CAPABILITY
多功能插件组织方式(dev_base64dev_hashdev_jsondev_regexdev_urldev_uuid
:plugin-zorvweb
ZorvWeb 网页引擎
15 AI_TOOL + 1 UI_SURFACE
旗舰示例
:AI 工具 + 完整界面共存,用 WebView 做插件自带前端
:plugin-todo
待办清单
AI_TOOL
有状态插件 + 持久化
:plugin-units
单位换算
AI_TOOL
极简单工具插件(含 enum 参数约束)
:plugin-sysinfo
设备体检
AI_TOOL
借宿主 Context 读系统信息(sys_batterysys_memorysys_storagesys_report

旗舰示例:plugin-zorvweb 的 15 个工具

web_open        web_nav         web_read       web_query      web_findweb_elements    web_console     web_script     web_wait       web_tabsweb_media       web_http        web_crawl      web_info       web_search_page

外加 1 个 uiSurface(id = 浏览器,标题「ZorvWeb 浏览器」), 插件内部用 BrowserSurfaceView 构建界面,onRelease 里做 WebView 资源释放——这一个插件就同时演示了 AI 工具族、界面承载、生命周期管理三件事


十二、方案对比

维度
系统安装的独立 App
纯 JS / 脚本插件
ZorvAI APK 插件
能给 AI 加工具
不能(除非走 ACI 绕行)
能,且自动进工具集
能访问宿主上下文
不能
受限
能(同进程同权限)
能渲染完整界面
自己开 Activity(体验割裂)
受沙箱限制
能(宿主通用 Activity 承载 + 继承宿主主题)
分发形式
应用商店 / APK
脚本文件
签名 APK,可版本管理与热重载
性能
跨进程开销
解释执行开销
同进程原生,无跨进程开销
语言
Kotlin / Java
JS
Kotlin / Java(全生态可用)
安全边界
系统沙箱
沙箱
同签名 + 私有目录 + 清单校验
改宿主源码
不需要
不需要
不需要

取舍说明:APK 插件用「同签名」换来了最强的能力与性能, 代价是第三方无法自由发布插件——这是有意的设计选择:插件跑在宿主进程内, 放开签名等于允许任意代码注入。需要开放生态时,正确路径是 ACI_CAPABILITY(走 Binder 语义、跨进程隔离)。


十三、设计原则与边界

13.1 五条设计原则

原则
落地方式
宿主只认识抽象
宿主不 import 任何插件类,只消费 ExtensionType
依赖单向向下
实现层 → 契约层;引擎层 → 契约层;调度层 → 引擎层。禁止反向
契约层零实现:plugin-contract
 只有接口与数据类,保证 compileOnly 语义成立
能力收敛到单一出口
14 类能力最终都翻译成「AI 工具」或「ACI 能力」两种形态
默认安全
同签名 + 私有目录 + 清单校验,三条闸门都不提供「宽松模式」(调试开关除外)

13.2 边界与限制(明确不做的事)

限制
原因
替代方案
不能写 Activity / Service / Receiver
插件无系统安装记录
UI_SURFACE
(界面)、SCHEDULE_TASK(周期任务)
不能直接改宿主源码或布局
会破坏「宿主零改动」前提
只能通过扩展点接入
不能自由分发(必须同签名)
同进程 = 代码注入
开放生态走 ACI_CAPABILITY
不能在 onCreate 里做重活
在 Application.onCreate 同步链路里
惰性执行 / 自己开后台线程
热重载不保状态
reload
 = unload + load
持久化到 ctx.putString / getFilesDir()

13.3 术语表

术语
含义
宿主(Host)
ZorvAI 主程序(:app),负责调度与承载
契约层(Contract):plugin-contract
,插件与宿主之间的唯一接口约定
扩展点(Extension Point)
14 种可插入能力槽位之一
收纳槽(Registry)ExtensionRegistry
,按 (ExtensionType, id) 索引的注册表
表面(Surface)
插件提供的完整界面,由宿主通用 Activity 承载
桥(Bridge)HostToolBridge
 / AciBridge,把插件能力翻译成宿主认识的形态
ACI
跨进程能力调用体系;插件能力可对外发布,外部能力也可镜像成 AI 工具

相关文档与源码位置

文档 / 源码
链接
内容
《ZorvAI APK 插件开发手册》
本机桌面 / apk-plugin-arch 分支 docs
从 0 到 1 写插件:DSL 完整参考、工程配置、排错速查、完整示例
仓库 README
github.com/Quor-a/ZorvAI
 →「APK 级插件框架」
面向使用者的能力索引
扩展点权威定义
plugin-contract/.../extension/ExtensionPoints.kt
14 种 ExtensionType + 数据类
DSL 权威定义
plugin-contract/.../dsl/PluginDsl.ktplugin(ctx) { ... }
 全部 builder
引擎层实现
plugin-engine/
加载 / 安装 / 收纳槽 / 双向桥
示例插件
plugin-zorvweb
 · plugin-devkit · plugin-express
可直接编译运行的参考实现

仓库地址

GitHubgithub.com/Quor-a/ZorvAI(主仓库)Giteegitee.com/ZorvAI/ZorvAIGitLabjihulab.com/quor-a-group/ZorvAI下载Releases | 反馈Issues


本文档描述 ZorvAI APK 插件框架 v1.0.90 的架构与能力,随代码演进维护。项目开源地址:github.com/Quor-a/ZorvAI

相关学习资料

返回首页浏览学习资料