Files
agent c13d6baf60 feat: Android Compose client for the unibus bus
Thin Jetpack Compose UI over the real Go client (pkg/client) compiled to a
gomobile .aar, so the phone speaks NATS and runs the same end-to-end crypto as
any other peer. Connect, create room (nats/matrix), publish and live-receive.
2026-06-05 17:40:28 +02:00

4.4 KiB

name, domain, version, description, tags, lang, framework, entry_point, dir_path, repo_url, uses_functions, uses_types, e2e_checks
name domain version description tags lang framework entry_point dir_path repo_url uses_functions uses_types e2e_checks
unibus_android tools 0.1.0 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.
messaging
nats
e2e
android
compose
kotlin
gomobile
client
kt compose app/src/main/kotlin/com/fnregistry/unibus/MainActivity.kt projects/message_bus/apps/unibus_android https://gitea.organic-machine.com/dataforge/unibus_android
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
id cmd timeout_s
bind cd ../unibus && gomobile bind -target=android -androidapi 24 -o ../unibus_android/app/libs/unibus.aar github.com/enmanuel/unibus/mobile 600
id cmd timeout_s
build fn run gradle_assemble_debug_bash_infra projects/message_bus/apps/unibus_android 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/:

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

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):
    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.