乐于分享
好东西不私藏

Android MCP时刻你的App开始给自己打工了

Android MCP时刻你的App开始给自己打工了

Android 开发者的 AppFunctions:Android 移动应用的 MCP 时刻

Android 开源社区最抢眼的不是什么聊天机器人 UI,而是 AppFunctions——Android 针对每个移动团队都可能面临的问题给出的早期答案:你的应用应该允许智能体(Agent)做些什么?

有意思的点不在于 Android 又搞了个 AI API,而在于 Android 应用可能很快需要把自己的操作描述成安全、类型化的工具。

简单来说:Android 正在构建一个 OS 层面的机制,让应用可以暴露一些小巧、类型化的操作,让智能体能够在设备上发现并运行它们。Android AppFunctions 概览 说得很明白,AppFunctions 让应用可以向“内置于 Android 操作系统中的注册表”提供“服务、数据和操作”,这样用户就能通过智能体和系统级交互完成任务。同一页面还将 AppFunctions 比作模型上下文协议(Model Context Protocol)中的工具,只不过它用的是 Android 原生的钩子,是在本地执行,而不是只通过云端的工具来跑。

正因如此,我觉得这就像 Android 移动应用的“MCP 时刻”。不是说 API 完全一样,而是这个模式似曾相识:智能体选一个工具,填好结构化参数,然后让这个工具的所有者去执行工作。移动端的不同之处在于,这个工具可以是属于应用的代码,运行在本地状态、账户上下文、权限、离线行为和用户信任边界附近。

时间点也很重要。Android 16 已经上线,AppFunctions 的文档写着这个 API 可在运行 Android 16 或更高版本的设备上使用。目前还处于早期阶段的是更广阔的智能体故事:截至2026年5月,Gemini 集成还在与受信任的测试者进行私人预览,AppFunctions 本身也仍被标注为实验性预览。所以,操作系统层面的要求已经就绪,但 API 的形状、权限和助手行为仍可能变化。Google 还发布了 AppFunctions 示例应用 和 AppFunctions 智能体技能,这让人觉得它瞄准的是 Android 开发者,而不仅仅是平台团队。

如果你在开发 Android 应用,这事关重大,因为智能体操作正在成为一个应用架构问题,而不仅仅是一个助手功能。难点不在于加个注解。难点在于,你得决定你产品的哪些部分应该变得可调用,哪些部分应该只生成草稿,哪些部分永远不应该通过智能体来执行。

我的看法:不要只把 AppFunctions 当成“给你的应用加个 AI”。把它们当作一条新的产品边界。问题不仅仅在于智能体能不能调用你的应用,更在于你的应用应该安全地暴露哪些操作

这样,移动 AI 的故事就从:

助手可以谈论你的应用。

变成了:

助手可以通过系统拥有的边界,要求你的应用做一个具体的事情。

这就把助手的角色从“导航”推进到了“执行”,而移动端产品设计的难度也正在于此。


为什么 Android 开发者应该关注

简短的回答是:现在就开始研究它,因为 Android 16 已经上线,但先别把它当成一个广泛的生产级智能体渠道。

最明显的信号是,官方文档不光是在描述一个助手功能,而是在描述一个开发者的集成面

这让你可以将应用的能力作为可编排的“工具”暴露出来,授权的应用(调用者)可以发现并执行这些工具,以实现用户的意图。

这句话道出了全貌。Android 应用可以暴露能力作为工具,但调用者仍然需要平台权限。这可不只是一句关于 Gemini 的营销口号。

Jetpack 的发布说明则让开发者角度更加清晰。库的描述说,AppFunctions 让应用能够与 AI 助手共享功能和数据,“使它们能够直接在设备上发现并执行任务,以满足用户请求。”这不仅仅是 API 的管道工程。最近的 Alpha 版本说明覆盖了 Android 开发者实际需要的东西:针对 IntString 参数的约束、面向 LLM 的自然语言描述、智能体应用内部的用户可见描述、返回文件的 URI 授权,以及通过 AppFunctionTestRule 的 Robolectric 支持。

所以,这项工作不是“加个 AI”,而是更具体的:

  • 识别出哪些应用工作流应该是可调用的
  • 将输入和输出建模成类型化函数
  • 写一些足够好的描述,让智能体能正确选择
  • 决定哪些操作需要确认
  • 在真正的智能体依赖它之前,测试应用函数的边界

Google 自己的 AppFunctions 示例仓库 也印证了这点。示例是一个聊天应用,它提供了发送消息、搜索联系人和发起通话的 AppFunctions。这些可不是玩具示例。它们是真实的产品操作,一旦执行错误,后果会很严重。


一个实用的 AppFunctions 检查清单

如果我要为一个真实的应用评估 AppFunctions,在大量写代码之前,我会先对照这个清单检查一遍:

  1. 列出那些反复出现的、且已经映射到明确应用操作的用户意图。
  2. 从可逆或可审查的操作开始,而不是高风险的提交。
  3. 用狭窄的类型化输入和明确的结果类型来建模每个函数。
  4. 写出的描述能帮助智能体选择正确的函数,而不是营销文案。
  5. 对风险较高的工作流,将“准备”和“提交”步骤分开。
  6. 当操作影响到另一个人、涉及金钱、安全或公开内容时,要求用户确认。
  7. 明确要求指定账户、工作区和租户。
  8. 在智能体依赖函数之前,就决定好离线行为和同步行为。
  9. 围绕函数边界添加测试,包括错误的调用者、缺少参数和状态模糊的情况。
  10. 用用户和支持团队都能理解的方式记录智能体触发的操作。

这个清单是故意搞得有些乏味的。AppFunctions 之所以有趣,是因为它让应用的能力变得可调用,但信任来自于小而简单、可预测、建模良好的操作。


为什么它吸引了我的注意

很多移动设备上的 AI 功能,感觉仍然像是在真实应用上糊了一层东西。它们能摘要、重写或搜索,但一到执行环节就卡壳。助手让用户打开应用,应用自己再建个助手界面,或者后台工具调用一个没有本地应用上下文的 API。

AppFunctions 则给出了一种更清晰的模式:用户用自然语言表达,而应用则继续拥有对操作的控制权。


AOSP 告诉我们的

公开的 Android 文档给出了高层级的介绍,但 AOSP 让架构更容易理解。AppFunctionManager 指出,大多数开发者应该使用 AppFunctions SDK 来获得类型安全的模式、参数类和返回值。在内部,这些 SDK 类型会变成 ExecuteAppFunctionRequest 参数和 ExecuteAppFunctionResponse 结果文档。

核心流程很简单:

  1. 应用定义 AppFunctions 和静态元数据。
  2. 调用者通过元数据发现可用的函数。
  3. 调用者构建一个 ExecuteAppFunctionRequest
  4. Android 通过 AppFunctionManager 来路由调用。
  5. 应用的 AppFunctionService 执行这个操作。

AOSP 的 Javadoc 示例是一个笔记应用。助手试图执行“把 XYZ 保存到我的笔记里”,它找到一个笔记添加函数,构建一个请求,然后执行它。关键不在于笔记应用本身,而在于这个抽象层级:助手不是在截屏抓取 UI,而是在调用一个声明过的应用能力

服务端部分在 AppFunctionService 里。它是一个绑定服务,受到 android.permission.BIND_APP_FUNCTION_SERVICE 保护,AOSP 将其定义为签名权限。随便一个调用者是不能直接绑定到应用函数服务的。系统会坐在中间当裁判。


一图胜千言:架构概览

从高层来看,我认为 AppFunctions 有四个层次:

用户意图
  "在我的购物清单上添加燕麦奶"


智能体或助手
  选择一个函数并填充参数


Android AppFunction 管理器
  检查调用者元数据启用状态和用户边界


目标应用服务
  运行应用自己的代码操作本地应用状态

这跟很多人已经知道的 LLM 系统中的工具调用模式很接近,但有一点移动端的区别:这里的工具是本地应用代码,而不仅仅是远程服务器。

AppFunctions 概览 直接做了同样的比较。它把 AppFunctions 称为模型上下文协议中工具的移动端等价物,但也指出标准的 MCP 是平台无关、通常基于云端的,而 AppFunctions 是 Android 操作系统层面的钩子,在本地执行。

如果操作依赖于本地认证、应用设置、离线状态、最近的本地缓存、账户选择或设备拥有的权限,那么在应用内部执行通常比绕道云端工具要干净得多。


一个小例子

想象一个杂货应用,它暴露了一个添加商品的函数。

这个属于应用的函数用 Jetpack 库的形式可能会大致长这样:

classGroceryFunctions(
    private val repository: GroceryRepository,
) {
    @AppFunction
    suspend fun addGroceryItem(
        itemName: String,
        quantity: Int =1,
        listName: String ="Default",
    ): AddGroceryItemResult {
        val item = repository.addItem(
            listName = listName,
            name = itemName,
            quantity = quantity,
            source ="app_function",
        )
        return AddGroceryItemResult(
            itemId = item.id,
            visibleName = item.name,
            listName = listName,
        )
    }
}

这是伪代码,不是一个完整的、可以编译的示例。一个真实的应用还会加上 AppFunctionContext、可序列化的参数和结果类型、更好的描述、约束、错误处理和测试。Jetpack AppFunctions 参考 提到,编译器会生成一个 XML 文件来描述 @AppFunction 注解的函数的签名,并提供基础设施来通过 android.app.appfunctions.AppFunctionService 暴露它们。

生成的这个元数据才是最有意思的部分。助手不需要知道杂货应用的内部 UI。它只需要知道存在一个函数、需要哪些参数、以及会返回什么结果。

用户可以说:

在我的 Costco 清单上加两盒燕麦奶。

助手会把它映射成:

{
  "function": "addGroceryItem",
  "parameters": {
    "itemName": "oat milk",
    "quantity": 2,
    "listName": "Costco"
  }
}

应用仍然拥有最终的行为控制权。它可以决定哪个账户是激活的、清单是否存在、同步应该如何工作、撤销应该如何工作、以及下次用户打开应用时应该显示什么。

这就是我喜欢的地方。助手负责处理意图。应用则继续拥有产品逻辑。


为什么这不仅仅是深度链接

Android 已经有意图(Intent)、应用链接(App Link)、快捷方式(Shortcut)、微件(Widget)、切片(Slice)和无障碍服务了。所以有理由问:为什么还要再加一个机制?

AppFunctions 解决的是另一个问题。

深度链接擅长导航。它们回答的是:“这个用户应该去哪里?”

AppFunctions 是关于类型化执行的。它们回答的是:“应该执行哪个属于应用的操作,输入什么结构化参数,以及在什么调用者权限下执行?”

对于 AI 智能体来说,这个区别很重要。自然语言必须变成可执行的东西。如果唯一的目标是一个 URL 或一个屏幕,助手仍然需要依赖应用的 UI 来完成整个任务。如果目标是一个带有元数据的类型化函数,助手就能选择更精确的操作。

一个有用的思维模型:

  • 意图或应用链接: 把用户带到正确的表面。
  • 快捷方式: 暴露一个常见的用户操作。
  • AppFunction: 暴露一个类型化的操作,智能体可以发现、填充并执行它。

这些机制可以协同工作。一个安全的 AppFunction 可能直接执行操作并返回结果。一个风险较高的 AppFunction 可能创建一个草稿,并用深度链接把用户带去确认界面。


安全边界才是产品

这个系统最重要的部分不是那个注解,而是围绕执行的安全边界。

AOSP 为这个准备了单独的权限。在 AndroidManifest.xml 中,EXECUTE_APP_FUNCTIONS_TRUSTED 是为那些能够代表用户行事、并具有系统隐私保证的受信任应用定义的。EXECUTE_APP_FUNCTIONS 则被记录为一个系统 API 权限,供预装或具有 ASSISTANT 角色的系统应用使用。

这告诉我,Android 并没有把这事当作“任何应用都可以调用其他应用的私有工具。”它更接近于一个有中介的智能体边界

这个边界很重要,因为智能体操作的风险特征与普通导航不同。一个深度链接可以打开一个编辑界面。一个 AppFunction 可能会直接发送消息。一个快捷方式可以启动一个任务。一个 AppFunction 可能会用从对话中推断出的参数来完成它。

所以,应用需要决定哪些函数应该立即执行、需要确认、只暴露读取权限、返回一个草稿,还是生成一个审计轨迹。平台会为执行做中介,但产品团队仍然需要为他们领域内的确认、撤销和信任体验负责。

这正是良好的应用设计比花哨的 AI 管道工程更重要的时候。


一个更好的例子:消息草稿

一个消息应用可以暴露两个不同的函数:

@AppFunction
suspend fun createDraftMessage(
    recipient: ContactRef,
    body: String,
): DraftMessageResult

@AppFunction
suspend fun sendMessage(
    draftId: String,
): SendMessageResult

第一个函数风险较低。它只是创建一个草稿。第二个函数风险较高。它会发送消息。

助手可以帮助用户说:

告诉 Alex 我会晚到10分钟,但语气要客气点。

更安全的流程是:

  1. 助手调用 createDraftMessage
  2. 应用返回一个草稿 ID 和预览文本。
  3. 应用或助手请求用户确认。
  4. 只有到那时,sendMessage 才会运行。

这种拆分给了产品一个清晰的安全策略边界。创建草稿是智能体友好型的。发送消息则需要用户确认。

这应该是 AppFunctions 鼓励的设计:不是“让 AI 做所有事”,而是“让正确的应用操作在正确的护栏下变得可调用。”


哪些地方可能会变得棘手

我喜欢这个方向,但难点也是实实在在的。

  • 发现质量很重要。 如果函数的名字含糊、描述很弱,智能体就会选错。Jetpack 的发布说明已经提到了面向 LLM 的自然语言描述,这说明元数据质量是设计的一部分,而不是事后才想到的。
  • 确认体验会很困难。 “添加一个商品”和“转账”不应该感觉一样。
  • 账户、离线和策略行为仍然属于应用。 工作区、租户、同步队列、托管设备和工作资料都需要显式处理。OS 的边界并没有取消产品层面的决策。
  • 私人预览意味着公开的故事还没讲完。 Android 16 已经上线,但 Gemini 集成仍在与受信任的测试者进行私人预览。开发者可以准备,但这还没有到每个已安装的助手都能广泛生产访问的地步。

我会先暴露什么

对于大多数 Android 开发者,我会建议密切关注并轻量原型实践。现在还不到围绕它重构应用的时候。Android 16 已经上线,但公开文档仍说 Gemini 集成在私人预览中,依赖也还是 Alpha 阶段。

不过,如果应用有明确、重复、属于用户自己的操作(笔记、待办事项、消息、购物清单、预约、媒体搜索或企业状态更新),我会花一天时间来梳理一下真实应用的工作流。

给 Android 开发者的要点很简单:AppFunctions 让你的核心工作流对系统变得可理解。如果智能体界面在 Android 上发展起来,那么拥有干净、类型化、描述良好的函数的应用,会比那些只暴露屏幕的应用更容易被智能体使用。

如果今天要给一个真实应用添加 AppFunctions,我会从那些无聊的、可逆的操作开始:

  • 创建一条笔记草稿
  • 添加一个待办事项
  • 搜索本地应用内容
  • 在应用内创建一个类似日历的占位
  • 摘要一条属于应用的记录
  • 附加一个标签
  • 准备一个可分享的草稿

我会避免一开始就触碰不可逆的操作:

  • 转账
  • 删除数据
  • 给另一个人发消息
  • 更改安全设置
  • 发布公开内容
  • 邀请团队成员

对于高风险操作,我会把 API 拆成两步:准备,然后确认。这就是同一个检查清单的产品版本:让智能体有用,但把最终的信任边界保持可见。

@AppFunction
suspend fun prepareRefund(
    orderId: String,
    reason: String,
): RefundDraft

@AppFunction
suspend fun submitRefund(
    refundDraftId: String,
): RefundResult

这种两步的形状没那么神奇,但信任起来要容易得多。


结论

AppFunctions 之所以有趣,是因为它让 AI 集成感觉再次变成了一个移动架构问题

那些棘手的问题我们都熟悉:数据源、活跃账户、离线行为、确认、局部失败、用户反馈和审计日志。智能体并不会消除这些问题。它只会让它们变得更加显眼。

在这里成功的应用,不会是 AI 功能最多的那些。它们会是那些在智能体界面在 Android 上成为常态之前,就以正确的护栏暴露了正确操作的应用。


延伸阅读

有用的来源:

  • Android AppFunctions 概览:产品模型,Android 16 可用性,与 MCP 的比较,Gemini 私人预览说明,示例和智能体技能链接。
  • 向你的应用添加 AppFunctions API:设置流程,编译 SDK 要求,KSP 设置和 Jetpack 依赖。
  • Jetpack AppFunctions 发布说明:Alpha 历史,参数约束,LLM 描述,URI 授权和测试辅助工具。
  • Android AppFunctions 示例:官方示例仓库,包含一个聊天应用示例。
  • AOSP AppFunctionManager:平台 API 形状和笔记助手示例。
  • AOSP 应用函数权限:绑定和执行权限。

如果这篇文章对你有用,欢迎 请我喝杯咖啡 ☕。如果你有问题、指正,或者有产品想让我下次分析,请留言评论。

原文链接https://seankim.dev/blog/appfunctions-for-android-developers-androids-mcp-moment-for-mobile-apps/