news 2026/9/28 18:42:11

移动端自动化新范式:谷歌ARTEMIS如何让AI像人一样操作手机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
移动端自动化新范式:谷歌ARTEMIS如何让AI像人一样操作手机

做了七八年移动端自动化,我越来越确信一件事:把“点击屏幕上第三个商品”写成脚本很容易,让机器自己看懂什么叫“第三个商品”,才是真正难的地方。传统 UI 自动化工具在这个问题上努力了很多年,始终绕不开一个死结——它们依赖的界面结构,跟人眼看到的界面,根本不是一回事。ARTEMIS 是谷歌最近开源的一个移动端 AI 自动化框架,它想解决的就是这个死结:让 AI 助手像人一样操作手机,而不是像脚本一样机械执行坐标。

这篇文章适合三类人。第一类是移动端测试开发,天天写 UIAutomator、Appium 脚本,被版本迭代和界面变动折磨;第二类是正在做 AI Agent 应用的人,想找一个可靠的移动端“手脚”去落地你的“大脑”;第三类是纯好奇的爱好者,想看看所谓“AI 操作手机”到底是真的智能,还是又一个 PR 视频。我会把这套框架的原理、本地跑通路径和实测中踩过的坑一次讲清楚,全程不回避问题。

1. 为什么移动端自动化卡在了“看懂屏幕”这一步

1.1 传统自动化工具的三个共同短板

先别急着聊 ARTEMIS 有多强,得先弄清楚它要替代的是什么。过去十年,移动端自动化基本被三个技术路线统治:基于控件树的 UIAutomator、基于坐标和截图的 Image Recognition、以及基于无障碍服务的 AccessibilityService。这套组合拳看起来很完整,但实际用起来各有各的窝囊。

基于控件树的问题在于,它只能识别“愿意暴露自己”的控件。原生 TextView、Button 这种好办,到了 Flutter、游戏引擎或者大量自定义绘制的界面,整个视图树要么是空的,要么是几块巨大的空白区域。你 dump 出来的 XML 和用户看到的屏幕,完全对不上。

坐标方案就更脆弱了。脚本写死(540, 1200)这个位置,换一台分辨率不同的手机就废了;即使同一台手机,开了单手模式、弹出键盘、或者出现一个系统悬浮窗,坐标整体下移,点击全部错位。更别提很多 App 有开屏动画和过渡动画,脚本辛辛苦苦等了个固定时间,动画还没走完,下一步操作就已经发出去。

最隐蔽的短板是“状态机思维”。传统脚本本质上是预设路径:从 A 点走到 B 点,中间遇到什么情况都写在代码里。一旦出现没有预判到的弹窗、网络延迟导致的加载态、或者某个按钮文案从“立即购买”改成“马上抢”,脚本就当场死亡。测试工程师常年干的一件事,就是给脚本打补丁——这个地方加个if,那个地方加个sleep——而不是让脚本“自己看情况办”。

1.2 “像人一样操作”到底意味着什么

人是怎么操作手机的?看到屏幕,理解当前状态,结合任务目标决定下一步动作,执行,然后观察结果,错了再纠正。这个过程和写脚本有本质区别:脚本是“我早就知道要怎样”,人是“我根据现场情况决定怎样”。

ARTEMIS 想做的,就是把这套人类行为模型搬到自动化框架里。它不再要求你预先定义每一步动作,而是给 AI 一个任务目标,比如“帮我在备忘录里创建一条关于项目周报的提醒”,然后由 AI 自己去看屏幕、想办法、执行、反馈、修正。整个链路可以拆成四个环节:感知界面、推理规划、执行动作、观察结果。

这个思路在 LLM 大规模普及之前其实很难落地。原因很简单:传统算法做界面语义理解的能力太弱了。你让一套规则引擎去分析“当前屏幕是一个商品列表,第三件商品在促销”,它能做到,但成本极高,而且换个 App 就全部推翻。大语言模型出现之后,“理解截图 + 理解自然语言指令”变成了一个通用能力,ARTEMIS 这类框架的价值才真正被释放出来。

2. ARTEMIS 的核心链路:从屏幕像素到可执行动作

2.1 感知层:UI 状态不是一张截图那么简单

ARTEMIS 要解决的第一个问题是:AI 怎么“看懂”手机屏幕。大多数人对这件事的理解是“给模型截个图”,这远远不够。

截图只是一个像素矩阵,模型虽然能看图,但有几个致命弱点。第一,像素级别的信息量太大,整张截图直接塞进模型,推理延迟和 token 成本都不可接受;第二,纯视觉理解容易出错,尤其是面对小字号的灰色提示、被折叠的菜单、状态栏和系统图标这类区域,模型经常看错;第三,很多 App 的界面状态并不是静态的,列表在滚动、进度条在转、弹窗在冒出来,单张截图根本反映不了。

所以 ARTEMIS 的感知层通常会做两个动作。一个是抓取视图树,也就是通过无障碍服务拿到当前界面的控件层级和布局信息,把“屏幕上有哪些可交互元素”这件事结构化成文本或者更高层的语义描述;另一个是结合截图,针对视图树缺失的场景做兜底。你可能会问,视图树不是刚才还说不可靠吗?对,所以更合理的设计是把两者合并:有视图树就用视图树,没有视图树就退回视觉识别,然后统一编码成一个对 LLM 友好的“界面状态表示”。

这个表示才是关键。它决定了模型能不能理解“当前屏幕是一个商品详情页,右上角有购物车图标,底部有加入购物车按钮”。界面表示做得越干净、越结构化,规划层推理出错的可能性就越低。

2.2 规划层:任务怎么被拆成可执行动作

感知完成之后,模型手里有一份“当前屏幕状态说明书”,接下来要做的是决策——在众多可执行动作里选一个。

ARTEMIS 一类框架通常会把动作空间限定在一个集合里:点击、长按、滑动、输入、返回、等待。这些动作需要绑定到具体元素上,而不是简单给一个坐标。比如“点击屏幕中央”这种动作是反模式的,正确的方式是“点击 ID 为product_card_3的节点”,或者“点击文本为‘加入购物车’的按钮”。

规划过程本身是一个动态循环。比如任务是“打开设置里的 Wi-Fi 页面并连接指定网络”。模型看到桌面,决定先找到“设置”图标,点击;进入设置主页后,重新感知,看到列表里有“WLAN”选项,再点击;进入 WLAN 页后,感知当前网络列表,找到目标 SSID,执行点击和输入密码。每一步决策都依赖于上一步执行后的新界面状态。

这个过程中最值得聊的是“约束”。一个裸奔的 LLM 在手机上随便乱点,很快就能把自己带进沟里:点了不可点击的文案、把系统设置改了、在支付页面误触了确认按钮。ARTEMIS 这类框架在规划层会有意识地做动作过滤和风险控制,把明显不可逆的、敏感的动作拦下来,至少要求额外的确认信号。这种约束不是限制框架能力,而是让它变成一个可用的生产工具而不是玩具。

2.3 执行与反馈:操作之后怎么知道对不对

执行动作这一步本身并不复杂:点击就是adb shell input tap,滑动就是adb shell input swipe,整个动作周期可能不到 200 毫秒。真正难的是“操作之后怎么确认动作生效了、对不对”。

如果没有反馈闭环,AI 就是一个盲人,只能靠猜。ARTEMIS 的做法是在每次动作执行后,主动发起一次新的界面感知,把执行前后的界面状态做对比,然后判断是否离目标更近了一步。比如点击“加入购物车”后,屏幕上出现了一个 Toast“已加入”,或者购物车角标从 0 变成了 1,这些都算正反馈;如果点击之后没有任何变化,那就要考虑是不是点错了、按钮被遮挡、或者页面还没加载完。

这个环节最容易翻车的是“时机判断”。你以为点击之后界面已经稳定,于是立刻感知,结果动画还在播放、列表还在刷新,拿到的状态是伪状态。更合理的做法是引入一个等待策略:感知到界面上有“正在加载”“转圈”“骨架屏”这类特征时,先等待再重新感知,直到界面进入稳定状态,再进行下一个决策。

整个感知、规划、执行、再感知的循环,其实就是人类操作手机的原子化版本。你把一个人操作手机的每秒钟拆开看,本质也是这套循环。ARTEMIS 和传统自动化最根本的区别,就在这里。

3. 本地跑通最小闭环:环境、依赖与一份可照抄的 Demo

3.1 环境准备里最容易被忽略的三个细节

聊完原理,该动手了。不管你是想直接跑 ARTEMIS 的官方示例,还是想先搭一套最小闭环验证一下思路,基础环境都绕不开这几样:一台 Android 手机或者模拟器、ADB 工具链、Python 3.10 以上环境,以及一个能理解图片和界面文本的大模型接口。

如果你用真机,强烈建议优先选 Pixel 或者类原生系统手机。这不是崇洋媚外,是因为原生系统对无障碍服务的兼容性最好,国内定制 ROM 经常会杀掉后台的无障碍服务、限制 ADB 指令、或者弹一些奇怪的自启动管理窗口,排查起来非常麻烦。模拟器也可以用,但分辨率尽量固定在一个值,别开自适应旋转,不然下面的坐标问题会把你折磨死。

开发者选项里有两个设置特别容易被忽略。一个是“USB 调试”要打开,这个大家都知道;另一个是“USB 调试(安全设置)”,允许通过 ADB 修改权限或模拟点击的选项,很多系统默认是关闭的,不打开的话部分自动化动作会被系统拦截。连接之后先跑一句adb devices确认设备在线,再跑一句adb shell wm size拿到当前分辨率,这两个命令是后面所有操作的基础。

3.2 一段能跑的决策循环:截图、取 XML、问模型、执行

在接入任何 Agent 框架之前,我建议你先用一套“裸链路”把流程跑通。这套链路的核心就是四句话:拿当前界面截图、拿界面 XML、丢给大模型问下一步动作、执行 ADB 命令。ARTEMIS 的封装本质上也是在优化这四步之间的衔接,但你亲手把它跑一遍,对框架的理解会完全不一样。

以下是一段可以直接跑的最小 Python 脚本雏形,我用的是最常见的 Android 调试工具链:

import subprocess import base64 import time def adb_exec(cmd: list) -> str: """执行 ADB 命令并返回 stdout""" result = subprocess.run( ["adb", "shell"] + cmd, capture_output=True, text=True, encoding="utf-8", errors="ignore", ) return result.stdout def dump_ui_xml(): """抓取当前界面的视图树 XML 并拉到本地""" adb_exec(["uiautomator", "dump", "/sdcard/ui_dump.xml"]) subprocess.run(["adb", "pull", "/sdcard/ui_dump.xml", "ui_dump.xml"]) with open("ui_dump.xml", "r", encoding="utf-8") as f: return f.read() def take_screenshot(): """抓取当前屏幕截图并保存到本地""" with open("screen.png", "wb") as f: f.write(subprocess.check_output(["adb", "exec-out", "screencap", "-p"]))

拿到截图和 XML 之后,构造一个给大模型的提示词,核心内容是:你有当前手机界面的截图和视图树,任务是完成“XXX”,请从候选动作(tap、swipe、input、back、wait)里选择一个返回,并给出目标元素的坐标或文本描述。然后把模型返回的动作解析出来,用 ADB 执行:

adb shell input tap X Y adb shell input swipe X1 Y1 X2 Y2 duration adb shell input text "hello"

这一步看起来简单,但它已经是一个真正的 Agent 闭环了。我见过很多人上来就去调 ARTEMIS 的完整 API,环境配了一整天还没跑起来,就是因为缺了这条最朴素的手搓链路。裸链路能跑通,你才算真正具备了排查框架问题的前置知识。

3.3 模型选型:云端多模态还是本地推理

框架只是骨架,真正决定“智能”的是背后的模型。ARTEMIS 类的 GUI Agent 对模型有两个硬性要求:第一是能理解截图,也就是多模态能力;第二是能输出结构化决策,最好直接给出 JSON 格式的动作指令。

如果走云端方案,主流的选择是 GPT-4V、Gemini、Qwen-VL 这一档的多模态模型。实际测试下来,这几家在“看图 + 理解界面 + 输出动作”上的能力都够用,差异主要在延迟和成本。一次决策大概要消耗几千个 token,其中截图占大头。如果你的任务环节很多,一场完整流程跑下来消耗几十万 token 很正常,做预算的时候要有心理准备。

走本地方案的话,门槛会高不少。界面截图这种高分辨率图像对显存要求很苛刻,7B 级别的多模态模型勉强能用,但推理速度在普通消费级显卡上会比较难受,一次决策等十几秒根本没法做实时自动化。我的建议是:先跑通云端方案验证效果,等确认思路可行,再考虑对延迟敏感的部分做本地化微调或者模型蒸馏。不要一上来就在本地部署上死磕。

4. 实测中绕不开的四个坑:偏移、动态界面、弹窗与输入

4.1 坑一:视图树坐标和实际渲染位置对不上

ARTEMIS 的感知层拿到视图树之后,模型天然会信任节点坐标。但在我实测的很多场景里,视图树给的bounds和元素实际显示的位置就是有偏差。最典型的情况是 WebView 混合页面:HTML 内容渲染出来的节点,坐标经常偏移几十个像素;Flutter 应用更极端,整个界面可能只有一个根节点,坐标范围覆盖全屏,等于没坐标。

遇到这种情况,第一步排查永远是做“截图对照”。把当前截图拉下来,再用开发者工具或 UIAutomator Viewer 打开同一时刻的 XML,肉眼比对目标元素的视觉位置和节点bounds是否一致。如果偏移是固定方向的,比如总是向下偏 100 像素,很可能是系统状态栏或导航栏占据了部分空间,视图树以全屏坐标计算,而你设备的实际可用区域更小,这种情况用adb shell wm size和adb shell wm density确认分辨率再做坐标归一化。

如果偏移不固定,就要考虑走视觉锚点方案。也就是不完全依赖视图树坐标,而是让模型根据截图上的视觉特征自己估算点击位置。这个方法准确率会略降,但能应对动态渲染和自绘 UI。ARTEMIS 的感知层如果只开了视图树模式,碰到这种情况大概率翻车,记得确认框架是否支持切换或合并感知模式。

4.2 坑二:界面是活的,看一遍就动手必然出错

第一次跑全流程的时候,我低估了“界面是动态的”这件事对 AI 决策的破坏力。比如一个商品列表页,模型看到第五个位置是“蓝牙耳机”,决定点击它,但就在模型推理的那两三秒里,页面已经自动刷新,第五个位置变成了“充电器”。模型还按旧状态执行,点下去就歪了。

更隐蔽的是延迟加载。列表快速滑动时,底部还在加载更多;搜索框输入关键词后,联想词才慢慢蹦出来。如果你在界面未稳定时就去感知,拿到的状态是残缺的,决策质量必然下降。

我的解决经验是给感知层加一道“稳定守卫”:在执行动作前,连续抓两次界面状态做 diff,如果差异很小,就认为稳定;如果差异大,继续等待并重新感知。同时在动作执行后加一个最小观察窗口,别急着推进下一步。这套逻辑听起来像是给脚本加sleep,但区别在于它是感知驱动的动态等待,而不是拍脑袋的固定等待。

4.3 坑三:系统弹窗和权限浮层随时打断流程

几乎所有移动端 Agent 跑到一半都会遇到一个头疼问题——系统弹窗。权限请求、App 更新弹窗、广告弹窗、优惠券弹窗、手机管家悬浮窗,每一样都能把流程截断。传统脚本的做法是提前写好哪个弹窗、点哪个按钮;但 Agent 面临的弹窗是开放式的,你根本无法穷举。

一个比较实用的思路是在规划层加入“弹窗处理优先”的默认策略:每次感知界面后,先让模型判断当前是不是异常浮层,是的话先处理掉,再继续主线任务。同时,对高频的权限弹窗做预授权——在启动 App 之前把存储、定位、通知等权限提前用pm grant授予,减少运行时弹窗的触发次数。这不能覆盖所有情况,但至少能干掉一半的打断场景。

另一个建议是给框架配置“任务禁区”。比如某些系统级页面、支付确认页、账号删除入口,一旦感知到进入这些页面,强制让 Agent 停下来等待人工确认。这个约束极其重要,我宁可在流程上多一步人工点确认,也不愿意让模型在无人监管的情况下误触敏感操作。

4.4 坑四:中文输入在 ADB 这条路上总是翻车

最后这个坑看起来小,实际杀伤力极大。adb shell input text是一个很低层的输入命令,它只支持 ASCII 字符。你想让 Agent 在搜索框里输入“蓝牙耳机”,命令发过去,界面可能是空的,或者出现一串乱码。我见过不少做 Agent 演示视频的人,一到输入环节就卡住,最后只能放慢动作录个屏幕键盘找补。

常见解法是用剪贴板广播:先把要输入的内容复制到系统剪贴板,然后通过 ADB 广播一个粘贴事件,让目标 App 接收。具体原理是利用 Android 的剪贴板服务,命令大体是cmd clipboard set或者通过am broadcast发送自定义广播,各家 Rom 实现不一,稳定性要看目标设备的系统版本。

更省心的方案是直接安装 ADBKeyboar 这类开源的 ADB 输入法,它会监听 ADB 过来的广播消息并模拟真实键盘输入,对中文输入法环境比较友好。这类输入法本质上是系统输入法的一种,装好之后切到它再执行输入,就能绕开input text的 ASCII 限制。不过要留意,某些过于严格的国产 ROM 可能不会让第三方输入法稳定驻留,所以在真机测试时先跑通输入再谈别的。

5. 从 Demo 到生产:ARTEMIS 落地前要想清楚的事

5.1 评估 Agent 好不好用,别只看最终成功率

很多人测试 AI 自动化,只看“任务最终完成了没有”,这是个严重的误导。一次任务可能中途点错三次,最后误打误撞完成;也可能走了完全离谱的路径,只是结果碰巧正确。生产环境里,这种“碰巧成功”比失败还危险,因为它不可复现、不可预测。

我建议从四个维度去评估:任务成功率、平均步数、平均耗时、异常恢复能力。成功率衡量最终结果;平均步数是看 Agent 找路的效率,人类 10 步做完的事 AI 花了 40 步,说明决策质量不行;平均耗时是把模型推理时间也算进去;异常恢复能力最关键——就是遇到意外弹窗、界面错位、动作执行失败之后,Agent 是能自己纠偏,还是一路错到底。

拿这四个维度做个简单的评分表,跑二十组任务求平均,比盯着一两个成功案例管用得多。我在选型任何 GUI Agent 框架时都会先做这组评估,ARTEMIS 也不例外。

5.2 落地场景:自动化测试之外可能更有价值

很多人第一反应是拿 ARTEMIS 做自动化测试,这当然可以,但我觉得它价值更大的场景是“跨 App 的复杂流程编排”。这类流程对传统自动化来说是灾难,因为要跨越多个应用、处理各种状态;但对 Agent 来说,它天然是用自然语言理解任务的,反而更擅长。

另外一个值得尝鲜的方向是回归验证的“模糊探索”。让 Agent 在 App 里自由游走,按预设的风险偏好随意点击、滑动、输入,遇到崩溃或异常就截图留证。这可以覆盖掉很多测试用例设计时没想到的边界路径,相当于请了一个不知疲倦的探索者帮你找问题。

不过有一点风险必须反复提醒:别拿它做支付、删除、账号注销这类高影响动作的无人值守自动化。Agent 再强也是概率决策,是概率就有失败的可能。把这些环节设成人工确认,或者干脆划出禁区,保证系统边界稳定。

5.3 我的扩展实践与一点收尾建议

最后分享两个我自己扩展的做法。第一个是“动作白名单”:在 ARTEMIS 的规划层外面再拦一道规则,只允许 Agent 执行我指定的动作类型和操作范围,比如禁止打开系统设置、禁止长按删除 App、禁止点击所有带“删除”“退出登录”字样的节点。这层约束放在模型之外,从工程上兜底,不依赖模型自觉。第二个是“全过程留痕”:把每一步的截图、界面 JSON、模型思考内容、执行命令全部落盘。出问题的时候,回放这个过程比任何日志都更直观。

跑完这套流程之后我最大的感受是:ARTEMIS 真正改变的不是自动化测试的写法,而是我们和手机交互的抽象层级。过去我们用坐标、控件 ID 跟手机对话,现在用自然语言任务跟手机对话,中间的理解和翻译交给模型,手脚交给框架。这套体系不会让所有脚本立刻消失,但它会让那些真正复杂、真正反模式的场景第一次变得可以被自动化。如果你想试试看,建议从今天的最小闭环开始,不要一开始就追求全流程跑通。先把机制彻底理解清楚了,再去碰框架的高级能力,遇到的每一个问题你都会知道该从哪一层入手排查。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 18:42:03

Windows 11下STLINK驱动安装失败的根源与精准修复

1. 为什么STLINK在Windows 11上总“装不上”?这不是驱动包的问题,是系统底层逻辑变了你手边刚拆封的STLINK V2调试器,USB线一插,设备管理器里却只显示一个带黄色感叹号的“Unknown device”——不是线坏了,不是板子没供…

作者头像 李华