Files
unibus/android
egutierrez a11d67cf70 feat(android): app Kotlin/Compose sobre el binding gomobile
Cliente móvil nativo: embebe un peer real del bus (unibus.aar), de modo que
el cifrado E2E y el transporte NATS corren en el dispositivo.

- Conexión: Host (control plane) + NATS (data plane) + identidad; defaults
  10.0.2.2 para el emulador, configurables (sin IPs hardcodeadas).
- BusViewModel: llamadas de red del binding en Dispatchers.IO; los frames
  entrantes (FrameListener.onFrame, hilo NATS) se publican en un StateFlow
  thread-safe que Compose recolecta en el hilo principal.
- Chat: crear/unir room (toggle cifrado), enviar, recibir.
- El .aar es artefacto (gitignored); se regenera con gomobile bind (README).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:43:10 +02:00
..

unibus · app Android

Cliente móvil nativo de unibus. La app no habla con un gateway: embebe un peer real del bus a través del binding gomobile mobile/unibus.go, de modo que el cifrado extremo a extremo corre en el dispositivo. Cada teléfono es un peer de primera clase del bus, igual que cualquier peer Go.

Arquitectura

Kotlin/Compose UI  ──>  BusViewModel  ──>  com.unibus.core.mobile.Session (.aar)
                                              │  (NATS data plane + E2E crypto, en Go)
                                              ▼
                                      membershipd (control plane HTTP :8470)
                                      NATS (data plane :4250)
  • BusViewModel traduce intents de UI en llamadas al binding. Las llamadas de red (newSession, createRoom, join, publish) corren en Dispatchers.IO.
  • Los frames entrantes llegan por FrameListener.onFrame en una goroutine NATS (hilo JNI); se publican en un StateFlow (thread-safe) que Compose recolecta en el hilo principal.

Requisitos

  • Android SDK (compileSdk 34), NDK (para regenerar el .aar), JDK 17.
  • El binding app/libs/unibus.aar (no versionado: es un artefacto de ~24 MB).

1. Generar el binding (.aar)

Desde la raíz del repo de la app (projects/message_bus/apps/unibus):

export ANDROID_HOME=$HOME/android-sdk
export ANDROID_NDK_HOME=$HOME/android-sdk/ndk/26.3.11579264
mkdir -p android/app/libs
gomobile bind -target=android -androidapi 21 -javapkg com.unibus.core \
  -o android/app/libs/unibus.aar ./mobile

Esto produce unibus.aar con la clase estática com.unibus.core.mobile.Mobile (generateIdentity, newSession) y los tipos Session y FrameListener.

2. Compilar el APK

cd android
export JAVA_HOME=$HOME/android-sdk/jdk-17/jdk-17.0.19+10
export ANDROID_HOME=$HOME/android-sdk
./gradlew assembleDebug
# APK: app/build/outputs/apk/debug/app-debug.apk

local.properties apunta a sdk.dir; ajústalo si tu SDK está en otra ruta.

3. Arrancar el bus y probar en el emulador

# 1. En el PC: control plane + NATS embebido (HTTP :8470, NATS :4250)
cd projects/message_bus/apps/unibus && go run ./cmd/membershipd

# 2. Emulador Pixel_API34
$ANDROID_HOME/emulator/emulator -avd Pixel_API34 &

# 3. Instalar + lanzar
adb install -r app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n com.unibus.app/.MainActivity

En la pantalla de conexión, desde el emulador el host del PC es 10.0.2.2:

  • Host (control plane): http://10.0.2.2:8470
  • NATS (data plane): nats://10.0.2.2:4250

Para un teléfono físico en la misma LAN, usa la IP LAN del PC en lugar de 10.0.2.2.

Notas

  • La identidad del peer se guarda en filesDir/peer.id (claves privadas Ed25519 + X25519). No se sincroniza ni se respalda.
  • Una room creada en modo "cifrar (E2E)" usa la política Matrix (cifrada, persistida, firmada); en modo normal usa NATS cleartext.