站点图标 高效码农

ApkClaw详解:如何让旧手机通过AI Agent听懂并执行自然语音指令?

ApkClaw:用自然语言远程操控 Android 手机的 AI Agent 实践


图片来源:Unsplash

本文要回答的核心问题:如何让一台 Android 手机像有了自己的”大脑”一样,仅凭你发去的一句自然语言消息,就能自主完成打开 App、点击按钮、滑动页面等一系列复杂操作?

ApkClaw 是一款 AI 驱动的 Android 自动化应用,它的核心理念非常直接——通过自然语言让 LLM Agent 操控 Android 设备。用户不需要写脚本、不需要连数据线、不需要懂任何编程,只需在钉钉、飞书、QQ、Discord 或 Telegram 中发一条消息,AI Agent 就会理解你的意图,然后自主在手机上执行操作。

这款产品尤其适合那些闲置的旧 Android 手机。一台 Android 9 及以上版本的备用机,装上 ApkClaw 之后,就变成了一个 24 小时待命的智能干活助手。


核心架构:一条消息如何变成手机上的实际操作?

本节要回答的核心问题:当你在一款聊天软件里发了一条”帮我打卡”,这条文字消息经过了哪些环节,最终变成了手机屏幕上的点击和滑动?

ApkClaw 的整体架构可以分为四个清晰的层次,从上到下依次是:消息渠道层、消息路由层、任务编排层和 Agent 执行层。


图片来源:Unsplash

┌───────────────────────────────────────────────────────────────┐
│                      消息渠道                                  │
│   钉钉  │  飞书  │  QQ  │  Discord  │  Telegram  │  微信        │
└──────────────────────┬────────────────────────────────────────┘
                       │ 收到消息
                       ▼
              ┌─────────────────┐
              │  ChannelManager  │  消息路由与分发
              └────────┬────────┘
                       │
              ┌────────▼────────┐
              │ TaskOrchestrator │  任务锁、生命周期管理
              └────────┬────────┘
                       │
              ┌────────▼────────┐
              │  AgentService    │  Agent 循环
              │                  │
              │  ┌────────────┐  │
              │  │  LLM 调用  │◄─┼── LangChain4j (OpenAI / Anthropic)
              │  └─────┬──────┘  │
              │        │         │
              │  ┌─────▼──────┐  │
              │  │  工具执行   │◄─┼── ToolRegistry → ClawAccessibilityService
              │  └─────┬──────┘  │
              │        │         │
              │    循环直到       │
              │    任务完成       │
              └────────┬────────┘
                       │
                       ▼
              通过渠道回复用户

第一层:消息渠道。 这是用户接触 ApkClaw 的入口。目前支持钉钉、飞书、QQ、Discord、Telegram,以及微信。每个渠道对应一套独立的协议和凭证体系——比如钉钉使用 App Stream Client,需要 Client ID 和 Client Secret;Discord 使用 Gateway WebSocket 加 REST,只需要一个 Bot Token。多渠道的设计意味着你不需要为了用 ApkClaw 而去安装一个新的 App,直接用你已经在用的聊天工具就能发指令。

第二层:ChannelManager(消息路由与分发)。 当任意一个渠道收到消息后,ChannelManager 负责把这条消息统一接进来,进行初步校验(比如检查无障碍服务是否已开启),然后传递给下一层。

第三层:TaskOrchestrator(任务编排)。 这一层做两件关键的事:第一,获取任务锁——ApkClaw 采用单任务模型,同一时间只执行一个任务,避免多个指令在手机上打架;第二,按 Home 键重置设备状态,确保每次任务都从一个干净的桌面开始,而不是在某个 App 的深层页面里。

第四层:AgentService(Agent 循环)。 这是整个系统的大脑所在,也是后文会重点展开的部分。简单说,它调用 LLM 理解指令、决定调用哪个工具、执行工具、把结果反馈给 LLM,如此循环直到任务完成。

最终,执行结果会通过你发消息的那个渠道原路返回,你在聊天窗口里就能看到任务的执行过程和最终结果。

反思: 四层架构看似不复杂,但”单任务锁 + Home 键重置”这个设计细节很值得玩味。很多自动化工具出问题,不是因为”做不对”,而是因为”状态乱了”——上一个任务停在了某个弹窗,下一个任务就从错误的状态开始。ApkClaw 在编排层就强制重置状态,把状态管理的复杂度从 Agent 层移到了编排层,这是一个很务实的工程选择。


Agent 执行流程:从收到指令到任务完成的完整链路

本节要回答的核心问题:Agent 在接到一条自然语言指令后,具体是怎么一步步”看屏幕、想对策、做动作”的?

ApkClaw 的核心执行流程可以拆解为五个阶段:

  1. 用户发送消息:通过任意已连接的渠道发送自然语言消息,比如”打开飞书并进行打卡”。
  2. 渠道校验:ChannelSetup 校验无障碍服务是否已经开启。如果没有开启,任务不会继续,因为后续所有操作都依赖无障碍服务。
  3. 任务编排:TaskOrchestrator 获取任务锁,按 Home 键把手机重置到桌面状态。
  4. Agent 循环:DefaultAgentService 进入核心的 Agent 循环,这是整个系统最关键的部分。
  5. 结果回复:任务完成后,结果通过同一渠道回复给用户。

Agent 循环内部遵循 观察 → 思考 → 行动 → 验证 的协议,每一轮循环做的事情如下:

构建上下文。 系统提示词会注入设备上下文信息,包括手机品牌、型号、Android 版本、屏幕分辨率,以及当前已注册的所有工具列表和安全约束。这些信息让 LLM “知道”自己正在操作一台什么样的设备、能用到哪些能力。

调用 LLM。 通过 LangChain4j 桥接层,把系统提示词、用户消息和工具定义一起发给 LLM。LLM 返回的不是一个纯文本回答,而是一个工具调用指令——比如”调用 tap 工具,坐标 (540, 1200)”。

执行工具。 从 LLM 响应中提取工具调用,通过 ToolRegistry 找到对应的工具实现,最终由 ClawAccessibilityService(无障碍服务)在设备上真正执行操作。

反馈与循环。 工具执行的结果(成功/失败、屏幕变化等)被反馈给 LLM,LLM 根据新的信息决定下一步操作。这个循环会一直持续,直到 LLM 主动调用 finish 工具表示任务完成,或者达到最大迭代次数(40 轮)。


图片来源:Unsplash

Agent 循环中的四个关键机制

LLM 调用重试。 网络请求不可能永远成功。ApkClaw 对 LLM 调用设置了最多 3 次重试,采用指数退避策略(1 秒 → 2 秒 → 4 秒)。但如果遇到 401(未授权)或 403(禁止访问)错误,则不进行重试——因为这两种错误通常是 API Key 配置问题,重试多少次都不会变。

死循环检测。 AI 在执行任务时可能会陷入重复操作——比如反复点击同一个位置。ApkClaw 维护了一个 4 轮的滑动窗口,记录每一轮的 (screenHash, toolCall) 指纹。如果连续 4 轮的指纹完全相同,系统会注入一条系统消息强制 Agent 换一种方式操作,打破死循环。

Token 优化。 在多轮循环中,get_screen_info 工具会频繁返回 UI 层级树数据,这些数据非常消耗 token。ApkClaw 的策略是将历史中的 get_screen_info 结果替换为占位符,仅保留最近一次的完整结果。这在长任务场景下能显著节省 token 消耗。

系统弹窗处理。getRootInActiveWindow() 返回 null 时,说明检测到了受保护的系统弹窗(比如权限确认对话框)。此时 Agent 无法读取界面也无法注入手势,于是会自动截取当前屏幕、发送给用户、并终止任务,让用户手动处理。

反思: 死循环检测和 Token 优化这两个机制,体现了”在真实设备上跑 Agent”和”在纯文本环境中跑 Agent”的本质区别。纯文本环境里 token 不够了就截断,死循环了大不了重来;但在真实设备上,死循环意味着手机一直在无意义地操作,token 暴涨意味着你的 API 账单在燃烧。这些机制不是锦上添花,而是从”能跑”到”能用在生产环境”的必要门槛。


工具系统:AI 能对手机做哪些操作?

本节要回答的核心问题:ApkClaw 的 AI Agent 到底有哪些”手和眼”,能够完成哪些类型的手机操作?

工具系统是 ApkClaw 的”手脚”。所有工具按设备类型在 ToolRegistry 中注册,每个工具继承 BaseTool,实现 execute(Map<String, Any>): ToolResult 方法,提供中英文双语描述和类型化参数声明。

工具分为两大类:通用工具和手机专属工具。

通用工具(所有设备可用)

工具 说明 场景举例
get_screen_info 获取 UI 层级树,供 AI 分析当前界面 每轮循环开始时”看”一眼屏幕上有什么
find_node_info 通过文本或资源 ID 查找元素 在当前页面找到”签到”按钮
take_screenshot 截取当前屏幕为 PNG 截图发给用户确认当前状态
input_text 向焦点输入框输入文本 在搜索框中输入”小Lin说”
open_app 通过名称打开应用 “打开抖音”
get_installed_apps 获取已安装应用列表 确认手机上是否安装了飞书
press_back 返回上一页 从子页面返回
press_home 回到桌面 重置设备状态
open_recent_apps 打开最近任务列表 切换到另一个 App
expand_notifications 展开通知栏 查看是否有新消息
collapse_notifications 收起通知栏 关闭通知栏
lock_screen 锁屏 任务完成后锁屏省电
wait 等待指定时长 等待页面加载完成
repeat_actions 重复执行一组操作 批量点赞
send_file 通过渠道发送文件给用户 把截图或日志发给用户
finish 完成任务并返回总结 告诉用户”打卡已完成”

手机专属工具

工具 说明 场景举例
tap 点击指定坐标 (x, y) 点击屏幕上的某个按钮
long_press 长按指定坐标 长按消息进行删除
swipe 从 A 点滑动到 B 点 上滑浏览抖音视频流
click_by_text 通过可见文字点击元素 点击”发送”按钮
click_by_id 通过资源 ID 点击元素 点击 com.example.app:id/submit
search_app_in_store 在应用商店中搜索应用 搜索并安装某个 App

举个具体的例子:当你发送”打开抖音,搜索小Lin说的视频进行点赞和评论”这条消息时,Agent 的实际操作链路大致是——调用 open_app 打开抖音 → 调用 tap 点击搜索框 → 调用 input_text 输入”小Lin说” → 调用 tap 点击搜索结果 → 调用 get_screen_info 确认视频已打开 → 调用 tap 点赞 → 调用 tap 打开评论区 → 调用 input_text 输入评论 → 调用 tap 发送 → 调用 finish 结束任务。

反思: 工具设计的颗粒度选择是一件很有意思的事。ApkClaw 同时提供了 tap(坐标点击)和 click_by_text(文本点击)两种方式。坐标点击更通用但更脆弱(换了分辨率就失效),文本点击更语义化但依赖 UI 节点的文本属性。两者并存,让 LLM 可以根据实际情况灵活选择,这种”给 AI 选择权而不是替它做决定”的思路,在 Agent 工具设计中值得借鉴。


LLM 集成:如何选择和配置大模型后端?

本节要回答的核心问题:ApkClaw 支持哪些大模型,如何配置它们,以及为什么 temperature 设得这么低?

ApkClaw 通过 LlmClientFactory 实现可插拔的 LLM 后端,目前支持两个提供商:

提供商 客户端类 模型构建器
OpenAI 兼容 OpenAiLlmClient OpenAiChatModel / OpenAiStreamingChatModel
Anthropic AnthropicLlmClient AnthropicChatModel / AnthropicStreamingChatModel

“OpenAI 兼容”意味着不只是 OpenAI 官方 API,任何兼容 OpenAI 接口格式的第三方服务都可以接入。这为使用国内 LLM 服务商(通常提供 OpenAI 兼容接口)留出了空间。

两个提供商均支持流式和非流式模式。在 HTTP 层,ApkClaw 使用基于 OkHttp 的自定义 OkHttpClientBuilderAdapter 替代了 LangChain4j 默认的 JDK HttpClient,原因是 JDK HttpClient 在 Android 上的兼容性不佳。

核心配置项

配置集中在 AgentConfig 中:

  • apiKey:你的 API Key,在本地设置中填写,不会上传到第三方服务器。
  • baseUrl:LLM 接口地址,默认为 https://api.openai.com/v1。如果你使用第三方兼容服务,需要修改为对应的端点地址。
  • modelName:模型名称,例如 gpt-4oclaude-sonnet-4-20250514,由用户自行选择。
  • provider:选择 OPENAI(默认)或 ANTHROPIC
  • temperature:默认 0.1。这是一个非常低的值,意味着模型输出高度确定性——对于”点击坐标 (540, 1200)”这种操作,你需要的是精确和稳定,而不是创意和发散。
  • maxIterations:最大循环轮数,默认 40。
  • streaming:是否启用流式输出,默认关闭。

LangChain4j 桥接层

ApkClaw 并没有直接使用 LangChain4j 的 @Tool 注解方式定义工具,而是自己定义了一套 BaseTool 抽象,然后通过 LangChain4jToolBridge 将其转换为 LangChain4j 的 ToolSpecification 格式。参数类型(stringintegernumberboolean)会被映射为 JSON Schema。这种桥接设计让工具定义完全掌控在 ApkClaw 自己手中,同时复用了 LangChain4j 的 Agent 编排能力。

反思: temperature 设为 0.1 这个细节,看似不起眼,实际上反映了”设备操控”和”内容生成”两种场景对 LLM 的根本不同要求。写文章时你希望 temperature 高一些让内容有灵气,但控制手机时你希望每次都点击同一个位置。很多开发者直接拿默认 temperature 0.7 去跑自动化任务,结果就是同一条指令每次执行路径都不一样,调试起来非常痛苦。


渠道系统:通过哪些平台发送指令?

本节要回答的核心问题:除了在手机上直接操作,你还能通过哪些聊天平台远程给手机下达指令?

ApkClaw 目前支持的渠道及其协议和凭证要求如下:

渠道 协议 所需凭证
钉钉 App Stream Client Client ID + Client Secret
飞书 OAPI SDK App ID + App Secret
QQ QQ Bot API App ID + App Secret
Discord Gateway WebSocket + REST Bot Token
Telegram Bot HTTP API Bot Token

每个渠道的实现位于项目的 channel/ 目录下,各自是独立的处理器模块。

以远程打卡为例:你把 Android 手机放在公司充电,连接好 Wi-Fi。哪天起晚了,不需要慌张,直接在飞书里发一条”打开飞书并进行打卡”,手机端的 ApkClaw 通过飞书渠道收到消息,Agent 自主完成打开飞书、找到打卡入口、执行打卡的全过程,然后通过飞书把结果回复给你。

再以自媒体运营为例:你在 Discord 里发送”打开抖音,搜索小Lin说的视频进行点赞和评论”,手机端的 ApkClaw 通过 Discord 渠道收到指令,自动在手机上完成搜索、点赞、评论操作。这种基于真实手机物理操作的自动化,模拟的是正常用户的操作行为,与脚本注入有本质区别。

渠道凭证有两种配置方式:一是在手机 App 的设置页中手动填写;二是通过局域网 HTTP 服务器在 PC 浏览器上配置,后文会详细介绍。

反思: 多渠道设计看似只是”多接了几个 SDK”,但它解决的是一个真实的痛点——不同团队、不同场景下常用的沟通工具不同。产品团队用飞书,技术社区用 Discord,海外用户用 Telegram,个人用户可能用 QQ。ApkClaw 不强迫用户迁移到某个特定平台,而是”用户在哪,我就在哪”,这个产品思路在 ToB/ToC 边界模糊的工具类产品中非常重要。


无障碍服务:设备交互的底层引擎与已知限制

本节要回答的核心问题:ApkClaw 在 Android 系统层面到底是通过什么机制实现点击、滑动、读取界面的?有哪些做不了的事?

ClawAccessibilityService 是整个 ApkClaw 的物理执行层,用 Java 实现,承担四类核心操作:

手势操作。 通过 dispatchGesture() 实现点击、滑动、长按。这是手机专属工具(tapswipelong_press)的底层实现。所谓的”点击坐标 (x, y)”,最终就是通过这个方法在屏幕上对应位置触发一个触摸事件。

节点遍历。 通过 getRootInActiveWindow() 获取当前界面的 UI 层级树。这就是 get_screen_infofind_node_info 的数据来源。UI 层级树包含了界面上所有可访问性节点的信息——文本内容、资源 ID、坐标范围、是否可点击等。

按键注入。 通过 performGlobalAction() 实现 Home 键、返回键、打开最近任务等系统级按键。press_backpress_homeopen_recent_apps 这几个工具的底层就是这个。

截屏。 通过 takeScreenshot() 实现屏幕截图,生成 PNG 图片。这个功能需要 Android 11 及以上版本的支持。

已知限制:系统保护窗口

Android 系统有一套安全机制叫做 filterTouchesWhenObscured。当出现某些系统保护窗口时(比如权限请求弹窗,典型的是 com.android.permissioncontroller 的权限确认对话框),这些窗口会同时阻止两件事:

  1. 节点树读取——getRootInActiveWindow() 返回 null,Agent “看”不到界面上有什么。
  2. 手势注入——dispatchGesture() 无法穿透保护窗口执行操作。

也就是说,Agent 在这种情况下既”看不清”也”摸不到”。ApkClaw 的处理策略是:检测到 getRootInActiveWindow() 返回 null 时,自动截取当前屏幕、通过渠道发送给用户、并终止当前任务,由用户手动处理这个系统弹窗。


图片来源:Unsplash

反思: 系统保护窗口的限制不是 ApkClaw 的 bug,而是 Android 的安全设计。任何基于无障碍服务的自动化方案都会遇到这个问题。ApkClaw 做得好的地方在于:它没有假装这个问题不存在,而是做了明确的检测和优雅的降级——截图通知用户,而不是卡死或者报一个让人摸不着头脑的错误。在真实使用中,这种”知道自己能做什么、不能做什么”的诚实,比”什么都想做但什么都做不好”要有价值得多。


实际应用场景:旧手机能变成什么?

本节要回答的核心问题:把一台闲置的 Android 手机装上 ApkClaw,在真实生活中到底能派上什么用场?

以下是经过实际验证或从产品能力中自然推导出的应用场景:

场景一:远程打卡

把 Android 手机放在公司,插上充电线。某天起晚了或者路上堵车,打开手机里的飞书或钉钉,发一条消息:”打开飞书并进行打卡”。ApkClaw 收到指令后,自动打开飞书 App、找到打卡入口、完成打卡操作,并把结果回复给你。

这个场景的价值在于:手机在公司、人在家里,实现了物理位置的”跨越”。传统的自动化脚本需要电脑在线才能跑,而 ApkClaw 只需要手机在线。

场景二:社交媒体自动操作

发送指令:”打开抖音,搜索小Lin说的视频进行点赞和评论”。ApkClaw 会在手机上自动打开抖音、进入搜索、找到目标视频、执行点赞和评论。

这个场景的特殊之处在于:因为操作发生在真实手机上,走的是正常的用户交互路径(点击、滑动、输入),而不是通过 API 或脚本注入,所以行为模式是合理的用户行为,不容易触发平台的风控策略。

场景三:App 抢票

很多票务平台只支持 App 端抢票,PC 端反而没有入口。ApkClaw 天然运行在手机上,直接在 App 内操作,完美适配这类场景。

场景四:App 测评自动化

如果你是产品体验官,需要对新 App 做全面的操作测试和截图记录。可以让 ApkClaw 自动打开 App、浏览各个页面、执行关键操作、截图保存,大幅减少重复性手工操作。

场景五:自媒体内容发布

自媒体运营者经常需要在抖音、小红书等多个平台发布内容。ApkClaw 可以模拟正常的手机点击行为,在各个 App 中完成打开、编辑、发布的流程。

场景六:机票酒店规划与预订

出差或出游时,经常需要在多个 App 之间查找最优路线、最合适的酒店、预估打车时间、设置闹钟提醒。这些跨 App 的重复性操作,可以一次性交给 ApkClaw 完成——它能在飞书中查行程、在酒店 App 中预订、在日历中设置提醒。

场景七:远程帮助父母操作手机

很多父母在使用智能手机办理社保、养老金等个人业务时遇到困难。子女可以通过聊天工具发送指令,远程操控父母的手机完成操作,而不需要电话里反复描述”点左边那个按钮”。

反思: 这七个场景看起来跨度很大,但有一个共同特征:它们都是”只能在手机上完成”或者”在手机上完成更自然”的操作。PC 端的自动化工具(比如传统的 RPA)在这些场景下要么完全无能为力(因为没有 App),要么需要绕很远的路(通过模拟器)。ApkClaw 直接运行在手机上这个事实,本身就是最大的竞争壁垒。手机龙虾和 PC 龙虾不是替代关系,而是互补关系。


安装配置完整指南

本节要回答的核心问题:从零开始,如何把 ApkClaw 跑起来并完成第一次任务?

环境要求

  • Java 17 及以上版本
  • Android Studio(建议 Ladybug 或更高版本)
  • Android SDK 36(编译版本和目标版本),最低支持 SDK 28(Android 9)

从源码编译

# 克隆仓库
git clone https://github.com/apkclaw-team/ApkClaw.git
cd ApkClaw

# Debug 构建
./gradlew assembleDebug

# Release 构建
./gradlew assembleRelease

如果你不想自己编译,也可以直接下载预编译的 APK 安装到设备上。

安装与授权

将 APK 安装到 Android 9 及以上版本的设备后,打开 App,在首页依次开启以下权限:

  • 无障碍服务:这是最核心的权限,所有设备交互都依赖它。
  • 通知权限:用于接收渠道消息。
  • 悬浮窗权限:用于显示悬浮球等 UI 组件。
  • 电池白名单:防止系统因省电策略杀掉后台服务。
  • 文件访问权限:用于截图保存和文件发送。

配置 LLM

进入 设置 > LLM Config,填写以下信息:

  • API Key:你的 OpenAI 或 Anthropic 的 API Key。
  • Base URL:LLM 接口地址。如果直接使用 OpenAI 官方,保持默认的 https://api.openai.com/v1 即可;如果使用第三方兼容服务,修改为对应的端点地址。
  • Model Name:填写你想使用的模型名称,例如 gpt-4oclaude-sonnet-4-20250514

配置消息渠道

进入设置页面,选择至少一个消息渠道,填写对应的机器人凭证。以 Telegram 为例,只需要填写一个 Bot Token 即可。

发送第一条指令

配置完成后,通过已配置的渠道发送一条简单的消息试试,比如”截一张图发给我”或者”打开设置”。如果一切配置正确,你应该能在聊天窗口中收到 Agent 的执行结果。


局域网配置服务器:用 PC 浏览器管理手机

本节要回答的核心问题:不想在手机的小屏幕上输入长长的 API Key 和 Token,有没有更方便的配置方式?

ApkClaw 内置了一个基于 NanoHTTPD 的 HTTP 服务器,运行在端口 9527。开启方法很简单:在设置中打开”LAN Config”开关,然后在 PC 浏览器中访问 http://<设备IP>:9527

这个服务器提供了以下接口:

端点 方法 用途
/ GET 配置页面(一个 Web UI)
/api/channels GET 读取渠道凭证(敏感信息脱敏,仅显示末尾 4 位)
/api/channels POST 更新渠道凭证
/api/llm GET 读取 LLM 配置(敏感信息脱敏)
/api/llm POST 更新 LLM 配置

在 GET 请求返回数据时,所有敏感信息(如 API Key、Token)都会做脱敏处理,只显示末尾 4 位字符,防止在浏览器中意外泄露。

此外,Debug 构建版本还额外提供了一个 /debug.html 工具调试控制台,可以在浏览器中直接测试各个工具的执行效果,非常适合开发和调试阶段使用。

反思: 局域网配置服务器这个功能,典型地体现了”以用户为中心”的设计思维。从技术角度看,在手机 App 里加几个输入框是最简单的实现方式;但从用户角度看,在手机上复制粘贴几十个字符的 API Key 是一种糟糕的体验。一个轻量的 HTTP 服务器(NanoHTTPD 整个体积很小),换来的是配置效率的巨大提升。而且脱敏设计也说明开发者对安全性有基本的意识——不是”能跑就行”,而是”跑起来也要安全”。


项目结构与主要依赖

本节要回答的核心问题:ApkClaw 的代码是怎么组织的,背后依赖了哪些关键技术栈?

项目目录结构

app/src/main/java/com/apk/claw/android/
├── agent/                  # Agent 循环、配置、回调
│   ├── langchain/          # LangChain4j 桥接层 & OkHttp 适配器
│   └── llm/                # LLM 客户端 (OpenAI, Anthropic)
├── base/                   # BaseActivity(屏幕密度适配)
├── channel/                # 消息渠道处理器
│   ├── dingtalk/
│   ├── feishu/
│   ├── qqbot/
│   ├── discord/
│   └── telegram/
├── floating/               # 悬浮球 UI 管理
├── server/                 # 局域网配置 & 调试 HTTP 服务器
├── service/                # 无障碍服务、前台服务、保活服务
├── tool/                   # 工具抽象层 & 注册中心
│   └── impl/               # 工具实现 (通用/手机/电视)
├── ui/                     # Activity(启动页、首页、引导页、设置)
├── utils/                  # KVUtils, XLog, 格式化工具
└── widget/                 # 自定义 UI 组件

结构清晰,模块边界明确。agent/ 负责 AI 大脑,channel/ 负责消息入口,tool/ 负责手脚,service/ 负责系统级能力,server/ 负责辅助配置。

主要依赖

AI / Agent 层

依赖 版本 用途
LangChain4j 1.12.2 Agent 编排、工具定义、LLM 集成

消息渠道层

依赖 版本 用途
DingTalk Stream Client 1.3.12 钉钉渠道接入
Feishu OAPI SDK 2.5.3 飞书渠道接入

网络层

依赖 版本 用途
OkHttp 4.12.0 HTTP 客户端,用于 LLM 调用
Retrofit 2.11.0 REST API 客户端
NanoHTTPD 2.3.1 局域网配置与调试 HTTP 服务器

存储与工具层

依赖 版本 用途
MMKV 2.3.0 高性能本地键值存储
Gson 2.13.2 JSON 序列化与反序列化
ZXing 3.5.3 二维码生成
UtilCode 1.31.1 Android 通用工具函数库

UI 层

依赖 版本 用途
Glide 5.0.5 图片加载
EasyFloat 2.0.4 悬浮窗管理
MultiType 4.3.0 RecyclerView 多类型适配器

整体技术栈的选择很务实:LangChain4j 做 Agent 编排省去了大量造轮子的工作,OkHttp 替代 JDK HttpClient 解决了 Android 兼容性问题,MMKV 替代 SharedPreferences 提升了存储性能,NanoHTTPD 用极小的代价实现了局域网配置服务器。


反思与总结

本节要回答的核心问题:ApkClaw 这类”手机端 AI Agent”产品的本质价值是什么,它的局限和发展方向在哪?

写完以上所有技术细节后,我想退一步谈谈对这类产品的整体认知。

ApkClaw 的本质不是”一个能控制手机的脚本”,而是把大语言模型的推理能力延伸到了物理设备上。LLM 本身只能输出文本,但通过 ApkClaw 的工具系统,LLM 的文本输出被翻译成了屏幕上的点击和滑动。这个”翻译层”看似简单(就是一个工具调用映射),但它打通的是数字世界和物理世界的边界。

从工程角度看,ApkClaw 在几个关键点上做了正确的选择:

  • 单任务模型避免了多任务并发时设备状态混乱的问题。
  • Home 键重置把状态管理从 Agent 层提升到了编排层。
  • 死循环检测和 Token 优化让系统在真实设备上长时间运行成为可能。
  • 系统弹窗的优雅降级体现了对自身能力边界的诚实。
  • 多渠道接入降低了用户的使用门槛。

当然,局限性也很明显:系统保护窗口无法自动处理、单任务模型限制了并发能力、40 轮迭代上限对特别复杂的任务可能不够、对 LLM 的推理能力有较高依赖(模型不够聪明时工具调用会出错)。

但从”让旧手机变成智能助手”这个定位来看,ApkClaw 找到了一个精准的切入点——不需要最新的旗舰机,不需要 root,不需要复杂的环境配置,一台 Android 9 的备用机加上一个 API Key 就能跑起来。这个低门槛,是它相比 PC 端自动化方案最核心的差异优势。


实用摘要 / 操作清单

从零开始使用 ApkClaw,按以下顺序操作:

  1. 准备一台 Android 9 及以上版本的手机
  2. 安装 ApkClaw APK(自行编译或下载预编译版本)
  3. 在首页依次开启:无障碍服务、通知权限、悬浮窗权限、电池白名单、文件访问权限
  4. 进入设置 > LLM Config,填写 API Key、Base URL、Model Name
  5. 进入设置,选择至少一个消息渠道,填写对应凭证
  6. 通过已配置的渠道发送第一条测试消息
  7. (可选)在设置中开启 LAN Config,通过 PC 浏览器访问 http://<设备IP>:9527 进行配置

一页速览

维度 内容
产品定位 AI 驱动的 Android 自动化 Agent,通过自然语言远程操控手机
最低系统要求 Android 9(SDK 28)
支持 LLM OpenAI 兼容接口、Anthropic
Agent 框架 LangChain4j 1.12.2
支持渠道 钉钉、飞书、QQ、Discord、Telegram
工具数量 通用工具 15 个 + 手机专属工具 6 个
最大迭代轮数 40 轮
LLM 重试策略 3 次指数退避(1s→2s→4s),401/403 不重试
死循环检测 4 轮滑动窗口指纹比对
局域网配置 端口 9527,Web UI + REST API
已知限制 系统保护窗口无法自动处理,单任务并发
开源协议 Apache License 2.0

常见问答

ApkClaw 支持 iOS 吗?
目前不支持,仅支持 Android 9 及以上版本的设备。

必须使用 OpenAI 官方 API 吗?
不一定。ApkClaw 的 OpenAI 客户端兼容所有 OpenAI 接口格式的服务,你可以使用第三方兼容服务商的端点地址。

同时能执行多个任务吗?
不能。ApkClaw 采用单任务模型,同一时间只执行一个任务,新任务需要等待当前任务完成。

系统权限弹窗怎么办?
Agent 检测到系统保护窗口时会自动截图发送给你,并终止当前任务,由你手动处理弹窗后可以继续发送下一条指令。

局域网配置服务器安全吗?
GET 请求返回的敏感信息(API Key、Token)会做脱敏处理,仅显示末尾 4 位字符。建议仅在可信的局域网环境中使用。

不配置消息渠道能直接在手机上用吗?
ApkClaw 的设计是通过消息渠道发送指令,不配置渠道则无法接收和执行任务。

最多能循环多少轮?
默认最大迭代次数为 40 轮。如果 40 轮内 LLM 没有调用 finish 工具,任务会被强制终止。

temperature 为什么默认 0.1?
设备操控需要高度确定性的输出,低 temperature 能确保同样的屏幕状态和指令产生一致的工具调用,避免操作路径随机化。

退出移动版