Android 跨应用能力调用新范式:ACI 架构被控端开发实战指南

发布时间:2026/8/31 22:58:30
Android 跨应用能力调用新范式:ACI 架构被控端开发实战指南 1. 引言从应用到平台Android 跨应用调用的新思路在 Android 应用生态中应用之间的通信与能力共享一直是一个复杂且充满挑战的领域。传统的 Intent、ContentProvider 等方式虽然强大但在面对 AI Agent 等新兴场景时往往显得不够灵活和安全。今天我们要介绍的ACIAgent Capability Interface智能体能力接口架构正是为了解决这一痛点而生。ACI 是一套运行在同一台 Android 设备内、无需 Root、基于AIDL Binder的本地跨应用调用框架。它由开源项目ZorvAI提供旨在通过标准化的能力发现和调用协议大幅降低跨应用集成的成本同时提供 Token 认证、权限控制和高危能力确认等安全保障。开源地址https://github.com/Quor-a/ZorvAI本文将聚焦于 ACI 架构中的被控端Controlled开发手把手带你从零开始构建一个可以被其他应用安全调用的能力提供方。2. 核心概念与角色在深入代码之前我们先来理解 ACI 架构中的几个核心角色。它们共同构成了一个清晰、解耦的调用模型。2.1 角色定义角色职责关键类控制端Controller发起能力调用的应用如 Zorv AI 主应用QuroAidlAciManageraci-core的IAidlAciService桩被控端Controlled暴露能力供其他应用调用的应用BaseAidlAciService/Capability/AidlAciRequest/AidlAciResponse传输层Transport控制端与被控端之间的通信方式AIDL / HTTP / MCPToken用于身份认证的令牌AndroidKeyStore AES/GCM2.2 核心数据结构被控端开发的核心是理解请求与响应的数据封装。以下是两个最基础的数据类。AidlAciRequest请求publicclassAidlAciRequestimplementsParcelable{publicStringtoken;// 认证令牌publicStringcapability;// 能力名称publicBundleparams;// 参数键值对publiclongtimestamp;// 请求时间戳publicStringsourcePackage;// 调用方包名}AidlAciResponse响应publicclassAidlAciResponseimplementsParcelable{publicbooleansuccess;// 是否成功publicBundledata;// 返回数据publicinterrorCode;// 错误码publicStringerrorMessage;// 错误信息}Capability能力定义publicclassCapability{publicStringid;// 能力 ID如 execpublicStringname;// 显示名称publicStringdescription;// 描述publicbooleanrequireUserConfirm;// 是否需要用户确认publicBundlemetadata;// 元数据}3. 被控端开发实战理论铺垫完毕现在进入实战环节。我们将一步步构建一个完整的被控端应用。3.1 环境准备首先你需要从 ZorvAI 的 GitHub Release 页面下载最新的aidl-aci-core-release.aar文件。方式 A从 Release 下载# 从 GitHub Release 下载最新的 aidl-aci-core-release.aarwgethttps://github.com/Quor-a/ZorvAI/releases/download/v1.0.69/aidl-aci-core-release.aar方式 BGradle 依赖// app/build.gradle.ktsdependencies{implementation(files(libs/aidl-aci-core-release.aar))}3.2 添加依赖在你的被控端模块的build.gradle.kts中添加dependencies{implementation(files(libs/aidl-aci-core-release.aar))implementation(androidx.annotation:annotation:1.7.1)}3.3 声明权限与清单在AndroidManifest.xml中你需要声明使用控制端定义的权限并注册你的 ACI 服务。注意不要自己定义权限权限定义权归控制端所有。manifest...!-- 引用控制端定义的权限不要自己定义 --uses-permissionandroid:nameai.aci.permission.CALL/uses-permissionandroid:nameai.aci.permission.DISCOVER/uses-permissionandroid:nameai.aci.permission.CALL_DANGEROUS/uses-permissionandroid:nameandroid.permission.INTERNET/!-- 剥离库可能带入的权限定义避免同名异签冲突 --permissionandroid:nameai.aci.permission.CALLtools:noderemove/permissionandroid:nameai.aci.permission.DISCOVERtools:noderemove/permissionandroid:nameai.aci.permission.CALL_DANGEROUStools:noderemove/!-- 声明查询Android 11 包可见性 --queriesintentactionandroid:nameai.aci.intent.BIND//intent/queriesapplication...!-- 注册 ACI 服务 --serviceandroid:name.MyAciServiceandroid:exportedtrueandroid:permissionai.aci.permission.CALLintent-filteractionandroid:nameai.aci.intent.BIND//intent-filter/service/application/manifest3.4 实现被控端服务接下来创建你的 ACI 服务类继承BaseAidlAciService。这是整个被控端的核心。packagecom.example.myapp.aciimportai.aidl.aci.core.BaseAidlAciServiceimportai.aidl.aci.core.Capabilityimportai.aidl.aci.core.AidlAciRequestimportai.aidl.aci.core.AidlAciResponseimportandroid.os.Bundleimportandroid.util.LogclassMyAciService:BaseAidlAciService(){overridefunonCreateCapabilities(capabilities:MutableListCapability){// 在这里注册你的能力capabilities.add(Capability(idgreet,name打招呼,description向用户发送一条问候信息,requireUserConfirmfalse))capabilities.add(Capability(idget_device_info,name获取设备信息,description返回设备型号和系统版本,requireUserConfirmfalse))}overridefunonCall(request:AidlAciRequest):AidlAciResponse{returnwhen(request.capability){greet-handleGreet(request)get_device_info-handleDeviceInfo(request)else-errorResponse(未知能力:${request.capability})}}privatefunhandleGreet(request:AidlAciRequest):AidlAciResponse{valnamerequest.params?.getString(name)?:陌生人returnsuccessResponse(Bundle().apply{putString(message,你好$name欢迎使用 ACI 能力。)})}privatefunhandleDeviceInfo(request:AidlAciRequest):AidlAciResponse{returnsuccessResponse(Bundle().apply{putString(model,android.os.Build.MODEL)putString(sdk,android.os.Build.VERSION.SDK_INT.toString())})}privatefunsuccessResponse(data:Bundle):AidlAciResponse{returnAidlAciResponse().apply{successtruethis.datadata}}privatefunerrorResponse(message:String):AidlAciResponse{returnAidlAciResponse().apply{successfalseerrorMessagemessage errorCode-1}}}3.5 处理高危能力对于涉及用户隐私或系统敏感操作的能力你必须设置requireUserConfirm true。这样控制端在调用这些能力时会强制弹出用户确认对话框确保操作透明可控。overridefunonCreateCapabilities(capabilities:MutableListCapability){// ... 其他能力// 高危能力删除文件capabilities.add(Capability(iddelete_file,name删除文件,description删除指定路径的文件,requireUserConfirmtrue// 必须用户确认))}4. 控制端调用示例为了验证你的被控端是否工作正常我们来看一下控制端是如何发起调用的。4.1 发现并绑定服务classMyController{privatelateinitvaraciManager:AidlAciManagerfuninit(context:Context){aciManagerAidlAciManager.getInstance(context)}funconnectToControlledApp(packageName:String){// 发现服务valservicesaciManager.discover(packageName)if(services.isNotEmpty()){// 绑定到第一个服务aciManager.bind(services[0])// 获取能力列表valcapabilitiesaciManager.getCapabilities()Log.d(Controller,发现${capabilities.size}个能力)}}funcallCapability(capability:String,params:Bundle){valrequestAidlAciRequest().apply{this.capabilitycapabilitythis.paramsparams}// 同步调用valresponseaciManager.call(request)if(response.success){Log.d(Controller,调用成功:${response.data})}else{Log.e(Controller,调用失败:${response.errorMessage})}}}4.2 异步调用对于耗时操作建议使用异步调用避免阻塞主线程。funcallCapabilityAsync(capability:String,params:Bundle,callback:(AidlAciResponse)-Unit){valrequestAidlAciRequest().apply{this.capabilitycapabilitythis.paramsparams}// 异步调用aciManager.callAsync(request,object:IAidlAciCallback.Stub(){overridefunonResult(response:AidlAciResponse){callback(response)}})}5. 调试与故障排除开发过程中难免会遇到问题。这里整理了几个常见问题及排查思路。5.1 服务无法绑定// 检查清单valcheckslistOf(AndroidManifest.xml 中是否声明了 service,intent-filter 是否包含 ai.aci.intent.BIND,android:permission 是否正确,被控端应用是否已安装并运行)// 调试代码valintentIntent(ai.aci.intent.BIND)intent.setPackage(com.example.myapp)valresolveInfospackageManager.queryIntentServices(intent,0)if(resolveInfos.isEmpty()){Log.e(ACI,未找到 ACI 服务请检查 AndroidManifest.xml)}5.2 Token 验证失败// 检查 Token 生成和验证逻辑valtokenAidlAciTokenGenerator.generate(packageNamecom.example.myapp,timestampSystem.currentTimeMillis())// 验证 TokenvalisValidAidlAciTokenVerifier.verify(tokentoken,expectedPackagecom.example.myapp,maxAgeMs5*60*1000)Log.d(Token,Token 验证结果:$isValid)5.3 权限不足// 检查权限声明valpermissionslistOf(ai.aci.permission.CALL,ai.aci.permission.DISCOVER,ai.aci.permission.CALL_DANGEROUS)for(permissioninpermissions){valgrantedcontext.checkSelfPermission(permission)Log.d(Permission,$permission:${if(grantedGRANTED)已授权else未授权})}6. 最佳实践最后分享一些在开发 ACI 被控端时的最佳实践帮助你构建更安全、更高效的服务。6.1 安全性永远不要在受控端定义权限权限定义权归控制端高危能力必须设置requireUserConfirm true验证所有输入参数防止注入攻击定期轮换 Token避免长期有效 Token记录所有审计日志便于安全审计6.2 性能优化使用异步调用避免阻塞主线程缓存能力列表避免频繁查询限制响应大小避免传输大量数据使用连接池复用 AIDL 连接6.3 错误处理返回详细的错误信息便于调试使用标准错误码保持一致性实现重试机制处理临时故障提供降级方案服务不可用时的备选7. 总结与展望ACI 架构为 Android 跨应用能力调用提供了一种全新的、标准化的解决方案。通过本文的实战指南你应该已经掌握了如何构建一个安全、高效的 ACI 被控端。这不仅为 AI Agent 提供了强大的工具调用能力也为应用间的深度协作打开了新的可能。ZorvAI 项目仍在快速迭代中未来还将支持更多传输方式、更丰富的安全策略和更完善的开发工具链。欢迎 Star 并参与到项目中来共同推动 Android 应用生态的智能化演进。项目地址https://github.com/Quor-a/ZorvAI相关文档ACI_DEVELOPER_GUIDE.mdACI_TECHNICAL_ARCHITECTURE.mdTERMINAL_ARCHITECTURE.md本文基于 ZorvAI v1.0.69 编写最后更新于 2026年8月30日。

相关新闻