dsh-android-emulator-helper
Verified@zhz8888/dsh-android-emulator-helper · v1.1.3 · MIT · Web UI
Android SDK, emulator and device management plus Kotlin/Compose build-and-run tools for DeepSeek Harness, ported from the official ZCode android-emulator plugin, with its parameter page on the plugin's own detail page in the Plugins panel.
Install
dsh plugin add @zhz8888/dsh-android-emulator-helper Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Readme
dsh-android-emulator-helper
English | 简体中文
把 ZCode 官方 [email protected] 插件移植为 DSH(DeepSeek Harness)原生插件:原有 23 个 MCP 工具全部保留为 DSH 原生工具,并新增一个参数表单,渲染在「插件」页该插件的详情页里(插件 → 已安装插件 → Android 模拟器助手),让 SDK、模拟器、系统镜像、构建与输出目录等参数在应用里配置,而不是靠环境变量。
- 工具名、参数名与原插件完全一致,为原
android_emulatorMCP 服务器写的工作流可直接迁移;这次移植既不新增工具,也不删除工具。 - 5 组 17 个设置项,全部实时生效;原插件暴露的 7 个字段仍会回落到同名
ANDROID_PLUGIN_*变量,再回落到内置默认值。 android_preflight与参数页的 检测环境 按钮跑同一套检查——SDK、adb、emulator、AVD、JDK、Gradle——并逐条给出修复建议。- 包名为
@zhz8888/dsh-android-emulator-helper;插件页显示的是locale/里的本地化名称 Android Emulator Helper / Android 模拟器助手,而不是原始包名,两条描述都写明本插件非官方、与 Google 无隶属关系。
快速上手
在一台装有 Android SDK、JDK 与 DSH 的机器上:
安装插件
dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helperDSH Desktop 则在 插件 页里添加同一个包名。装完重载或重启 DSH。
检查本机环境 —— 打开 插件 → 已安装插件 → Android 模拟器助手,点 检测环境。它跑的就是
android_preflight那套检查,缺什么都会给出修复建议。开始使用 —— 直接说你要什么(「把这个工程在模拟器上构建并运行」「给跑起来的应用截个图」),或直接调用 23 个
android_*工具。工具需要的参数都能在那个页面里改。
目录
环境要求
| 依赖 | 说明 |
|---|---|
| Android SDK | 插件配置页的 sdkPath,留空则依次探测 ANDROID_HOME、ANDROID_SDK_ROOT 与常见安装路径。 |
| platform-tools、emulator 与系统镜像 | adb 与 emulator 来自 SDK;创建 AVD 需要与目标 API 级别匹配的系统镜像。 |
| JDK | jdkMajor(默认 17)决定构建用哪个 JDK;生成工程的 JVM target 由它推导并钳制在 [17, 21]。 |
| Gradle | android_build_app 优先用工程自带的 ./gradlew,没有就用 PATH 里的 gradle(也能用后者生成 wrapper)。而 android_create_app 生成的工程不带 wrapper。 |
| 一台设备或一个 AVD | 已连接设备,或一个可启动的 AVD;autoStartEmulator 决定工具能否自行启动模拟器。 |
| Node.js ≥ 22 | DSH 宿主运行时。 |
android_preflight 会逐项检查上表并给出修复建议;插件页的 检测环境 按钮跑的是同一套检查。
安装
dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper
DSH Desktop:desktop profile 由 Electron 应用独占管理——请在 插件 页里添加 @zhz8888/dsh-android-emulator-helper,并启用它创建的那一行。重载或重启后,打开 插件 → 已安装插件 → Android 模拟器助手:参数表单就在该插件的详情页里,且只有当 host 半侧真正提供该设置命名空间时它才会出现。
发布包内含插件需要的一切——host 半侧、浏览器 bundle、内置 skill 与 locale/ 词条——且安装期不编译任何东西,因此没有构建审批环节。@deepseek-ai/cordis、@deepseek-ai/dsh-tools、@deepseek-ai/schemastery 都是由宿主提供的 peer 依赖,插件不会带入第二份副本,本身没有任何运行时依赖;DSH 的兼容性闸门会拿 @deepseek-ai/dsh* 的 peer 区间与运行版本比对,不匹配直接拒装。
同一个包只能挂载一次。
dsh plugin add会把这一行记进dsh.profile.bundles;再往 profile 自己的cordis.patch.yml里手加同一行,会让所有工具名二次注册并在加载期报错。
升级与卸载
dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper@latest # 升级
dsh plugin --profile <profile> remove @zhz8888/dsh-android-emulator-helper # 卸载
设置保存在 profile 里而不是包里,所以这两条命令都不会动它。数据目录(默认 $DSH_HOME/android-emulator-helper,其次 ~/.dsh/android-emulator-helper)存放截图与构建日志,卸载不会删除它,是否清理由你决定。
版本闸门
DSH 兼容范围是 >=0.2.1-rc.2——只有下界,没有上界,三处声明逐字一致(peerDependencies、engines.dsh、dsh.compatibility.dsh):低于下界的运行时会直接拒绝安装,同时未来的稳定版都不会被排除。下界即本插件「插件」页配置所构建并验证过的版本。
只有一个 node-semver 细节绕不开:0.2.2-alpha.1 这类新元组的预发布在 npm/pnpm 的默认规则下不被放行,安装会失败。此时二选一——给范围补一条该元组的分支(">=0.2.1-rc.2 <0.2.2-0 || >=0.2.2-0"),或让 pnpm 放宽 peer 校验:
dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper \
--config.strict-peer-dependencies=false
稳定版中不低于下界的版本(0.2.1、0.3.0、1.0.0…)不受这个细节影响,一律放行。
配置页面
配置命名空间 = profile patch 行 id = android-emulator-helper(同时是 dsh.name)。表单注册到插件页的 plugins.bundle.config 槽、以包名为键,因此渲染在「插件」页该插件的详情页里,而不是「设置」对话框里;只有当 host 半侧提供该命名空间时它才存在。表单通过 ctx.configForms 读写,因此暂存编辑、脏值检测、内联校验、乐观并发(revision)与「已覆盖 / 恢复默认」语义都由 harness 提供。详情页负责绘制插件标题、图标与描述;表单本身只贡献一行「改动何时生效」的说明、每个分组一张卡片——卡片描边就是分组之间的分隔——以及底部粘性保存栏;保存栏只在有可操作内容时出现:有暂存改动、正在写入,或一次失败值得重试。
| 分组 | 设置项 | 类型 | 默认值 | 旧环境变量回落 |
|---|---|---|---|---|
| SDK 与工具链 | sdkPath |
文本 | 空(自动探测) | ANDROID_PLUGIN_SDK_PATH |
jdkMajor |
文本,建议来自本机 | 17 |
ANDROID_PLUGIN_JDK_MAJOR |
|
buildToolsVersion |
文本,建议来自本机 | 35.0.0 |
ANDROID_PLUGIN_BUILD_TOOLS_VERSION |
|
| 模拟器与设备 | defaultAvd |
文本,建议来自本机 | medium_phone |
ANDROID_PLUGIN_DEFAULT_AVD |
defaultSerial |
文本,建议来自本机 | 空 | — | |
autoStartEmulator |
开关 | 开 | — | |
emulatorArgs |
多行文本,每行一个参数 | 空 | — | |
bootTimeoutSeconds |
整数 | 180 |
— | |
| API 与系统镜像 | apiLevel |
文本,建议来自本机 | 35 |
ANDROID_PLUGIN_API_LEVEL |
systemImageVariant |
下拉 | default |
ANDROID_PLUGIN_SYSTEM_IMAGE_VARIANT |
|
systemImageAbi |
下拉(留空 = 宿主架构) | 自动 | ANDROID_PLUGIN_SYSTEM_IMAGE_ABI |
|
minSdk |
整数 | 23 |
— | |
| 构建 | buildTimeoutSeconds |
整数 | 600 |
— |
gradleExtraArgs |
多行文本 | 空 | — | |
| 输出目录与日志 | dataDir |
文本 | $DSH_HOME/android-emulator-helper |
— |
screenshotDir |
文本 | <数据目录>/screenshots |
— | |
logTailLines |
整数 | 500 |
— |
配置页的两个按钮调用 host 半侧的两个精确 Fetch 路由:
- 检测环境 →
GET /api/android-emulator-helper/status,返回与android_preflight相同的检查结果,逐条显示状态、详情与修复建议。 - 刷新设备与 AVD →
GET /api/android-emulator-helper/inventory,探测 SDK 根目录、AVD、已连接设备、已安装 JDK、已装系统镜像/platform/build-tools,用于填充上方字段的建议列表。
兼容旧配置
原插件的 userConfig——也就是上表最后一列的 7 个变量——仍会作为回落生效,所以已有的 ZCode 或 CI 环境无需改动:解析顺序为配置页 → 环境变量 → 内置默认值。原插件的数据目录读的是 ANDROID_PLUGIN_DATA;在本插件里,这个目录就是配置页的 dataDir 字段。
配置页截图
四张都是 DSH harness 0.2.1-rc.2 里真实页面按滚动顺序的实拍,没有任何拼凑。1598 × 1588 PNG,对应收紧后的卡片节奏(每个字段上下各 7px,卡片 12px 16px,卡片之间 16px);截图时是中文语言,插件 面板停留在该插件的详情页:第一张从插件标题 Android 模拟器助手 与描述开始,侧边栏高亮 插件,而上表里的字段 key 两种语言下完全一致。灰色文字是留空字段的占位提示;底部保存条只在有改动待保存时出现,因此这几张图里没有它。
1. SDK 与工具链 —— 页面开头是插件标题、包名与描述,然后是每次 android_* 调用最先解析的 SDK 根目录、JDK 主版本与 build-tools 版本,以及模拟器与设备卡片直到启动超时:

2. 模拟器与设备 —— 调用打到哪台设备、模拟器怎么起来:默认 AVD、默认设备序列号、自动启动开关、额外 emulator 参数与启动超时,然后是 API 级别卡片:

3. API 级别与构建 —— 生成项目与安装系统镜像的目标、gradle 的超时与附加参数,然后是输出卡片的开头:

4. 输出目录与检测 —— 截图和构建日志落在哪里,以及支撑页面的两个按钮(对应上面的 Fetch 路由);画面停在插件表单结束处:

screenshots.json 就在仓库里的 package.json 旁边按这个顺序列出四张图,插件市场据此展示。
工具清单
23 个工具,名称与参数与原 MCP 服务器一致。
| 工具 | 作用 |
|---|---|
android_preflight |
检查 SDK、adb、emulator、AVD、Java、Gradle 工程状态与 UI 自动化后端,并回显当前设置。 |
android_discover_project |
发现 Gradle 根、模块、variant、applicationId、manifest 与 APK 产物。 |
android_create_app |
生成最小 Kotlin + Jetpack Compose 工程。 |
android_build_app |
用 Gradle 构建指定模块与 variant。 |
android_build_and_run |
构建 → 复用或启动设备 → 安装 → 启动。 |
android_list_devices / android_list_avds |
列出 adb 可见设备 / 本机 AVD。 |
android_start_emulator / android_stop_emulator |
启动新的 GUI 模拟器 / 按序列号停止模拟器。 |
android_create_avd |
用 avdmanager 创建 AVD。 |
android_install_app / android_launch_app / android_terminate_app |
安装 APK / 按 applicationId 启动 / 强制停止应用。 |
android_open_url |
在设备上打开 URL。 |
android_screenshot |
截图并落盘;模型支持图像输入时同时返回图像。 |
android_logs |
读取 logcat 尾部,可按 applicationId 过滤。 |
android_ui_status |
报告 UI 自动化后端可用性。 |
android_ui_describe / android_ui_resolve |
返回 UI Automator 元素树 / 按文本、描述、资源 id 或类名解析到坐标。 |
android_ui_tap / android_ui_swipe / android_ui_type_text / android_ui_keyevent |
基于 adb 的点击、滑动、文本输入与按键事件。 |
android_screenshot 的行为值得单独说明:PNG 总会写到磁盘(默认在数据目录的 screenshots/ 下),同时尝试把图像提交给宿主的附件服务以获得规范的图像块。当前模型未声明图像输入、或部署没有附件服务时,结果会退化为纯文本并附上文件路径,而不会让整次调用失败。
Skill 与斜杠命令
android-devskill —— 随包提供(skills/android-dev/),host 半侧通过ctx.skills.register()注册为嵌入式 skill,并把 skill 目录作为resourceBase,因此INSTALL_ENVIRONMENT.md的相对引用照旧可用。内容已按 DSH 改写:不再有mcp__…前缀,环境配置指向插件配置页而不是环境变量。/android-dev [目标]命令 —— 通过ctx.commands.register()注册。DSH 的用户命令刻意不产生模型消息,因此该命令做一件不依赖模型的事:跑一遍环境诊断,输出结论、失败项与修复建议。
与原插件的差异
| 方面 | 原插件(ZCode) | 本插件(DSH) |
|---|---|---|
| 工具暴露 | stdio MCP 服务器 android-emulator;模型看到 mcp__android_emulator__* |
原生 ctx.tools.register();模型看到 android_* |
| 用户配置 | plugin.json 的 userConfig(7 项),经环境变量注入 |
配置页 + schemastery Config 的 17 个字段,全部 .volatile();旧环境变量仍作回落 |
| 工作目录 | process.cwd() |
exec.agent.session.header.cwd(会话工作区) |
| 数据目录 | ANDROID_PLUGIN_DATA / 临时目录 |
$DSH_HOME/android-emulator-helper,可在配置页配置 |
| 截图返回 | MCP image content(base64) | 由 host 附件引用生成的图像块,被拒时退化为文本 + 磁盘路径 |
| 结果归一 | provider 返回含 undefined 的对象 |
所有结果都过一遍 toLosslessJson()(注册表拒绝 undefined) |
| 斜杠命令 | 向模型对话注入一段提示词 | 直接运行诊断并输出结论 |
| 进程调用 | node:child_process 直接 spawn |
保持一致 |
保留直接 spawn 是有意的取舍:这样 gradlew、adb、emulator 的行为与原插件逐字节一致,也不必为 adb exec-out 的二进制流另写适配层;代价是绕过了 DSH 的 subprocess seam,因此每个外部调用都自带 timeout 与 SIGTERM。插件不读取、不转发任何含凭据的环境变量。
已知限制
- Linux 不支持,与原插件一致;
android_preflight会明确报告。 android_start_emulator永远启动新模拟器,从不复用已有目标(原插件语义)。复用请把serial传给其他工具。android_create_avd对avdmanager的确认提示固定回答no,绝不静默触发数 GB 的镜像下载;请先用sdkmanager装好镜像。- UI 自动化依赖设备端的
uiautomator;不可用时android_ui_status会报告,构建 / 运行 / 截图链路不受影响。 - 配置页的「已安装系统镜像」列表来自 SDK 目录扫描,而不是
sdkmanager --list_installed(后者在受限环境下会失败,且输出夹带大量弃用提示)。 - 配置页的两条路由由插件提供并在真实 profile 中挂载,但它们的 HTTP 响应无法在 GUI 之外验证:桌面端对每个请求做鉴权,未带浏览器会话的
curl访问/api/android-emulator-helper/status会在进入 handler 之前返回403 forbidden。配置页的间距、暗色主题与窄屏换行仍建议在 GUI 中人工核对。 - 插件不触碰凭据:不读取、不转发任何含 key/token/secret 的环境变量。
版本与发布
每次发布都是同一个提交出现在两处:在 main 上打 vX.Y.Z 轻量 tag,并从该 tag 发布到 npm,npm 记录的 gitHead 就是它的 SHA。完整列表见 Releases——最新是 v1.1.3,之前是 v1.1.2、v1.1.1、v1.1.0 与 v1.0.0。
升级后请重启 DSH 宿主进程。 本包以 link: 软链挂载,Node 对 ESM 做进程级缓存,lib/ 的改动在宿主重启前不会生效——否则工具仍会跑旧代码。
参与贡献
欢迎在 github.com/zhz8888/dsh-android-emulator-helper 提 issue 或 PR。任何改动都必须让 pnpm check 保持全绿——单元测试、host/client 一致性闸门、以及在真实 Cordis 宿主上的挂载验证;没有 CLA,也没有需要填的表单:一个说清楚改了什么、为什么改的聚焦 PR 就够了。
本包按 awesome-dsh-plugin 市场的形态组织。开发约定——命令、仓库结构、不变式、测试、提交与发布规则——都在 AGENTS.md。
许可
MIT,版权所有 (c) 2026 zhz8888。工具定义、provider 逻辑与生成的 Kotlin/Compose 工程模板移植自 ZCode 官方 android-emulator 插件(同样以 MIT 分发,版权归 Z.ai),模板源文件逐字保留;完整的来源说明见 LICENSE 末尾。