feat(kotlin-compose): design system fn.compose:ui + toolbelt android Linux-first
Design system Compose (kotlin/functions/ui, modulo Gradle `fn.compose:ui`):
- FnTokens + FnTheme con la paleta heredada al hex de cpp/DESIGN_SYSTEM.md
(Mantine v9 dark + indigo), identica a la web @fn_library y a las apps C++.
- 26 componentes Compose (Layout/Display/Inputs/Feedback/Data/Charts) +
FnTheme + FnTokens registrados en el registry (28 entradas kind=component
lang=kt domain=ui), descubribles via fn_search. Habilitan init_kotlin_app.
Recuperacion: el commit cb6d9e6 habia anadido `kotlin/functions/ui/` al
.gitignore, por eso el design system nunca se versiono y se perdio del working
tree. Des-ignorado; el .gitignore interno del modulo ya excluye
build/.gradle/local.properties. La gallery (apps/gallery_kt) se recupero del
sub-repo Gitea y sus 27 componentes se reconstruyeron con su MainActivity como
contrato exacto.
Toolbelt Android Linux-first (antes asumia WSL2 + Windows):
- adb_wsl 1.1.0, android_emulator_start 1.1.0, android_emulator_list 1.1.0:
resuelven adb/emulator nativos del SDK ($ANDROID_HOME), .exe solo fallback WSL2.
- android_emulator_start: fix `timeout adb_run wait-for-device` (timeout no puede
ejecutar una funcion del shell; ahora invoca el binario $ADB directamente).
- install_android_sdk 1.0.1: fix licencias bajo pipefail (SIGPIPE de `yes`) +
trap EXIT con variable unbound.
- docs/capabilities/android.md regenerado Linux-first + seccion design system.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,17 +3,17 @@ name: adb_wsl
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
purity: impure
|
||||
signature: "source adb_wsl.sh [ADB=<path>] [ANDROID_SDK_WIN=<sdk_root>]"
|
||||
description: "Wrapper sourceable para usar adb.exe Windows desde WSL2. Resuelve binario, convierte paths, espera boot del emulador."
|
||||
tags: ["android", "adb", "wsl", "windows"]
|
||||
signature: "source adb_wsl.sh [ADB=<path>] [ANDROID_HOME=<sdk_root>]"
|
||||
description: "Wrapper sourceable para resolver e invocar adb. Linux-first: usa el adb nativo del Android SDK ($ANDROID_HOME) o del PATH; fallback a adb.exe solo si detecta WSL2. Expone adb_run, adb_devices, adb_pick_serial, adb_s, adb_wait_boot."
|
||||
tags: ["android", "adb", "linux", "emulator", "wsl"]
|
||||
params:
|
||||
- name: ADB
|
||||
desc: "Env var opcional. Path absoluto a adb.exe. Si no se fija, se construye desde ANDROID_SDK_WIN o el default /mnt/c/Users/lucas/AppData/Local/Android/Sdk."
|
||||
- name: ANDROID_SDK_WIN
|
||||
desc: "Env var opcional. Raiz del Android SDK montado en WSL. Default: /mnt/c/Users/lucas/AppData/Local/Android/Sdk."
|
||||
output: "Source-able shell helpers: adb_run, adb_devices, adb_wsl_to_win, adb_wait_boot. Define ADB env var apuntando a Windows adb.exe via ANDROID_SDK_WIN."
|
||||
desc: "Env var opcional. Path absoluto al binario adb (override explicito). Si no se fija, se resuelve Linux-first: $ANDROID_HOME/platform-tools/adb, luego adb del PATH, luego adb.exe si WSL2."
|
||||
- name: ANDROID_HOME
|
||||
desc: "Env var opcional. Raiz del Android SDK nativo. Si esta presente, se usa $ANDROID_HOME/platform-tools/adb. Tambien se acepta ANDROID_SDK_ROOT."
|
||||
output: "Source-able shell helpers: adb_run, adb_devices, adb_pick_serial, adb_s, adb_wait_boot, adb_wsl_to_win. Resuelve y fija la env var ADB al binario adb disponible."
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
@@ -26,24 +26,33 @@ test_file_path: ""
|
||||
file_path: "bash/functions/infra/adb_wsl.sh"
|
||||
---
|
||||
|
||||
## Uso
|
||||
## Cuando usarla
|
||||
|
||||
Sourcéala como capa base de cualquier script que hable con un device o emulador Android via adb. Es la dependencia comun de todo el toolbelt android del registry (`android_screenshot`, `android_input_*`, `android_logcat`, `android_app_*`, `android_push/pull`). En Linux nativo resuelve el adb del SDK automaticamente; no hace falta configurar nada si `ANDROID_HOME` esta exportado (o `adb` esta en el PATH).
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
# Sourcear (usa SDK default)
|
||||
# Linux nativo: con el SDK instalado y ANDROID_HOME exportado, resuelve solo.
|
||||
source ~/android-sdk/env.sh
|
||||
source bash/functions/infra/adb_wsl.sh
|
||||
adb_devices
|
||||
# List of devices attached
|
||||
# emulator-5554 device
|
||||
|
||||
# Sourcear con SDK custom
|
||||
ANDROID_SDK_WIN=/mnt/d/Android/Sdk source bash/functions/infra/adb_wsl.sh
|
||||
# Fijar binario adb explicito (override)
|
||||
ADB=/opt/android/platform-tools/adb source bash/functions/infra/adb_wsl.sh
|
||||
|
||||
# Sourcear con binario fijo
|
||||
ADB=/mnt/c/my/tools/adb.exe source bash/functions/infra/adb_wsl.sh
|
||||
# Smoke test
|
||||
bash bash/functions/infra/adb_wsl.sh --self-test
|
||||
# Android Debug Bridge version 1.0.41
|
||||
```
|
||||
|
||||
## Funciones expuestas
|
||||
|
||||
### `adb_run "<args...>"`
|
||||
|
||||
Ejecuta `$ADB` con los argumentos dados. Retorna el exit code de `adb.exe`.
|
||||
Ejecuta `$ADB` con los argumentos dados. Retorna el exit code de adb.
|
||||
|
||||
```bash
|
||||
adb_run shell ls /sdcard/
|
||||
@@ -54,45 +63,34 @@ adb_run install app.apk
|
||||
|
||||
Alias de `adb_run devices`. Lista dispositivos/emuladores conectados.
|
||||
|
||||
```bash
|
||||
adb_devices
|
||||
# List of devices attached
|
||||
# emulator-5554 device
|
||||
```
|
||||
### `adb_pick_serial [--serial <S>] [...]`
|
||||
|
||||
### `adb_wsl_to_win <path_wsl>`
|
||||
|
||||
Convierte un path WSL a formato Windows con `wslpath -w`. Si `wslpath` no está disponible retorna el path sin convertir.
|
||||
Resuelve el serial a usar (multi-device). Lee `--serial X` de los args y setea los globals `ADB_PICK_SERIAL` y `ADB_PICK_REST`. Si no se pasa, autoselecciona el primer device/emulador conectado.
|
||||
|
||||
```bash
|
||||
win_path=$(adb_wsl_to_win /home/lucas/proyecto/app.apk)
|
||||
# C:\Users\lucas\AppData\Local\... (o la ruta Windows equivalente)
|
||||
adb_run install "$win_path"
|
||||
adb_pick_serial "$@" || { echo "no device" >&2; exit 3; }
|
||||
serial="$ADB_PICK_SERIAL"; set -- "${ADB_PICK_REST[@]}"
|
||||
```
|
||||
|
||||
### `adb_s <serial> <args...>`
|
||||
|
||||
Atajo de `adb_run -s <serial> <args...>` para multi-device.
|
||||
|
||||
### `adb_wait_boot [timeout_s]`
|
||||
|
||||
Espera a que el emulador/dispositivo complete el boot (`sys.boot_completed = 1`). Útil tras lanzar un AVD en CI.
|
||||
Espera a que el emulador/dispositivo complete el boot (`sys.boot_completed = 1`). Polling cada 3s. Retorna `0` si bootó, `1` si timeout (default 120s).
|
||||
|
||||
```bash
|
||||
adb_wait_boot # timeout 120s
|
||||
adb_wait_boot 60 # timeout 60s
|
||||
```
|
||||
### `adb_wsl_to_win <path_wsl>`
|
||||
|
||||
Retorna `0` si el boot se completó, `1` si expiró el timeout.
|
||||
Legacy WSL: convierte path WSL→Windows con `wslpath -w`. En Linux nativo (sin `wslpath`) devuelve el path tal cual.
|
||||
|
||||
## Smoke test
|
||||
## Gotchas
|
||||
|
||||
```bash
|
||||
bash bash/functions/infra/adb_wsl.sh --self-test
|
||||
# OK
|
||||
```
|
||||
- **Linux-first.** El default ya NO es Windows. Resolucion: `$ADB` → `$ANDROID_HOME/platform-tools/adb` → `adb` del PATH → (solo si `/proc/version` indica WSL2) `adb.exe`. En un PC Linux con el SDK instalado funciona sin configurar nada.
|
||||
- **Necesita el SDK o adb en PATH.** Si no encuentra adb aborta con mensaje a stderr. Instala con `fn run install_android_sdk_bash_infra` y exporta `ANDROID_HOME` (o `source ~/android-sdk/env.sh`).
|
||||
- **`ADB` se resuelve una sola vez al sourcing.** Cambiar el SDK despues requiere re-sourcear.
|
||||
- **Sourcéala con bash, no zsh.** Los consumidores usan `${BASH_SOURCE[0]}` para localizar este archivo; ejecutarlos con `bash <file>` (no `zsh`/`source` desde zsh) resuelve el path correctamente.
|
||||
|
||||
## Notas
|
||||
## Capability growth log
|
||||
|
||||
- El script es **source-able**: define funciones en el shell actual, no crea subshell.
|
||||
- `ADB` se resuelve una sola vez al sourcing. Si el binario no existe en disco, la carga falla con mensaje en stderr y `return 1` / `exit 1`.
|
||||
- `adb_wait_boot` hace polling cada 3 segundos. Ajustar `interval` si el emulador es especialmente lento.
|
||||
- En WSL2 `wslpath` siempre está disponible; el fallback existe para entornos Linux puros que accidentalmente sourceen el archivo.
|
||||
- Si el emulador requiere `-s <serial>`, pasar el flag directamente a `adb_run`: `adb_run -s emulator-5554 shell ...`.
|
||||
---
|
||||
- v1.1.0 (2026-06-03) — Linux-first: la resolucion de adb ahora prioriza el adb nativo del SDK (`$ANDROID_HOME/platform-tools/adb`) y del PATH; el adb.exe de Windows queda como fallback legacy solo bajo WSL2. Se elimina el default hardcodeado `/mnt/c/Users/lucas/...`. Todo el toolbelt android (~20 funciones) pasa a funcionar en Linux nativo sin preexportar `ADB`.
|
||||
|
||||
@@ -1,20 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# adb_wsl — Wrapper sourceable para usar adb.exe Windows desde WSL2.
|
||||
# adb_wsl — Wrapper sourceable para resolver e invocar adb.
|
||||
# Linux-first: usa el adb nativo del Android SDK o del PATH. Conserva un
|
||||
# fallback a adb.exe SOLO cuando se detecta WSL2 (legacy). El nombre del
|
||||
# archivo se mantiene por compatibilidad con sus consumidores del registry.
|
||||
# Uso: source bash/functions/infra/adb_wsl.sh
|
||||
# Smoke test: bash bash/functions/infra/adb_wsl.sh --self-test
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Resolver ADB
|
||||
# Resolver ADB (Linux-first; fallback WSL legacy)
|
||||
# ---------------------------------------------------------------------------
|
||||
# El caller puede fijar ADB antes de sourcing para apuntar a otro binario.
|
||||
# Prioridad de resolucion:
|
||||
# 1. $ADB preexportada por el caller (override explicito).
|
||||
# 2. adb nativo del Android SDK ($ANDROID_HOME / $ANDROID_SDK_ROOT).
|
||||
# 3. adb del PATH.
|
||||
# 4. (legacy) adb.exe de Windows, solo si corremos dentro de WSL2.
|
||||
if [[ -z "${ADB:-}" ]]; then
|
||||
_sdk_root="${ANDROID_SDK_WIN:-/mnt/c/Users/lucas/AppData/Local/Android/Sdk}"
|
||||
ADB="${_sdk_root}/platform-tools/adb.exe"
|
||||
unset _sdk_root
|
||||
_sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
|
||||
if [[ -n "$_sdk" && -x "$_sdk/platform-tools/adb" ]]; then
|
||||
ADB="$_sdk/platform-tools/adb"
|
||||
elif command -v adb &>/dev/null; then
|
||||
ADB="$(command -v adb)"
|
||||
elif grep -qiE "(microsoft|wsl)" /proc/version 2>/dev/null; then
|
||||
_sdk_win="${ANDROID_SDK_WIN:-/mnt/c/Users/$USER/AppData/Local/Android/Sdk}"
|
||||
ADB="${_sdk_win}/platform-tools/adb.exe"
|
||||
unset _sdk_win
|
||||
fi
|
||||
unset _sdk
|
||||
fi
|
||||
|
||||
if [[ ! -f "$ADB" ]]; then
|
||||
echo "adb_wsl: ADB no encontrado en '$ADB'. Fija ADB= o ANDROID_SDK_WIN= antes de sourcear." >&2
|
||||
if [[ -z "${ADB:-}" ]] || ! command -v "$ADB" &>/dev/null; then
|
||||
echo "adb_wsl: adb no encontrado. Instala el SDK (fn run install_android_sdk_bash_infra), exporta ANDROID_HOME, o fija ADB= antes de sourcear." >&2
|
||||
# Solo abortamos si el script se ejecuta directamente; si se sourcea,
|
||||
# permitimos continuar para que el caller maneje el error.
|
||||
return 1 2>/dev/null || exit 1
|
||||
@@ -22,8 +37,8 @@ fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# adb_run "<args...>"
|
||||
# Ejecuta el ADB Windows con los argumentos dados.
|
||||
# Retorna el exit code de adb.exe.
|
||||
# Ejecuta adb (el binario resuelto en $ADB) con los argumentos dados.
|
||||
# Retorna el exit code de adb.
|
||||
# ---------------------------------------------------------------------------
|
||||
adb_run() {
|
||||
"$ADB" "$@"
|
||||
|
||||
@@ -3,11 +3,11 @@ name: android_emulator_list
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
purity: impure
|
||||
signature: "android_emulator_list([--json])"
|
||||
description: "Lista los AVDs disponibles invocando emulator.exe Windows desde WSL2."
|
||||
tags: [android, emulator, wsl]
|
||||
description: "Lista los AVDs disponibles. Linux-first: usa el emulator nativo del Android SDK ($ANDROID_HOME); fallback a emulator.exe solo bajo WSL2."
|
||||
tags: [android, emulator, linux, avd, wsl]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
@@ -17,35 +17,41 @@ imports: []
|
||||
params:
|
||||
- name: "--json"
|
||||
desc: "Optional flag, outputs JSON array instead of newline-separated names"
|
||||
output: "Lista de AVDs disponibles en el SDK Windows. Una por linea, o JSON array con --json."
|
||||
output: "Lista de AVDs disponibles en el SDK. Una por linea, o JSON array con --json."
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "bash/functions/infra/android_emulator_list.sh"
|
||||
notes: "Lee env var EMULATOR o ANDROID_SDK_WIN. Default Windows path: /mnt/c/Users/lucas/AppData/Local/Android/Sdk/emulator/emulator.exe. Exit 0 si lista (incluso vacia). Exit 1 solo si el binario no existe o no es ejecutable."
|
||||
notes: "Resuelve el binario emulator Linux-first ($ANDROID_HOME/emulator/emulator -> emulator del PATH -> emulator.exe si WSL2). Override con EMULATOR=. Exit 0 si lista (incluso vacia). Exit 1 solo si el binario no existe."
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
source ~/android-sdk/env.sh # exporta ANDROID_HOME
|
||||
|
||||
# Listar AVDs (una por linea)
|
||||
android_emulator_list
|
||||
# Pixel_API34
|
||||
|
||||
# Listar AVDs en formato JSON
|
||||
android_emulator_list --json
|
||||
# ["Pixel_7_API_34","Pixel_4_API_30"]
|
||||
# ["Pixel_API34"]
|
||||
|
||||
# Sobreescribir ruta del emulador
|
||||
EMULATOR="/custom/path/emulator.exe" android_emulator_list
|
||||
|
||||
# Sobreescribir SDK base
|
||||
ANDROID_SDK_WIN="/mnt/d/Android/Sdk" android_emulator_list
|
||||
EMULATOR="/opt/android/emulator/emulator" android_emulator_list
|
||||
```
|
||||
|
||||
## Notas
|
||||
## Cuando usarla
|
||||
|
||||
El script es ejecutable directamente (`chmod +x`) o invocable con `bash android_emulator_list.sh`.
|
||||
Antes de arrancar un emulador, para validar que el AVD existe (lo hace `deploy_capacitor_to_emulator` y `run_kotlin_app_tests` internamente). Útil también para listar qué AVDs hay creados en la máquina.
|
||||
|
||||
`emulator.exe -list-avds` imprime warnings a stderr que se descartan con `2>/dev/null`. La captura con `mapfile` filtra ademas lineas vacias para producir una lista limpia.
|
||||
## Gotchas
|
||||
|
||||
La variable `EMULATOR` tiene prioridad sobre `ANDROID_SDK_WIN`. Si ninguna esta definida se usa el path Windows por defecto de Lucas.
|
||||
- **Linux-first.** El default ya no es Windows. Resuelve `$ANDROID_HOME/emulator/emulator`, luego `emulator` del PATH, y solo bajo WSL2 cae a `emulator.exe`.
|
||||
- `emulator -list-avds` imprime warnings a stderr que se descartan con `2>/dev/null`. La captura con `mapfile` filtra líneas vacías.
|
||||
- Override del binario con `EMULATOR=`; override del SDK con `ANDROID_HOME=`.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
- v1.1.0 (2026-06-03) — Linux-first: resuelve el emulator nativo del SDK (`$ANDROID_HOME`) y del PATH antes que `emulator.exe`; se elimina el default hardcodeado `/mnt/c/Users/lucas/...`.
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# android_emulator_list — Lista los AVDs disponibles invocando emulator.exe Windows desde WSL2.
|
||||
# android_emulator_list — Lista los AVDs disponibles. Linux-first: usa el
|
||||
# emulator nativo del Android SDK; fallback a emulator.exe solo bajo WSL2.
|
||||
set -euo pipefail
|
||||
|
||||
# Resolve emulator binary
|
||||
EMULATOR="${EMULATOR:-${ANDROID_SDK_WIN:-/mnt/c/Users/lucas/AppData/Local/Android/Sdk}/emulator/emulator.exe}"
|
||||
# Resolve emulator binary (Linux-first; WSL fallback)
|
||||
if [[ -z "${EMULATOR:-}" ]]; then
|
||||
_sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
|
||||
if [[ -n "$_sdk" && -x "$_sdk/emulator/emulator" ]]; then
|
||||
EMULATOR="$_sdk/emulator/emulator"
|
||||
elif command -v emulator &>/dev/null; then
|
||||
EMULATOR="$(command -v emulator)"
|
||||
elif grep -qiE "(microsoft|wsl)" /proc/version 2>/dev/null; then
|
||||
EMULATOR="${ANDROID_SDK_WIN:-/mnt/c/Users/$USER/AppData/Local/Android/Sdk}/emulator/emulator.exe"
|
||||
fi
|
||||
unset _sdk
|
||||
fi
|
||||
|
||||
if [[ ! -x "$EMULATOR" ]]; then
|
||||
echo "error: emulator binary not found or not executable: $EMULATOR" >&2
|
||||
if [[ -z "${EMULATOR:-}" ]] || ! command -v "$EMULATOR" &>/dev/null; then
|
||||
echo "error: emulator no encontrado. Instala el SDK (fn run install_android_sdk_bash_infra) + el paquete 'emulator', exporta ANDROID_HOME, o fija EMULATOR=." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@ name: android_emulator_start
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
version: "1.1.0"
|
||||
purity: impure
|
||||
signature: "android_emulator_start(avd_name: string, timeout_s: int) -> string"
|
||||
description: "Arranca un AVD en background y espera a que termine de bootear. Idempotente: si ya hay emulador corriendo no lanza otro."
|
||||
tags: [android, emulator, wsl]
|
||||
description: "Arranca un AVD Android en background y espera a que termine de bootear. Linux-first: resuelve el emulator/adb nativos del SDK; fallback a binarios .exe solo bajo WSL2. Idempotente: si ya hay un emulador corriendo, imprime 'already running' y su serial sin lanzar otro."
|
||||
tags: [android, emulator, linux, avd, wsl]
|
||||
params:
|
||||
- name: avd_name
|
||||
desc: "Nombre del AVD a arrancar (visible con android_emulator_list o `emulator.exe -list-avds`)"
|
||||
desc: "Nombre del AVD a arrancar (visible con android_emulator_list o `emulator -list-avds`)"
|
||||
- name: timeout_s
|
||||
desc: "Timeout total en segundos para esperar el boot completo. Opcional, default 180"
|
||||
output: "Serial del device emulado (ej. emulator-5554) en stdout. Exit 0 = boot completo, exit 1 = timeout o emulador murio."
|
||||
@@ -29,21 +29,31 @@ file_path: "bash/functions/infra/android_emulator_start.sh"
|
||||
## Ejemplo
|
||||
|
||||
```bash
|
||||
source ~/android-sdk/env.sh # exporta ANDROID_HOME -> resuelve emulator/adb nativos
|
||||
source bash/functions/infra/android_emulator_start.sh
|
||||
|
||||
# Arrancar AVD con timeout por defecto (180s)
|
||||
serial=$(android_emulator_start "Pixel_6_API_34")
|
||||
serial=$(android_emulator_start "Pixel_API34")
|
||||
echo "Emulador listo: $serial" # emulator-5554
|
||||
|
||||
# Con timeout personalizado
|
||||
serial=$(android_emulator_start "Pixel_6_API_34" 300)
|
||||
serial=$(android_emulator_start "Pixel_API34" 300)
|
||||
```
|
||||
|
||||
## Notas
|
||||
Para ver la ventana del emulador en un escritorio Linux, exporta `DISPLAY` (y `XAUTHORITY`) antes de invocar.
|
||||
|
||||
- Sourcea `adb_wsl.sh` del mismo directorio si existe (provee `ADB`, `adb_run`, `adb_wait_boot`). Si no, usa implementacion inline.
|
||||
- Resuelve `EMULATOR` y `ADB` desde `ANDROID_SDK_WIN` (default `/mnt/c/Users/lucas/AppData/Local/Android/Sdk`) o desde las variables de entorno `EMULATOR=` / `ADB=` si ya están fijadas.
|
||||
- Idempotente: si `adb devices` ya muestra un `emulator-*`, imprime "already running" + el serial y sale con exit 0 sin lanzar un segundo proceso.
|
||||
- Log del emulador en `/tmp/emulator_<avd>.log`. PID en `/tmp/emulator_<avd>.pid`.
|
||||
- El timeout total se reparte: primera mitad para `adb wait-for-device`, segunda mitad para esperar `sys.boot_completed=1`.
|
||||
- Diseñado para WSL2 con Android SDK instalado en Windows. En Linux nativo basta cambiar las rutas de los binarios via `EMULATOR=` y `ADB=`.
|
||||
## Cuando usarla
|
||||
|
||||
Cuando un script necesita un emulador booteado antes de instalar un APK o correr tests instrumentados (`gradle_instrumented_test`, `run_kotlin_app_tests`). Es idempotente, así que se puede llamar al principio de cualquier pipeline sin comprobar antes si ya hay uno arriba.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Linux-first.** Resuelve `EMULATOR`/`ADB` desde `$ANDROID_HOME/{emulator/emulator, platform-tools/adb}` o del PATH; `emulator.exe`/`adb.exe` solo como fallback bajo WSL2. Override manual con `EMULATOR=`/`ADB=`.
|
||||
- **Necesita `DISPLAY` para ventana.** Sin un servidor X accesible el emulador puede fallar al abrir ventana. Para headless/CI añade `-no-window` (editar la función o lanzar el emulador aparte).
|
||||
- **Aceleración KVM.** Requiere acceso a `/dev/kvm` (grupo `kvm` o ACL). Sin ella el boot es lentísimo o falla.
|
||||
- Log del emulador en `/tmp/emulator_<avd>.log`, PID en `/tmp/emulator_<avd>.pid`.
|
||||
- El timeout total se reparte: primera mitad para `adb wait-for-device`, segunda para `sys.boot_completed=1`.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
- v1.1.0 (2026-06-03) — Linux-first: resuelve emulator/adb nativos del SDK (`$ANDROID_HOME`) antes que los `.exe` de Windows (ahora solo fallback WSL2); se elimina el default hardcodeado `/mnt/c/Users/lucas/...`. fix: `timeout <n> adb_run wait-for-device` fallaba siempre porque `timeout` no puede ejecutar la función shell `adb_run`; ahora invoca el binario `"$ADB"` directamente.
|
||||
|
||||
@@ -11,11 +11,17 @@ if [[ -f "$_ADB_WSL_SH" ]]; then
|
||||
# shellcheck source=adb_wsl.sh
|
||||
source "$_ADB_WSL_SH"
|
||||
else
|
||||
# Fallback inline: resolver ADB
|
||||
# Fallback inline: resolver ADB (Linux-first; WSL fallback)
|
||||
if [[ -z "${ADB:-}" ]]; then
|
||||
_sdk_root="${ANDROID_SDK_WIN:-/mnt/c/Users/lucas/AppData/Local/Android/Sdk}"
|
||||
ADB="${_sdk_root}/platform-tools/adb.exe"
|
||||
unset _sdk_root
|
||||
_sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
|
||||
if [[ -n "$_sdk" && -x "$_sdk/platform-tools/adb" ]]; then
|
||||
ADB="$_sdk/platform-tools/adb"
|
||||
elif command -v adb &>/dev/null; then
|
||||
ADB="$(command -v adb)"
|
||||
else
|
||||
ADB="${ANDROID_SDK_WIN:-/mnt/c/Users/$USER/AppData/Local/Android/Sdk}/platform-tools/adb.exe"
|
||||
fi
|
||||
unset _sdk
|
||||
fi
|
||||
adb_run() { "$ADB" "$@"; }
|
||||
adb_wait_boot() {
|
||||
@@ -33,12 +39,18 @@ else
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Resolver EMULATOR
|
||||
# Resolver EMULATOR (Linux-first; WSL fallback)
|
||||
# ---------------------------------------------------------------------------
|
||||
if [[ -z "${EMULATOR:-}" ]]; then
|
||||
_sdk_root="${ANDROID_SDK_WIN:-/mnt/c/Users/lucas/AppData/Local/Android/Sdk}"
|
||||
EMULATOR="${_sdk_root}/emulator/emulator.exe"
|
||||
unset _sdk_root
|
||||
_sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
|
||||
if [[ -n "$_sdk" && -x "$_sdk/emulator/emulator" ]]; then
|
||||
EMULATOR="$_sdk/emulator/emulator"
|
||||
elif command -v emulator &>/dev/null; then
|
||||
EMULATOR="$(command -v emulator)"
|
||||
elif grep -qiE "(microsoft|wsl)" /proc/version 2>/dev/null; then
|
||||
EMULATOR="${ANDROID_SDK_WIN:-/mnt/c/Users/$USER/AppData/Local/Android/Sdk}/emulator/emulator.exe"
|
||||
fi
|
||||
unset _sdk
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -49,12 +61,12 @@ android_emulator_start() {
|
||||
local timeout_s="${2:-180}"
|
||||
|
||||
# Validaciones de entorno
|
||||
if [[ ! -f "$EMULATOR" ]]; then
|
||||
echo "android_emulator_start: emulator.exe no encontrado en '$EMULATOR'. Fija EMULATOR= o ANDROID_SDK_WIN=." >&2
|
||||
if [[ -z "${EMULATOR:-}" ]] || ! command -v "$EMULATOR" &>/dev/null; then
|
||||
echo "android_emulator_start: emulator no encontrado. Instala el SDK + paquete 'emulator', exporta ANDROID_HOME, o fija EMULATOR=." >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -f "$ADB" ]]; then
|
||||
echo "android_emulator_start: adb.exe no encontrado en '$ADB'. Fija ADB= o ANDROID_SDK_WIN=." >&2
|
||||
if [[ -z "${ADB:-}" ]] || ! command -v "$ADB" &>/dev/null; then
|
||||
echo "android_emulator_start: adb no encontrado. Instala platform-tools, exporta ANDROID_HOME, o fija ADB=." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -74,9 +86,12 @@ android_emulator_start() {
|
||||
local emu_pid=$!
|
||||
echo "$emu_pid" > "$pid_file"
|
||||
|
||||
# Esperar a que el dispositivo aparezca en adb
|
||||
# Esperar a que el dispositivo aparezca en adb.
|
||||
# Usamos el binario "$ADB" directamente (no la funcion adb_run): `timeout`
|
||||
# ejecuta un comando externo y no puede ver funciones del shell, asi que
|
||||
# `timeout ... adb_run` fallaba siempre con "command not found".
|
||||
local wait_timeout=$(( timeout_s / 2 ))
|
||||
if ! timeout "$wait_timeout" adb_run wait-for-device 2>/dev/null; then
|
||||
if ! timeout "$wait_timeout" "$ADB" wait-for-device 2>/dev/null; then
|
||||
echo "android_emulator_start: timeout esperando que el dispositivo aparezca en adb (${wait_timeout}s)." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -3,7 +3,7 @@ name: install_android_sdk
|
||||
kind: function
|
||||
lang: bash
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
version: "1.0.1"
|
||||
purity: impure
|
||||
signature: "install_android_sdk() -> void"
|
||||
description: "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."
|
||||
@@ -50,6 +50,17 @@ ANDROID_SDK_DIR=/opt/android source install_android_sdk.sh
|
||||
source ~/android-sdk/env.sh
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando necesites un Android SDK funcional en una maquina Linux sin permisos de root: CI, contenedores, o un PC de desarrollo donde quieras un SDK aislado en `$HOME`. Instala la base minima para compilar (cmdline-tools + JDK 17 + platform-tools + API 34 + build-tools). Hazle `source` para tener `sdkmanager`/`avdmanager`/`adb` en el PATH antes de invocar `gradle_run`, `gradle_assemble_debug` o `capacitor_build_apk`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **No instala `emulator` ni system images.** Solo la base de compilacion. Para correr un AVD: tras hacer `source env.sh`, instala `emulator` y una imagen (`sdkmanager "emulator" "system-images;android-34;google_apis;x86_64"`) y crea el AVD con `avdmanager create avd`.
|
||||
- **Aceleracion KVM:** el emulador necesita acceso a `/dev/kvm`. Verifica con `[ -w /dev/kvm ]`; si no, anade tu usuario al grupo `kvm` (`sudo usermod -aG kvm $USER` + re-login) o concede ACL.
|
||||
- **URL de cmdline-tools clavada** a la build 11076708 (2024). Si Google la retira, actualizar `tools_url` en el `.sh`.
|
||||
- **Idempotente:** re-ejecutar no reinstala; detecta `sdkmanager` existente y sale en 0.
|
||||
|
||||
## Notas
|
||||
|
||||
Requiere `curl` y `unzip` (disponibles en la mayoria de distros Linux). No requiere root ni sudo.
|
||||
@@ -61,3 +72,7 @@ La reorganizacion del zip es necesaria porque Google distribuye cmdline-tools co
|
||||
El archivo `env.sh` generado en `$ANDROID_SDK_DIR/env.sh` contiene las variables de entorno necesarias (`JAVA_HOME`, `ANDROID_HOME`, `ANDROID_SDK_ROOT`, `PATH`) y puede hacerse source desde `.bashrc`, `.zshrc` o desde scripts de CI.
|
||||
|
||||
Paquetes instalados: `platform-tools` (adb, fastboot), `platforms;android-34` (API 34), `build-tools;34.0.0`.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
- v1.0.1 (2026-06-03) — fix: `yes | sdkmanager --licenses` daba falso negativo bajo `pipefail` (SIGPIPE de `yes`, exit 141) abortando una instalacion exitosa; ahora se desactiva `pipefail` solo en ese pipe. fix: el trap `EXIT` referenciaba `$tmp_dir` (variable `local`) fuera del scope de la funcion → "unbound variable" con `set -u`; ahora es global con expansion defensiva.
|
||||
|
||||
@@ -5,11 +5,14 @@ set -euo pipefail
|
||||
|
||||
install_android_sdk() {
|
||||
local sdk_dir="${ANDROID_SDK_DIR:-$HOME/android-sdk}"
|
||||
local tmp_dir
|
||||
# tmp_dir es global a proposito: el trap EXIT se dispara al terminar el
|
||||
# script (fuera del scope de la funcion), donde una variable `local` ya no
|
||||
# existiria y `set -u` la marcaria como unbound. La expansion defensiva
|
||||
# ${tmp_dir:-} evita el fallo aunque el trap corra antes de la asignacion.
|
||||
tmp_dir="$(mktemp -d)"
|
||||
|
||||
# Limpia temporales al salir
|
||||
trap 'rm -rf "$tmp_dir"' EXIT
|
||||
trap 'rm -rf "${tmp_dir:-}"' EXIT
|
||||
|
||||
# 1. Verifica si ya está instalado
|
||||
if [[ -f "$sdk_dir/cmdline-tools/latest/bin/sdkmanager" ]]; then
|
||||
@@ -103,11 +106,18 @@ install_android_sdk() {
|
||||
export PATH="$JAVA_HOME/bin:$sdk_dir/cmdline-tools/latest/bin:$sdk_dir/platform-tools:$PATH"
|
||||
|
||||
# 4. Acepta licencias e instala paquetes necesarios
|
||||
# `yes` recibe SIGPIPE (exit 141) cuando sdkmanager termina de leer y cierra
|
||||
# el pipe; bajo `set -o pipefail` eso convierte un exito real en falso
|
||||
# negativo. Desactivamos pipefail solo aqui para que el exit del pipeline
|
||||
# refleje el de sdkmanager (ultimo comando), no el SIGPIPE de `yes`.
|
||||
echo "Aceptando licencias de Android SDK..."
|
||||
if ! yes | "$sdkmanager" --licenses; then
|
||||
set +o pipefail
|
||||
if ! yes | "$sdkmanager" --licenses >/dev/null 2>&1; then
|
||||
set -o pipefail
|
||||
echo "ERROR: fallo al aceptar licencias de Android SDK" >&2
|
||||
return 1
|
||||
fi
|
||||
set -o pipefail
|
||||
|
||||
echo "Instalando platform-tools, platforms;android-34, build-tools;34.0.0..."
|
||||
if ! "$sdkmanager" "platform-tools" "platforms;android-34" "build-tools;34.0.0"; then
|
||||
|
||||
Reference in New Issue
Block a user