--- name: unibus_android domain: tools version: 0.1.0 description: "Cliente Android (Jetpack Compose) del bus unibus: conecta, crea salas y chatea con el mismo cliente Go (pkg/client) compilado a un .aar via gomobile, conservando el cifrado E2E." tags: [messaging, nats, e2e, android, compose, kotlin, gomobile, client] lang: kt framework: compose entry_point: "app/src/main/kotlin/com/fnregistry/unibus/MainActivity.kt" dir_path: "projects/message_bus/apps/unibus_android" repo_url: "https://gitea.organic-machine.com/dataforge/unibus_android" uses_functions: - fn_theme_kt_ui - fn_tokens_kt_ui - fn_stack_kt_ui - fn_group_kt_ui - fn_card_kt_ui - fn_badge_kt_ui - fn_button_kt_ui - fn_text_kt_ui - fn_title_kt_ui - fn_text_input_kt_ui - fn_switch_kt_ui uses_types: [] e2e_checks: - id: bind cmd: "cd ../unibus && gomobile bind -target=android -androidapi 24 -o ../unibus_android/app/libs/unibus.aar github.com/enmanuel/unibus/mobile" timeout_s: 600 - id: build cmd: "fn run gradle_assemble_debug_bash_infra projects/message_bus/apps/unibus_android" timeout_s: 360 --- # unibus_android Cliente Android del bus de mensajería `unibus`. La aplicación es una fina capa de interfaz en Jetpack Compose sobre el cliente Go real del bus: `pkg/client` se compila a una librería nativa Android (`unibus.aar`) con `gomobile bind`, de modo que el teléfono habla el protocolo NATS y ejecuta el mismo cifrado end-to-end (ChaCha20-Poly1305 + Ed25519 + X25519) que cualquier otro peer. No se reimplementa ni el protocolo ni la criptografía: hay una única fuente de verdad compartida con el resto del ecosistema. ## Arquitectura ``` MainActivity.kt (Compose UI) └── mobile.Session (Kotlin, generado por gomobile) └── unibus.aar (libgojni.so: pkg/client + nats.go + crypto del registry) ├── data plane → NATS TCP (nats://host:4250) └── control plane → HTTP REST (http://host:8470) ``` El wrapper Go que define la API plana del binding vive en `projects/message_bus/apps/unibus/mobile/unibus.go` (paquete `mobile`): expone `NewSession`, `CreateRoom`, `Join`, `Publish`, `Subscribe`, `Request` y la interfaz `FrameListener` con tipos compatibles con gomobile (string, []byte, int, error, interface). ## Regenerar el binding (.aar) Tras tocar `pkg/client` o el wrapper `mobile/`: ```bash cd projects/message_bus/apps/unibus export ANDROID_HOME=$HOME/android-sdk export ANDROID_NDK_HOME=$(ls -d $HOME/android-sdk/ndk/* | head -1) export PATH="$PATH:$(go env GOPATH)/bin" gomobile bind -target=android -androidapi 24 \ -o ../unibus_android/app/libs/unibus.aar \ github.com/enmanuel/unibus/mobile ``` ## Build del APK ```bash fn run gradle_assemble_debug_bash_infra projects/message_bus/apps/unibus_android # o, directo: cd projects/message_bus/apps/unibus_android && ./gradlew :app:assembleDebug # salida: app/build/outputs/apk/debug/app-debug.apk ``` ## Probarlo contra el bus 1. Levantar el control plane real (NATS embebido + REST de membresía): ```bash cd projects/message_bus/apps/unibus go run ./cmd/membershipd # HTTP :8470, NATS :4250 ``` 2. En el **emulador** (`Pixel_API34`), instalar el APK. La app usa `host = 10.0.2.2`, que el emulador mapea al loopback del PC, así que conecta sin más configuración. 3. En la app: Conectar → Crear sala → escribir un mensaje. El mensaje viaja al bus por NATS y vuelve al propio suscriptor (eco del subject), confirmando el camino completo APK → bus → APK. ## Gotchas - `cmd/membershipd` escucha en `127.0.0.1` (líneas `addr := "127.0.0.1:" + httpPort`). Desde el emulador funciona (10.0.2.2 → loopback del host). Para un **teléfono real** en la LAN o vía Tailscale hay que bindear el control plane y el NATS embebido a `0.0.0.0` y usar la IP de red del PC/VPS en los campos Host de la app. - El control plane v1 es HTTP sin TLS; el manifest declara `usesCleartextTraffic="true"`. Para producción, exponer el bus con TLS y quitar ese flag. - El `.aar` pesa ~24 MB (runtime Go embebido) y el APK debug ~54 MB. Es esperado: el cliente Go completo viaja dentro. - `onFrame` del `FrameListener` llega en una goroutine de entrega de NATS; la UI hace `Handler(mainLooper).post { ... }` antes de tocar el estado de Compose. ## Capability growth log - v0.1.0 (2026-06-05) — baseline: conectar, crear sala (modo nats/matrix), publicar y recibir mensajes en vivo. Binding gomobile del `pkg/client` con cifrado E2E intacto.