借助 AppFunctions,您的 Android 应用可以分享特定的功能,供系统和各种 AI 智能体及助理发现和调用。通过定义这些功能,您可以让应用向 Android 操作系统提供服务、数据和操作,从而让用户能够通过 AI 代理和系统级互动完成任务。
AppFunctions 相当于 Model Context Protocol (MCP) 中的移动版工具。虽然 MCP 传统上会标准化智能体连接到服务器端工具的方式,但 AppFunctions 为 Android 应用提供了相同的机制。这样,您就可以将应用的功能作为可编排的“工具”公开,授权的应用(调用方)可以发现并执行这些工具,以实现用户意图。调用方必须具有 EXECUTE_APP_FUNCTIONS 权限才能发现和执行 AppFunction,并且可以包括代理、应用和 AI 助理(例如 Gemini)。
AppFunctions 适用于搭载 Android 16 或更高版本的设备。
用例示例
AppFunctions 提供了一种强大的机制来自动执行任务并简化用户互动。通过公开应用的功能,您可以让用户使用自然语言完成复杂的目标,从而通常无需通过界面进行逐步手动导航。
以下场景说明了如何使用 AppFunctions 在各种应用类别中打造体验:
- 任务管理和工作效率
- 用户请求:“提醒我今天下午 5 点在工作场所取包裹”。
- AppFunction 操作:调用方识别相关的任务管理应用,并调用一个函数来创建任务,根据用户的提示自动填充标题、时间和位置字段。
- 媒体和娱乐
- 用户请求:“创建一个包含今年热门爵士专辑的新播放列表”。
- AppFunction 操作:调用方在音乐应用中执行播放列表创建函数,传递“2026 年热门爵士专辑”等上下文作为查询,以立即生成并启动内容。
- 跨应用工作流程
- 用户请求:“查找 Lisa 的电子邮件中的面条食谱,并将食材添加到我的购物清单”。
- AppFunction 操作:此请求使用来自多个应用的功能。首先,调用方使用电子邮件应用的搜索功能检索内容。然后,它会提取相关食材,并调用购物清单应用的功能来填充用户的清单。
- 日历和日程安排
- 用户请求:“将妈妈的生日派对添加到我的日历中,时间是下周一下午 6 点”。
- AppFunction 操作:经批准的智能应用调用日历应用的“创建活动”函数,解析“下周一”和“下午 6 点”等相关情境,以创建条目,而无需用户手动打开日历。
AppFunction 的运作方式
AppFunctions 是一项 Android 16 平台功能以及一个配套的 Jetpack 库,可让应用公开特定功能,以便调用方(例如代理应用)在设备上访问和执行这些功能。
下图展示了应用如何将 AppFunction 共享给代理并随后执行的典型流程。代理在处理用户请求时,可能会同时考虑服务器端远程 MCP 工具和本地 AppFunctions。使用本地 AppFunctions 的详细流程如下:
- AppFunction 声明:Android 应用构建为公开其 AppFunction,例如“创建笔记”或“发送消息”。
- 架构生成:AppFunctions Jetpack 库会生成一个 XML 架构文件,其中列出了应用中所有已声明的 AppFunctions。Android 操作系统会使用此文件来为可用的 AppFunctions 编制索引。
- 元数据检索:代理可以通过查询来检索 AppFunction 元数据。
- AppFunction 选择和执行:根据用户提示,代理将选择并执行具有相应形参的相应 AppFunction。
AppFunctions Jetpack 库可简化应用功能的公开。借助注释处理器,开发者可以为要公开的函数添加注释。然后,调用方可以使用 AppFunctionManager 发现并调用这些已编入索引的函数。
您的应用无需验证是否支持 AppFunction 功能;Jetpack 库会自动处理此问题。例如,AppFunctionManager 可以验证相应功能是否受支持。
以下示例展示了具有创建、修改和列出笔记功能的一款记事应用的 AppFunctions。
class NoteFunctions(
private val noteRepository: NoteRepository
) {
/**
* A note.
*
* @param id The note's ID.
* @param title The note's title.
* @param content The note's content.
*/
@AppFunctionSerializable(isDescribedByKDoc = true)
data class Note(val id: Int, val title: String, val content: String)
/**
* Lists all available notes.
*
* @param appFunctionContext The context in which the AppFunction is executed.
*/
@AppFunction(isDescribedByKDoc = true)
suspend fun listNotes(appFunctionContext: AppFunctionContext): List<Note>? {
return if (noteRepository.appNotes.isEmpty()) null else viewModel.appNotes
}
/**
* Adds a new note to the app.
*
* @param appFunctionContext The context in which the AppFunction is executed.
* @param title The title of the note.
* @param content The note's content.
*/
@AppFunction(isDescribedByKDoc = true)
suspend fun createNote(
appFunctionContext: AppFunctionContext,
title: String,
content: String
): Note {
return noteRepository.createNote(title, content)
}
/**
* Edits a single note.
*
* @param appFunctionContext The context in which the AppFunction is executed.
* @param noteId The target note's ID.
* @param title The new title if it should be updated.
* @param content The new content if it should be updated.
*/
@AppFunction(isDescribedByKDoc = true)
suspend fun editNote(
appFunctionContext: AppFunctionContext,
noteId: String,
title: String?,
content: String,
): Note? {
return noteRepository.updateNote(noteId, title, content)
}
}