# Capability: android Toolbelt Android operable desde WSL2. Cubre: ADB (`adb_wsl`, conexion al daemon Windows), AVD emulator management (list/start/stop/wait, geo-fix), APK lifecycle (`android_apk_install`, `android_app_clear`, `android_app_launch`, `android_uninstall`), Capacitor build pipelines (`capacitor_build_apk`, `deploy_capacitor_to_emulator`), logcat streaming. WSL2 -> Windows adb daemon, no requiere Android Studio. ## Funciones | ID | Firma | Que hace | |---|---|---| | `adb_wsl_bash_infra` | `source adb_wsl.sh [ADB=] [ANDROID_SDK_WIN=]` | Wrapper sourceable para usar adb.exe Windows desde WSL2. Resuelve binario, convierte paths, espera boot del emulador. | | `android_apk_install_bash_infra` | `android_apk_install([--serial S], apk_path: string, package_name?: string, activity_name?: string) -> void` | Instala APK en device/emulador via adb y opcionalmente lanza la app. Multi-emulator via --serial. | | `android_app_clear_bash_infra` | `android_app_clear([--serial ], package: string) -> void` | Wipe app data + cache via pm clear. App keeps installed but factory-state. Multi-emulator via --serial. | | `android_app_info_bash_infra` | `android_app_info([--serial ], package, [--json]) -> stdout` | Inspect installed app: version, target SDK, activities via dumpsys package. | | `android_app_kill_bash_infra` | `android_app_kill([--serial ], package: string) -> void` | Force-stop running app via am force-stop. Multi-emulator via --serial. | | `android_app_launch_bash_infra` | `android_app_launch([--serial ], package: string, [activity: string]) -> void` | Launch app activity via am start. Multi-emulator via --serial. | | `android_app_uninstall_bash_infra` | `android_app_uninstall([--serial ] package [--keep-data]) -> void` | Uninstall app via adb uninstall. Optionally keep data with --keep-data. | | `android_emu_battery_bash_infra` | `android_emu_battery([--serial ], level: int, [--charging ]) -> void` | Simulate battery state on emulator (level + charging). Emulator-only. | | `android_emu_geo_fix_bash_infra` | `android_emu_geo_fix([--serial ], longitude: string, latitude: string, [altitude: string]) -> void` | Fake GPS location on Android emulator via emu geo fix. Emulator-only (not physical devices). | | `android_emu_rotate_bash_infra` | `android_emu_rotate([--serial ] [portrait\|landscape\|0\|90\|180\|270])` | Rotate emulator screen. Empty=toggle, or fixed orientation. Locks autorotate. | | `android_emulator_list_bash_infra` | `android_emulator_list([--json])` | Lista los AVDs disponibles invocando emulator.exe Windows desde WSL2. | | `android_emulator_start_bash_infra` | `android_emulator_start(avd_name: string, timeout_s: int) -> string` | Arranca un AVD en background y espera a que termine de bootear. Idempotente: si ya hay emulador corriendo no lanza otro. | | `android_emulator_stop_bash_infra` | `android_emulator_stop(serial?: string) -> void` | Para uno o todos los emuladores Android via adb emu kill. Si serial esta vacio, detecta todos los emulator-* activos y los para. Idempotente: exit 0 aunque no haya nada que matar. | | `android_input_keyevent_bash_infra` | `android_input_keyevent([--serial ] key: string)` | Send key event via adb shell input keyevent. Accepts aliases (BACK, HOME, POWER, ENTER, MENU, RECENT_APPS, VOLUME_UP, VOLUME_DOWN), raw numeric codes, or explicit KEYCODE_* names. | | `android_input_swipe_bash_infra` | `android_input_swipe([--serial ], x1: int, y1: int, x2: int, y2: int, [duration_ms: int])` | Send swipe gesture between two points with duration. | | `android_input_tap_bash_infra` | `android_input_tap([--serial ], x: int, y: int) -> void` | Send tap gesture at screen coordinates via adb shell input tap. | | `android_input_text_bash_infra` | `android_input_text([--serial ], text: string) -> void` | Type text in focused field via adb shell input text. Spaces handled. | | `android_logcat_bash_infra` | `android_logcat([--serial ] [--package ] [--level ] [--lines ] [--clear])` | Lee logcat del device/emulador, opcionalmente filtrado por package y nivel. Multi-emulator via --serial. | | `android_pull_bash_infra` | `android_pull [--serial ] remote_path local_path` | Pull file/dir from Android device to WSL via adb pull. | | `android_push_bash_infra` | `android_push([--serial ], local_path: string, remote_path: string) -> void` | Push file/dir from WSL to Android device via adb push. | | `android_screen_record_bash_infra` | `android_screen_record([--serial ] [--duration ] [--bit-rate ] [--size ] output_path: string) -> void` | Record screen video via adb screenrecord, pulls to local path. | | `android_screenshot_bash_infra` | `android_screenshot([--serial ], output_path: string) -> void` | Capture screen as PNG via adb exec-out screencap -p. | | `android_shell_bash_infra` | `android_shell([--serial ], cmd ...args)` | Execute arbitrary shell command on Android device. Multi-emulator via --serial. | | `capacitor_build_apk_bash_pipelines` | `capacitor_build_apk(web_app_dir: string, [app_id: string], [app_name: string]) -> void` | Pipeline que convierte una web app en un APK de Android usando Capacitor. Valida el entorno (ANDROID_HOME, Java 17+), construye el bundle web si no existe dist/, inicializa Capacitor si no está configurado, añade la plataforma Android, sincroniza y compila el APK con Gradle. El APK final queda en el directorio raíz de la web app. | | `deploy_capacitor_to_emulator_bash_pipelines` | `deploy_capacitor_to_emulator(app_dir: string, avd_name?: string, package_name?: string) -> void` | Pipeline end-to-end: build Capacitor APK + arranca AVD + instala + opcionalmente lanza la app. Valida que el AVD existe, construye el APK con capacitor_build_apk, arranca el emulador de forma idempotente, instala el APK y lanza la app si se da package_name. Imprime comando logcat sugerido al final. | | `gradle_assemble_debug_bash_infra` | `gradle_assemble_debug(project_dir: string, module: string) -> string` | Build APK debug de un modulo Android via gradlew assembleDebug. | | `gradle_clean_bash_infra` | `gradle_clean(project_dir: string) -> int` | Limpia build artifacts de un proyecto Android (gradle clean + rm .gradle + rm build). | | `gradle_instrumented_test_bash_infra` | `gradle_instrumented_test(project_dir: string, module: string) -> int` | Corre instrumented tests Compose en emulador/device Android conectado. | | `gradle_run_bash_infra` | `gradle_run(project_dir: string, task...: string) -> int` | Wrapper canonico para invocar gradlew Android en WSL2 con JDK 17 + ANDROID_HOME validados. | | `gradle_screenshot_test_bash_infra` | `gradle_screenshot_test(project_dir: string, module: string, flag: string) -> int` | Corre screenshot tests Roborazzi de Composables (JVM, no necesita emulador). | | `gradle_unit_test_bash_infra` | `gradle_unit_test(project_dir: string, module: string, --variant : string) -> int` | Corre unit tests JVM de un modulo Android (no requiere emulador). | | `init_kotlin_app_bash_pipelines` | `init_kotlin_app(name: string, [--project

] [--desc ] [--tags ] [--package ]) -> void` | Scaffolder canonico de app Android Kotlin Compose con FnTheme + Roborazzi tests + e2e_checks declarados. Mirror exacto del patron init_cpp_app para el stack Kotlin. | | `install_android_sdk_bash_infra` | `install_android_sdk() -> void` | Descarga e instala Android SDK command-line tools y JDK 17 localmente (sin root/sudo) en $ANDROID_SDK_DIR (default: $HOME/android-sdk). Idempotente: detecta instalacion existente y sale sin hacer nada. Genera env.sh con JAVA_HOME, ANDROID_HOME y PATH listos para hacer source. | | `nominatim_reverse_geocode_kt_infra` | `fun nominatimReverseGeocode(lat: Double, lon: Double, lang: String = "es"): GeocodedLocation` | Reverse geocoding usando Nominatim (OpenStreetMap). Convierte coordenadas lat/lon a una dirección estructurada (calle, ciudad, país, etc.) para Android/Kotlin sin dependencias externas. | | `ollama_chat_kt_infra` | `fun ollamaChat(messages: List>, model: String = "llama3.1:8b", baseUrl: String = "http://localhost:11434", temperature: Double = 0.7, maxTokens: Int = 1024): OllamaChatResponse` | Envía una solicitud de chat completion a un servidor Ollama local. Retorna el contenido generado junto a métricas de duración y tokens evaluados. | | `overpass_nearby_pois_kt_infra` | `fun overpassNearbyPois(lat: Double, lon: Double, radiusM: Int = 500, categories: List? = null): List` | Consulta la Overpass API (OpenStreetMap) para obtener POIs cercanos a una coordenada. Soporta 16 categorias mapeadas a tags OSM (amenity, tourism, historic, leisure, shop). Sin dependencias externas: solo Android SDK (HttpURLConnection + org.json). | | `run_kotlin_app_tests_bash_pipelines` | `run_kotlin_app_tests(project_dir: string, avd_name?: string, --skip-emulator?, --no-stop?) -> int` | Pipeline e2e completo de testing app Kotlin: unit JVM + screenshot Roborazzi + build APK + instrumented Compose en emulador. | ## Ejemplo canonico ### Arrancar emulator + deploy Capacitor + logcat ```bash ./fn run android_emulator_list ./fn run android_emulator_start --avd Pixel_7_API_34 --wait ./fn run deploy_capacitor_to_emulator \ --app-dir ~/projects/myapp \ --avd Pixel_7_API_34 \ --package com.example.myapp ./fn run adb_wsl -- logcat -v time | grep -E "(myapp|FATAL|AndroidRuntime)" ``` ### APK install/uninstall manual ```bash ./fn run android_apk_install --apk ~/myapp.apk --device emulator-5554 ./fn run android_app_launch --package com.example.myapp ./fn run android_app_clear --package com.example.myapp # limpia datos sin uninstall ``` ## Fronteras - **NO compila APK desde Gradle nativo**. Solo Capacitor build. Para Gradle puro, ver issue 0076 (`gradle_run`). - **NO instala Android SDK**. Asume `ANDROID_HOME` apuntando al SDK Windows accessible via WSL. - **NO maneja iOS**. Solo Android. Para iOS, ver issue 0072h (gamedev roadmap). - **NO depura nativo NDK**. Para LLDB-stage debugging, attach manual via Android Studio.