AppFunctions 完整介绍

Google Jetpack AppFunctions 完整介绍

Android 16 (API36) 新增 Jetpack 组件,Android 本地 MCP 实现 ,让 AI Agent (Gemini) 本地调用 App 内部能力,不用走网络。你项目里 Volvo 的 @AppFunction(isDescribedByKDoc=true) 就是参照谷歌原生 AppFunctions 做的内部自研框架,注解名字、参数几乎一模一样,但不是谷歌官方库

状态:Alpha 预览版,尚未稳定,仅 Android16 + 支持Android De...。

一、核心概念

  1. @AppFunction 注解:标记 suspend 函数,把普通 Kotlin 函数暴露给系统 AI 智能体调用。
  2. isDescribedByKDoc = true :KSP 编译器读取 KDoc 注释,自动生成 LLM Function‑call 的description、参数说明,不用手写 JSON 工具描述
  3. @AppFunctionSerializable :自定义入参 / 返回数据类,同样支持isDescribedByKDoc=true解析 KDoc。
  4. AppFunctionService:系统 Service,接收系统 Agent 的跨进程调用请求,KSP 自动生成子类。
  5. 系统维护全局函数注册表:所有 App 的 AppFunction 元数据注册到 SystemServer;Agent 有权限就可以发现、调用本机所有 App 开放的函数。

类比 MCP:

  • 传统 MCP:大模型 ↔ 远端服务器工具
  • AppFunctions:Gemini(Agent) ↔ 本机各个 App 本地函数,全部设备内执行,不上传业务数据到云端。

整体调用流程

  1. 开发者用@AppFunction标记 suspend 函数,写好 KDoc 注释
  2. KSP 编译期扫描注解,自动生成:元数据 XML、Service 骨架、序列化代码
  3. App 安装,XML 注册到 Android 系统 AppFunction 注册表
  4. Agent (Gemini) 拿到权限,查询系统注册表,获取全部函数 + 工具描述(来自 KDoc)
  5. LLM 决策调用哪个函数,系统 IPC 唤起目标 App 的AppFunctionService,执行函数,返回结果给 Agent

二、环境依赖 build.gradle.kts(Module 级别)

需要 KSP,Android16+,Jetpack AppFunctions alpha 库Android De...

kotlin

scss 复制代码
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("com.google.devtools.ksp") //必须开启KSP
}

android {
    compileSdk = 36 // Android16
    defaultConfig {
        minSdk = 36
    }
}

dependencies {
    implementation("androidx.appfunctions:appfunctions:1.0.0‑alpha10")
    ksp("androidx.appfunctions:appfunctions‑compiler:1.0.0‑alpha10")
}

三、完整代码示例

1. 定义可序列化数据类(入参、返回值)

kotlin

less 复制代码
/** 任务实体 */
@AppFunctionSerializable(isDescribedByKDoc = true)
data class Task(
    /** 任务唯一ID */
    val id: String,
    /** 任务标题 */
    val title: String,
    /** 任务详情内容 */
    val content: String
)

/** 创建任务入参 */
@AppFunctionSerializable(isDescribedByKDoc = true)
data class CreateTaskParams(
    /** 任务标题,可以为空 */
    val title: String?,
    /** 任务内容,可以为空 */
    val content: String?
)

2. AppFunctionService 基类

@AppFunctionServiceEntryPoint:KSP 基于这个抽象类生成真正的 Android Service 组件,注册到 AndroidManifest。

kotlin

kotlin 复制代码
@RequiresApi(36)
@AppFunctionServiceEntryPoint(
    serviceName = "TaskAppFunctionService",
    appFunctionXmlFileName = "task_app_function_service"
)
abstract class BaseTaskAppFunctionService : AppFunctionService() {

    /**
     * 创建一个待办任务
     * @param createTaskParams 创建任务的参数
     */
    @AppFunction(isDescribedByKDoc = true)
    suspend fun createTask(createTaskParams: CreateTaskParams): Task {
        // 业务逻辑,IO操作要放在Dispatchers.IO
        if(createTaskParams.title.isNullOrBlank() && createTaskParams.content.isNullOrBlank()){
            // 抛出框架预定义异常,Agent可以捕获识别错误原因
            throw AppFunctionInvalidArgumentException("标题或内容不能同时为空")
        }
        return Task(id = "123", title = createTaskParams.title, content = createTaskParams.content)
    }
}

⚠️ 强制约束:

  1. @AppFunction 只能修饰 suspend 挂起函数,不能普通函数、不能接口方法(Volvo 自研是接口,谷歌原生是 suspend function 写在 Service 内部)
  2. 入参返回值只能是基础类型 / @AppFunctionSerializable标记 data class,不支持任意对象
  3. isDescribedByKDoc=true,才提取 KDoc 生成 LLM 工具描述;false 就忽略注释,description 为空,Agent 无法理解函数用途
  4. 修改 KDoc 注释,必须 Rebuild 项目,增量编译不会重新解析注释

四、Manifest 配置

KSP 自动生成 Service,但需要权限声明:

xml

xml 复制代码
<!-- 本应用开放AppFunction能力给系统 -->
<uses-permission android:name="android.permission.BIND_APP_FUNCTION_SERVICE"/>

<!-- 调用方Agent(如Gemini)需要这个权限才能发现&执行AppFunctions -->
<uses-permission android:name="android.permission.EXECUTE_APP_FUNCTIONS"/>

注意:EXECUTE_APP_FUNCTIONS系统级签名权限,普通第三方 App 拿不到,只有系统 Agent/Gemini 可以拥有。

五、@AppFunction注解全部参数

kotlin

kotlin 复制代码
annotation class AppFunction(
    // true:解析KDoc注释作为LLM工具描述
    val isDescribedByKDoc: Boolean = false,
    // 是否对外暴露给Agent调用
    val isEnabled: Boolean = true
)

六、常见坑点

  1. 修改 KDoc 注释不生效 :KSP 增量编译不会重新处理注释,执行 Build → Rebuild Project
  2. 函数不能是普通 fun,谷歌原生强制 suspend 挂起函数 ,IO 逻辑用withContext(Dispatchers.IO)
  3. 普通第三方 App 不能作为调用端:EXECUTE_APP_FUNCTIONS是系统权限,只有系统 Agent 可以调用。
  4. 只能 Android16 以上,低版本系统无法兼容。
  5. 异常不要抛普通 Exception,要抛框架定义的AppFunctionInvalidArgumentException等,Agent 可以识别错误码。

七、Agent 调用方简单示意

Agent 拥有系统权限,通过AppFunctionManager查询全部可用函数、执行函数:

kotlin

kotlin 复制代码
val appFunctionManager = context.getSystemService(AppFunctionManager::class.java)
// 获取所有App暴露的函数元数据(包含从KDoc解析出来的tool description)
val allFunctions = appFunctionManager.getAppFunctions()
// 执行某个function,传入参数
appFunctionManager.executeAppFunction(request, ...)
相关推荐
蜡台2 小时前
Jetpack Compose 从入门到精通
android·前端·kotlin·compose·jepack
toooooop82 小时前
踩坑:PHP7.2导出Excel正常,升级7.3文件损坏需修复
android·excel
mmsx2 小时前
我明明调用了 zoomToBounds,地图却总是停在别处?延迟加到 5 秒也没用,真相只有一个
android·人工智能·bug·地图
蜡台4 小时前
Jetpack Compose 核心:状态管理 + Lazy 列表
android·kotlin·state·jetpack compose
Escalating_xu5 小时前
【Linux线程同步】从数据竞争到 mutex、条件变量与生产者消费者(上篇)
android·java·linux
00后程序员张6 小时前
Windows / Linux / Mac 上不用 Xcode 把 IPA 上传到 App Store,upload 命令详解
android·ios·小程序·https·uni-app·iphone·webview
秦少游在淮海6 小时前
id - Android、iOS
android·ios
恋猫de小郭6 小时前
超好用 R8 Configuration Analyzer, 优化你的 App 大小和内存
android·前端·flutter
又见情义6 小时前
Android 13 系统应用裁剪:RK3568平台下的精简之道
android