最新资讯
reddit.com OpenAI 称 Astra 仅满足 10% 安全任务标准 dev.to FreeToken:在自有 GPU 上运行前沿 MoE 模型及其内存需求 dev.to 当 AI Agent 说“完成”时,究竟完成了什么? dev.to 部署 Underdog Bark 3.0 Pro:逐字转写、自定义后端与分块设置 dev.to 为艰难对话构建 AI:五个 Agent、一条安全正则与一位盲评监督者 techcrunch.com Palo Alto Networks 洽谈以 5 亿美元收购 AI Agent 安全初创公司 Clutch theinformation.com 黄仁勋被要求就涉华间谍指控向国会作简报 www.infoq.com Edera 推出 Object Capability Bounded Authority,试图将凭证与 AI Agent 工作负载隔离 wechat 这波杀疯了!旗舰级模型不限量、1个月视频额度免费领 bloomberg.com AI 抛售蔓延至信用市场,软银领跌亚洲美元债 dev.to 如何在专用 GPU 服务器上用 OpenAI 兼容 API 部署 LLM dev.to 审计 153 份 Claude Code 与 Codex 会话记录:User-Agent 与 URL 中的邮箱泄露
多元动态
登录 注册
智能体 dev.to · @Evgeny Khramov

让编码 Agent 无需模拟器渲染 Android UI:截图并不够

原文 我的收藏

作者描述在编码 Agent 修改 Android XML 后,希望在同一工作流内直接查看渲染结果,而非手动打开界面确认。其方案是用 Kotlin/JVM 和 Robolectric 构建本地 MCP server,Agent 提供布局和显式数据后获得渲染输出。作者指出仅靠截图只是解决方案的一半。

AI推荐理由 开发者分享让编码 Agent 在不启动模拟器的情况下渲染 Android UI 的实践:用 Kotlin/JVM 与 Robolectric 构建本地 MCP server,Agent 提供布局与数据后获得渲染结果,并指出仅靠截图不足以完成验证。属于具体工程经验,对 Agent 与开发工具集成有参考价值,但为个人博客、缺乏量化效果。

68

正文

When a coding agent changes Android XML, it is fairly confident about what it can read: it finds the layout, understands the constraints, and produces a diff. But there was almost always one more manual step afterwards. I would open the screen and decide whether the button, the text, or the card had actually ended up in the right place. I wanted to remove that repeated switch. I was not trying to hand over responsibility for the product or to declare the emulator unnecessary. I wanted the result of the agent's changes to be available inside the same workflow in which it edited the code. My first idea was a screenshot: the agent changes XML, gets an image, and looks at it. In practice, that turned out to be only half of the solution. The setup The loop I wanted for XML/View screens: change XML → render → check the result → fix Enter fullscreen mode Exit fullscreen mode I put the rendering into a local MCP server built with Kotlin/JVM and Robolectric. The agent supplies a layout and explicit data for it, and gets the rendered result back. MCP is not the interesting part here. It is just a way to take me out of a repetitive intermediate step: launching the render by hand and passing the result back to the agent. The scope is deliberately narrow. This is for XML/View projects, not Compose. It is not a replacement for a device, it does not promise a pixel-for-pixel match with a physical phone, and it does not try to emulate hardware surfaces, video, or a camera. The PNG worked, and the tool was still not finished The screenshot made the result visible immediately. The agent could notice that text was clipped, that a block had unexpectedly disappeared, or that two elements were clearly overlapping. That was already better than editing XML blind. At that point the project looked almost done. Screenshots were generated, the MCP server responded, and an inspect_view tool existed. A closer review broke that impression. The screenshot was real, but the sidecar returned an artificial root node as the View tree. There was no real child View to query, so a tool called inspect_view was barely useful. That showed how much an image alone leaves unresolved. It is poor at answering the questions that often decide whether a UI change is correct: What is the actual distance between two Views? Has an element gone beyond the screen boundary? Where exactly is the View with a particular id? A person can estimate these by eye. The agent needs verifiable data, not just an illustration. A second wrong assumption: the warm JVM Around the same time the coding agent pointed out another oversimplified idea in my design. You cannot just start the Robolectric runtime once and keep reusing it after changes to XML or Kotlin: you risk inspecting stale resources and an outdated classpath. That observation changed the architecture. It removed the temptation to treat a "warm JVM" as a problem we had already solved. The default sidecar still is not the persistently warm JVM from my early architectural plan. The fix: measure what you render The turning point was simple to state: the PNG and the data must come from the very same layout, after layout has been performed. After inflate → fixture → measure → layout → draw, the renderer saves both the image and the real View tree. Each node includes its identifier, type, text and state, padding, margins, and absolute bounds. Three small operations make up the loop: render_layout → creates a render session get_view_tree → returns the tree of that session inspect_view → returns a single node by id Enter fullscreen mode Exit fullscreen mode The API names matter less than what they allow. The agent can move from "these look a little too close together" to a measurable fact, such as comparing the edge of a button with the edge of its container without estimating anything from a PNG. That gave us a geometry feedback loop: change → render → inspect → evidence → fix Enter fullscreen mode Exit fullscreen mode The image helps reveal a problem, the tree provides the geometry, and the next change goes through the same render again. Underneath there are also a source fingerprint and an allowlisted Gradle pipeline. They exist so the loop cannot silently render stale state or run arbitrary shell commands. Testing it on a real layout After these changes I connected the MCP server to an actual Android project I was working on. The coding agent used it to fix a real product-card layout with a required-items section. Before the fix. The UI is in Russian. After the fix. The UI is in Russian. The two screenshots show different items, so they are not a pixel-level comparison. For me this was the key acceptance test. The tool had moved beyond its RFC and its own unit tests into a real UI task, and a coding agent used the loop in an actual UI change. What the experiment did and did not prove What I wanted to check Result Can a real Android XML/View layout be rendered through MCP + Robolectric? Yes Can a real, machine-readable View tree be returned alongside the PNG? Yes Did a coding agent use this loop in a real UI change? Yes Can the agent's actions be fully reproduced from the saved data? Not yet I do not consider this a replacement for an emulator or a device. Robolectric does not guarantee a pixel-perfect match with hardware. I have no compatibility matrix covering custom Views and complex themes. For the next experiment of this kind I want to keep the complete record: the prompt, the tool calls, render IDs, the XML diff, the measurements, and the final verdict. These are reasonable limits for a first version. What matters more is that they can now be described as facts rather than as the impression left by a good screenshot. Who did what I did not give the agent the authority to "decide the UI." I defined a bounded problem, set the limits of support, refused to accept a PNG as sufficient evidence, and kept bringing the work back to verifiable criteria. The coding agent was more than a code generator. It helped implement the tool, flagged the risk of a stale Robolectric runtime, and helped build and use the loop itself. For me the main result is not that the agent now has an image. A screenshot makes an interface visible. A PNG together with a View tree makes it verifiable. That is how manual visual review can leave the routine loop: not because I decided to trust the agent, but because it gets artifacts that can be measured and checked again. The renderer is open source: android-ui-renderer-mcp on GitHub. The full case study is on my site: hram.github.io/en/articles/android-ui-renderer-mcp.

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容