DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

zhz8888 /

zhz8888/dsh-android-emulator-helper

Verified

在 DeepSeek Harness 里管理 Android SDK 与模拟器:23 个原生 android_* 工具覆盖环境探测、AVD 与模拟器生命周期、Kotlin/Compose 脚手架、Gradle 构建运行与安装启动,并提供设置页 | Android SDK and emulator management in DeepSeek Harness: 23 native android_* tools for SDK discovery, AVD and emulator lifecycle, Kotlin/Compose scaffolding, Gradle build and run, install and launch, plus a settings page.

★ 3 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@be6c1e26

dsh-android-emulator-helper

English | 简体中文

npm version license: MIT target: DSH

A DeepSeek Harness (DSH) native port of the official ZCode android-emulator@0.1.0 plugin: all 23 original MCP tools preserved as native DSH tools, plus a parameter page on the plugin row's own page in the Plugins panel (Plugins → Installed plugins → Android Emulator Helper → Configure) that edits the SDK, emulator, system-image, build and output parameters in-app instead of through environment variables, and the same page as a section in the Settings dialog once its Show in Settings switch is on and saved, with its own line-art Android icon.

  • Tool and argument names are identical to the original, so workflows written for its android_emulator MCP server keep working; the port adds no tool and drops none.
  • 18 settings fields in 6 groups, all live-editable; the seven fields the original exposed still fall back to their ANDROID_PLUGIN_* variable, then to the built-in default.
  • The page opens from the plugin row's Configure control, so the bundle's detail page keeps its description, its rows and its source; the Show in Settings switch in the page's last card also adds the same form to the Settings dialog's navigation, drawn with a line-art Android head as its icon. It is off by default, so a fresh profile keeps one configuration page.
  • The default AVD is picked from a dropdown of the AVDs on this machine that still have their payload: AVD discovery scans the AVD directory (ANDROID_AVD_HOME, then $ANDROID_USER_HOME/avd, then ~/.android/avd) as well as asking emulator -list-avds, so the list survives a host where the emulator cannot be started.
  • android_preflight and the parameter page's Run diagnostic button run the same checks — the host OS, the SDK root and the SDK's own tools (adb, emulator, sdkmanager, avdmanager), the JDK, Gradle, emulator acceleration, the AVDs and the attached devices — and print a fix for each failure.
  • Published as @zhz8888/dsh-android-emulator-helper; the plugin page shows Android Emulator Helper / Android 模拟器助手 from locale/ rather than the raw package name, and both descriptions say the plugin is unofficial and not affiliated with Google.

Quick start

On a machine with an Android SDK, a JDK and DSH installed:

  1. Install the plugin

    dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper
    

    In DSH Desktop, open Plugins and add the same package name there. Reload or restart DSH afterwards.

  2. Check the machine — open Plugins → Installed plugins → Android Emulator Helper and press Run diagnostic. It runs exactly the checks android_preflight runs, and prints a fix for anything missing.

  3. Use it — ask for what you want ("build and run this project on the emulator", "screenshot the running app"), or call the 23 android_* tools directly. Everything the tools need is editable on that page.

Contents

  • Quick start
  • Requirements
  • Install
  • Configuration page
  • Screenshots
  • Tools
  • Skill and slash command
  • Differences from the original
  • Known limitations
  • Releases
  • Contributing
  • License

Requirements

Dependency Notes
Android SDK sdkPath on the plugin's configuration page, else ANDROID_HOME, ANDROID_SDK_ROOT, the Windows registry, the project's local.properties, then the common install paths on every drive.
Platform tools, emulator and a system image adb and emulator come from the SDK; an AVD needs a system image for the API level you target. When adb is missing from PATH, the SDK's own platform-tools copy is used instead: a last-resort search looks for it inside the SDK the diagnostic found, and on Windows also under the drive roots, because a machine with the SDK installed must not be reported as having no adb.
JDK jdkMajor (17 by default) selects the JDK a build runs on; the nearest installed JDK is used when that major is missing, and the generated project's JVM target follows the JDK in use and is clamped to [17, 21].
Gradle android_build_app uses the project's ./gradlew when it has one and gradle from PATH otherwise; a generated wrapper is pinned to the installed Gradle's version but never below 8.9, the floor the bundled Android Gradle Plugin 8.7.3 accepts. The project android_create_app writes ships no wrapper either.
A device or an AVD An attached device, or an AVD to boot; autoStartEmulator decides whether the tools may boot one themselves.
Node.js ≥ 22 The DSH host runtime.

android_preflight checks every item above and prints a fix for each failure; the plugin page's Run diagnostic button runs the same checks.

Install

dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper

DSH Desktop: the desktop profile belongs to the Electron app — open Plugins, add @zhz8888/dsh-android-emulator-helper there, and enable the row it creates. After a reload or restart, open Plugins → Installed plugins → Android Emulator Helper and click Configure on its row: the parameter form is on that row's own page, and only appears while the host half actually serves this plugin's settings namespace. With Show in Settings on and saved, the same form is also a section in the Settings dialog.

The published tarball contains everything the plugin needs — the host half, the browser bundle, the bundled skill and the locale/ entries — and nothing is compiled at install time, so no build approval step is involved. @deepseek-ai/cordis, @deepseek-ai/dsh-tools and @deepseek-ai/schemastery are peer dependencies provided by the harness, so the plugin pulls in no second copy and has no runtime dependencies of its own; DSH's compatibility gate compares the @deepseek-ai/dsh* peer ranges against the running version and refuses to install on a mismatch.

Mount the package exactly once. dsh plugin add records the row in dsh.profile.bundles; adding a second row for the same package in the profile's own cordis.patch.yml registers every tool name twice and fails at the loader.

Upgrade and uninstall

dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper@latest   # upgrade
dsh plugin --profile <profile> remove @zhz8888/dsh-android-emulator-helper      # uninstall

Settings live in the profile, not in the package, so both commands leave them in place. The data directory (by default $DSH_HOME/android-emulator-helper, then ~/.dsh/android-emulator-helper) holds screenshots and build logs; it is yours to delete, and uninstalling does not touch it.

Version gate

The DSH compatibility range is >=0.2.2-rc.1, a lower bound only, declared identically in peerDependencies, engines.dsh and dsh.compatibility.dsh: a runtime below it is refused at install time, and no future harness release is excluded. The floor is the release this plugin's Plugins-page configuration was built and verified against, and it is a real floor rather than a formality — 0.2.2 moved three harness APIs this plugin uses (the resolved config moved to fiber.effectiveConfig, the tool executor became its own mounted row, and tools.execute now takes a batch), so an older runtime fails rather than degrading.

One node-semver detail survives — a new tuple's prerelease such as 0.2.3-alpha.1 is not admitted by npm's and pnpm's default rules, so that install fails until either the range gains a branch for the tuple (">=0.2.2-rc.1 <0.2.3-0 || >=0.2.3-0") or the peer check is skipped:

dsh plugin --profile <profile> add @zhz8888/dsh-android-emulator-helper \
  --config.strict-peer-dependencies=false

Stable releases at or above the floor (0.2.2, 0.3.0, 1.0.0, …) are unaffected and always admitted.

Configuration page

The settings namespace equals the profile patch row id equals android-emulator-helper (also dsh.name). The form registers with the Plugins page's plugins.row.config slot, keyed by <package name>#<row id>, so it renders on the page the row's Configure control opens — one click below the bundle's detail page, which keeps its description, its rows and its source — and it exists only while the host half serves that namespace. It reads and writes through ctx.configForms, so staged edits, dirty detection, inline validation, optimistic concurrency (revisions) and "overridden / reset to default" all come from the harness. The row's page draws the plugin's title, icon and crumb; the form contributes one line saying when an edit takes effect, one card per category — the card outline is what separates them — and saves from a sticky action bar at the bottom that appears only while there is something to act on: a staged edit, a write in flight, or a failure worth retrying.

Group Field Kind Default Legacy env fallback
SDK and toolchain sdkPath text empty (auto-detect) ANDROID_PLUGIN_SDK_PATH
jdkMajor text, suggestions from this machine 17 ANDROID_PLUGIN_JDK_MAJOR
buildToolsVersion text, suggestions 35.0.0 ANDROID_PLUGIN_BUILD_TOOLS_VERSION
Emulator and devices defaultAvd select (discovery), every AVD found on this machine medium_phone ANDROID_PLUGIN_DEFAULT_AVD
defaultSerial text, suggestions empty —
autoStartEmulator switch on —
emulatorArgs multiline, one argument per line empty —
bootTimeoutSeconds integer 180 —
API and system image apiLevel text, suggestions 35 ANDROID_PLUGIN_API_LEVEL
systemImageVariant select default ANDROID_PLUGIN_SYSTEM_IMAGE_VARIANT
systemImageAbi select (empty = host architecture) auto ANDROID_PLUGIN_SYSTEM_IMAGE_ABI
minSdk integer 23 —
Build buildTimeoutSeconds integer 600 —
gradleExtraArgs multiline empty —
Output and logs dataDir text $DSH_HOME/android-emulator-helper —
screenshotDir text <data dir>/screenshots —
logTailLines integer 500 —
Interface showInSettings switch off —

That last card decides where the page lives. With Show in Settings off, the default, the form renders only on the row's own page. Turn the switch on and save, and the bundle also registers a settings.section entry, id android-emulator-helper and order 100, plus the settings.section.icon contribution that draws its icon, so the same form, bound to the same settings namespace, also appears in the Settings dialog's navigation under Android emulator. The icon is the supplied Android glyph, shipped as its own file and referenced through the package's ./assets/* export, drawn as a mask over currentColor so it follows the navigation item's colour at 16 px — the active state is the same artwork in the rail's active colour. Both registrations follow the saved value live, so turning the switch off removes the section again without a reload.

Two exact Fetch routes back the page's buttons on the host half:

  • Run diagnostic → GET /api/android-emulator-helper/status, the same checks as android_preflight, each with its detail and fix hint.
  • Refresh devices and AVDs → GET /api/android-emulator-helper/inventory, detecting the SDK root, the AVDs stored in the AVD directory (ANDROID_AVD_HOME, else $ANDROID_USER_HOME/avd, else ~/.android/avd, merged with the names emulator -list-avds adds), connected devices, installed JDKs, system images, platforms and build-tools to populate the fields' suggestions. A record whose payload directory is gone is dropped from both sources. The scan is what lets the default-AVD dropdown list the machine's AVDs even when the emulator cannot be run.

The page's copy is not a route. Every label, hint and placeholder lives in locale/en.json and locale/zh.json; the host half reads those two files and publishes them as a page-initialization global (__DSH_ANDROID_EMULATOR_HELPER_LOCALE__) through the web server's webserver/index-inject table, which renders it into index.html ahead of the plugin bundle. The browser half therefore reads the copy synchronously at module scope and looks each string up by key — so the page carries no strings of its own, the two languages cannot drift apart, and the first render is already in the right language instead of showing raw keys until a fetch lands. A client bundle cannot read a file of its own package, and the package asset route admits images only, so that injection table is how the copy crosses into the browser.

Legacy configuration

The original plugin's userConfig — the seven variables in the last column above — still works as a fallback, so an existing ZCode or CI setup needs no change: the resolution order is configuration page → environment variable → declared default. The original also read ANDROID_PLUGIN_DATA for its data directory; here that directory is the page's dataDir field.

Screenshots

All four are real captures of this configuration page — nothing is mocked up — taken in DSH harness 0.2.2-rc.1, in the order you scroll it. They are 1598 × 1588 PNGs of the tightened card rhythm (7px above and below a field, a 12px 16px card, 16px between cards), captured in the Chinese locale with the Plugins panel open: the first shot opens on the plugin row's own page — its crumb, the plugin's title Android 模拟器助手 and description — the sidebar shows 插件 selected, and the field keys in the table above are the same in either language. Grey text is a placeholder standing in for a field left empty, a field carrying a value other than its declared default shows an override badge and a reset control, and the sticky save bar appears only while an edit is staged, so it is not in these shots.

They show that form where it lives today: on the plugin row's own page in the Plugins panel, the page the row's Configure control opens — not on the bundle's detail page.

1. SDK and toolchain — the form opens on the plugin row's own page with the plugin's title, package name and description, then the SDK root, JDK major version and build-tools version every android_* call resolves first, the emulator-and-devices card down to its boot timeout, and the start of the API-level card:

The Android Emulator Helper form on the plugin row's own page in the Plugins panel of DSH: the plugin title and description, then the SDK and toolchain card with the Android SDK root, JDK major version and build-tools version, then the emulator-and-devices card down to the boot timeout and the start of the API-level card

2. Emulator and devices — the form scrolled by one card: the SDK-and-toolchain card from its heading, then the emulator-and-devices card — the default AVD, the default serial, the auto-start switch, the extra emulator arguments and the boot timeout — then the API-level card and the start of the build card:

The form scrolled by one card: the SDK-and-toolchain card from its heading, then the emulator-and-devices card with the default AVD, default device serial, the auto-start emulator switch, the extra emulator arguments and the boot timeout, then the API-level card and the start of the build card

3. API level and build — the form scrolled further: the emulator-and-devices card from its heading, then the API-level-and-system-image card with the system image variant, ABI and default minSdk, the build card with the Gradle build timeout and the extra Gradle arguments, then the top of the output card:

The form scrolled further: the emulator-and-devices card from its heading, then the API-level-and-system-image card with the system image variant, ABI and default minSdk, the build card with the Gradle build timeout and the extra Gradle arguments, then the top of the output card

4. Output and diagnostics — where screenshots and build logs land, then the interface card that closes the page, with its Show in Settings switch, and the diagnostics-and-discovery card: the two buttons backing the page, next to the Fetch routes above, and the discovery result it fills in — the detected SDK root, AVD home, AVDs and installed system images:

The end of the captured form: the output-and-logs card with the data directory, screenshot directory and default logcat line count, then the interface card with the Show in Settings switch, then the diagnostics-and-discovery card with the run-diagnostic and refresh-devices buttons and the discovery result listing the detected SDK root, AVD home, AVDs and installed system images

screenshots.json lists these four files in this order next to package.json in the repository, which is how a plugin market finds them.

Tools

23 tools, identical names and arguments to the original MCP server.

Tool Purpose
android_preflight Check the host OS, the SDK and its tools (adb, emulator, sdkmanager, avdmanager), the JDK, Gradle, emulator acceleration, the AVDs and the attached devices, and echo the current settings.
android_discover_project Find Gradle roots, modules, variants, application ids, manifests and APK outputs.
android_create_app Generate a minimal Kotlin + Jetpack Compose project.
android_build_app Build one module and variant with Gradle.
android_build_and_run Build → reuse or start a device → install → launch the package read back from the built APK.
android_list_devices / android_list_avds List the devices adb sees / the AVDs on this machine.
android_start_emulator / android_stop_emulator Start a new GUI emulator / stop one by serial.
android_create_avd Create an AVD with avdmanager.
android_install_app / android_launch_app / android_terminate_app Install an APK / launch by application id / force-stop.
android_open_url Open a URL on the device.
android_screenshot Capture a PNG to disk, and return it as an image when the model accepts image input.
android_logs Read the logcat tail, optionally filtered to the app's own process (by PID).
android_ui_status Probe and report device-side UI automation availability.
android_ui_describe / android_ui_resolve The UI Automator element tree / resolve a text, description, resource id or class to coordinates.
android_ui_tap / android_ui_swipe / android_ui_type_text / android_ui_keyevent adb-backed tap, swipe, typing and key events.

android_screenshot deserves its own note: it always writes the PNG to disk (under <data dir>/screenshots/ by default) and additionally submits it to the host's attachment service for a canonical image block. When the current model declares no image input, or the deployment stores no attachments, the result degrades to text plus the file path instead of failing the call.

Skill and slash command

  • android-dev skill — shipped in skills/android-dev/ and registered by the host half through ctx.skills.register() as an embedded skill with the skill directory as its resourceBase, so INSTALL_ENVIRONMENT.md keeps resolving. Rewritten for DSH: no mcp__… prefix, and environment configuration points at the plugin's configuration page rather than at environment variables.
  • /android-dev [goal] command — registered through ctx.commands.register(). DSH user commands deliberately never create a model message, so this command does the one thing that is useful without the model: it runs the environment diagnostic and prints the verdict, the failing checks and their fixes.

Differences from the original

Aspect Original (ZCode) This plugin (DSH)
Tool exposure stdio MCP server android-emulator; the model sees mcp__android_emulator__* Native ctx.tools.register(); the model sees android_*
User configuration plugin.json userConfig (7 items), injected as environment variables Configuration page with 18 fields on a schemastery Config, all .volatile(); the old environment variables remain as fallbacks
Working directory process.cwd() exec.agent.session.header.cwd (the session workspace)
Data directory ANDROID_PLUGIN_DATA / temp $DSH_HOME/android-emulator-helper, configurable on the configuration page
Screenshot result MCP image content (base64) An image block built from a host attachment reference, degraded to text plus a disk path on refusal
Result normalisation Providers return objects containing undefined Every result passes through toLosslessJson() (the registry rejects undefined)
Slash command Injects a prompt into the model's conversation Runs the diagnostic and prints the verdict
Process invocation node:child_process spawn Unchanged

The direct spawn is a deliberate trade-off: gradlew, adb and emulator behave byte-for-byte as they did in the original, and adb exec-out needs no binary-stream adapter; the cost is bypassing DSH's subprocess seam, so every call carries its own timeout and SIGTERM instead. The plugin reads and forwards no credential-bearing environment variables.

Known limitations

  • A machine with no global Gradle cannot build a generated project. android_create_app writes no gradlew, and android_build_app can only generate one by running the gradle it finds on PATH; without one it fails with an explicit message. Install Gradle once, or run gradle wrapper in the project root yourself.
  • A generated project needs compileSdk 35 or newer. The template pins androidx.core:core-ktx 1.15.0, whose minCompileSdk is 35; android_create_app refuses an older level instead of writing a project Gradle cannot configure.
  • A batch-file tool cannot carry an argument holding a defined %NAME% reference. gradlew.bat, avdmanager.bat and any other .bat/.cmd launcher run through cmd.exe, which expands such a reference even inside quotes; the call refuses the argument instead of letting it be silently rewritten. A bare % — including the %s escapes input text sends for spaces — is safe.
  • Linux is unsupported, exactly as in the original; android_preflight reports it.
  • android_start_emulator always starts a new emulator and never reuses one. Pass serial to the other tools to reuse a target.
  • android_create_avd always answers no to avdmanager's confirmation, so it can never silently trigger a multi-gigabyte image download; install the image with sdkmanager first.
  • UI automation depends on the device-side uiautomator. When it is unavailable android_ui_status reports that, and the build, run and screenshot paths are unaffected.
  • The configuration page's installed-image list comes from scanning the SDK directory, not from sdkmanager --list_installed, which fails in restricted environments and prefixes its output with deprecation notices.
  • The configuration page's two routes are served by the plugin and are mounted in a real profile, but their HTTP responses cannot be exercised outside the GUI: the desktop app authenticates every request, so a bare curl to /api/android-emulator-helper/status answers 403 forbidden before the handler runs. The page's spacing, dark theme and narrow-width wrapping still deserve a human look in the GUI.
  • No credential handling: the plugin never reads or forwards key/token/secret environment variables.

Releases

Every release is one commit in two places: tagged vX.Y.Z on main and published to npm from that tag, whose SHA npm records as gitHead. The list is at Releases — v1.4.0 is the latest, after v1.3.1, v1.3.0, v1.2.0, v1.1.3, v1.1.2, v1.1.1, v1.1.0 and v1.0.0.

Restart the DSH host process after upgrading. The package is mounted as a link: symlink and Node caches ESM modules for the life of the process, so a change under lib/ does not take effect until the host restarts — until then the tools keep serving the old code.

Contributing

Issues and pull requests are welcome at github.com/zhz8888/dsh-android-emulator-helper. Every change has to keep pnpm check green — unit tests, a host/client consistency gate, a mount on a real Cordis host and a type check over both halves — and there is no CLA or form to fill in: a focused pull request that says what it changes and why is enough.

The package is shaped for the awesome-dsh-plugin market. Development conventions — commands, repository map, invariants, testing, commit and release rules — live in AGENTS.md.

License

MIT, copyright (c) 2026 zhz8888. Tool definitions, provider logic and the generated Kotlin/Compose project template are ported from the ZCode official android-emulator plugin, distributed under the MIT License by Z.ai; the template sources are kept verbatim. See the attribution at the end of LICENSE.

—/ 5

No ratings yet

Verified DSH bundle

Commit be6c1e26153b

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout