| name | android-deploy |
| description | Build and deploy an Android app to a connected device or emulator using Gradle + the Android CLI's `android describe` and `android run`. Use whenever the user wants to install / launch / sideload an app, test a code change on a device, deploy a service component, or push split APKs. Triggers include "앱 띄워줘", "디바이스에 설치", "에뮬에 deploy", "APK 설치", "run on device", "앱 빌드해서 띄워줘", "deploy". Do NOT use this skill to create or start emulators — use `android-emulator` for that. |
android-deploy
Standard build → deploy loop for an Android app, using android describe to discover APK paths reliably and android run to install/launch (handles split APKs and multi-device better than raw adb install).
Configuration
{
"androidCli": {
"defaultDevice": "emulator-5554",
"defaultBuildVariant": "debug"
}
}
| Field | Purpose |
|---|
androidCli.defaultDevice | Target serial when multiple devices are connected. Override per call with --device. |
androidCli.defaultBuildVariant | debug or release. Drives Gradle task selection (assembleDebug vs assembleRelease). |
If neither is set and ambiguity exists at runtime, ask once and save the answer.
Workflow
gradle assemble<Variant> → android describe → android run [--device=…] [--type=…] [--debug]
↓
verify launch via logcat
Step-by-step
-
Pre-flight: device available?
adb devices
- 0 devices → stop and route the user to
android-emulator (this skill does not start emulators).
- 1 device → use it implicitly.
- 2+ devices → resolve target via
androidCli.defaultDevice or prompt.
-
Build. Don't use android for this — it has no build subcommand.
./gradlew assembleDebug
For multi-module projects target a specific module: ./gradlew :app:assembleDebug.
-
Discover APK paths. Use android describe instead of guessing under app/build/outputs/apk/...:
android describe --project_dir=.
The output points at JSON files describing build targets and their output artifacts. Read those JSONs to get exact APK paths. This is more robust than hard-coded paths because module names and variants vary.
-
Deploy.
android run --apks=<comma-separated-apks>
-
Verify. Tail logcat for the package and confirm no immediate crash:
adb -s <serial> logcat -T 100 --pid=$(adb -s <serial> shell pidof <pkg>)
Decision matrix — android run vs alternatives
| Situation | Use | Don't use | Why |
|---|
| Standard debug install on connected device | android run | adb install | Simpler args, handles splits |
| Split APKs (App Bundle outputs) | android run --apks=a,b,c | adb install-multiple | Less error-prone, no order issues |
| Background service test | android run --type=SERVICE | am start-service | Auto-installs the APK first |
| Already installed, just relaunch | adb shell am start -n … | android run | Avoids reinstall |
Deploy via Gradle plugin (installDebug) | ./gradlew installDebug | both | Useful in CI; redundant locally if also using android run |
Operating rules
- Don't double-install. If the user already ran
./gradlew installDebug, skip android run (or vice versa).
- Always check
adb devices first. Never assume there's exactly one device.
- Never hard-code APK paths. Use
android describe output or the gradle task's reported output.
- Prefer debug variant by default. Release builds need signing config and shouldn't be sideloaded for normal development.
--debug is for IDE debugger attach, not for "build a debug APK". Don't conflate with --variant=debug.
- Never use
--type without --activity. Pair them; --type alone has no target.
- No mock APKs. If
assemble* failed, surface the gradle error; don't fabricate a path or proceed.
Anti-patterns
- ❌
adb install app-debug.apk for a project that emits split APKs (will install only base, app crashes at runtime with missing resources).
- ❌ Hardcoding
app/build/outputs/apk/debug/app-debug.apk instead of using android describe.
- ❌ Running
./gradlew installDebug && android run … (duplicate install).
- ❌ Forgetting
--device= when multiple emulators / devices are connected — android run errors out, not silently picks one.
- ❌ Calling this skill when no device is attached. Route to
android-emulator first.
- ❌ Deploying release builds without signing config — the install will fail mysteriously.
Error recovery
| Error | Cause | Fix |
|---|
INSTALL_FAILED_VERSION_DOWNGRADE | Existing app has higher versionCode | adb -s <serial> uninstall <pkg> then retry |
INSTALL_FAILED_UPDATE_INCOMPATIBLE | Signature mismatch (debug vs release, or different keystore) | adb uninstall <pkg> then retry |
Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE] | Emulator out of space | Stop emulator, recreate with bigger disk, or adb shell pm clear <pkg> |
more than one device/emulator | Forgot --device | Run adb devices, pick serial, retry with --device=<serial> |
error: device unauthorized | USB debugging not approved on physical device | Approve the dialog on device, retry |
Gradle: Unable to find APK | assemble* was skipped (cache up-to-date) but artifacts pruned | ./gradlew clean assembleDebug |