No description
- Kotlin 77.1%
- Shell 19.9%
- PowerShell 2.2%
- AIDL 0.7%
- Batchfile 0.1%
| app | ||
| dist/kipanga-field-kit | ||
| docs | ||
| gradle/wrapper | ||
| launcher | ||
| protocol | ||
| tools | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| README.md | ||
| settings.gradle.kts | ||
Kipanga Player (Android)
Stack di digital signage Android per totem unattended. Due APK co-firmate:
cloud.kipanga.player— renderizza la playlist del cliente (template HTML + JS sopra una WebView, ExoPlayer nativo per i video spot-creator), pollanode.kipanga.cloudper la config, scarica gli asset gallery, manda heartbeat.cloud.kipanga.launcher— Device Owner. Fa da HOME di sistema, detiene le policy kiosk (Lock Task whitelist, status bar / keyguard disabled, stay-on-while-plugged-in), gira un watchdog che si appaia via AIDL col player e lo force-restart se hung, fa silent OTA install della APK player, e ospita lo stack di accesso remoto (Dropbear SSH, reverse tunnel, screenshot).
Entrambe le APK sono stabili, kiosk-locked, validate end-to-end su ProDVX RK3288 / Android 9 (dev bed). Target produzione: Android 11+ / API 30+.
Documentazione
| Documento | Per chi | Cosa contiene |
|---|---|---|
docs/dev/ONBOARDING.md |
sviluppatori | ambiente, struttura moduli, build, test, convenzioni |
docs/dev/ARCHITECTURE.md |
sviluppatori | forma a runtime, contratto AIDL, schema state.json, failure mode |
docs/dev/COMPATIBILITY.md |
sviluppatori | matrice di compatibilità launcher↔player↔AIDL proto |
docs/ops/INSTALLAZIONE.md |
tecnici onsite | provisioning presso il cliente — percorso cavo USB / WiFi |
docs/ops/ACCESSO_REMOTO.md |
supporto | SSH, reverse tunnel, screenshot |
docs/ops/TROUBLESHOOTING.md |
supporto / tecnici | diagnosi e recupero device, factory reset |
docs/team-server/ |
team server Kipanga | API OTA / provisioning, problemi di data-quality |
Stato
| Area | Stato |
|---|---|
| Robustezza player (state.json, tolerant config parser, WebView watchdog, log rotator, SC retry+refresh, restart-on-do-refresh) | ✅ done |
Launcher + modulo AIDL :protocol + watchdog |
✅ done |
| Device Owner + Lock Task + kiosk UI policies | ✅ done |
Tooling provisioning (provision.sh, setup_device_owner.sh, field-setup, QR template) |
✅ done |
| OTA: silent player install via AIDL launcher | ✅ done client-side — endpoint server pendenti, vedi docs/team-server/API_OTA_PROVISIONING.md |
| SSH server locale (Dropbear cross-compilato, patch Android-compat) | ✅ done |
Reverse SSH tunnel outbound device→pop.pointonpeople.com |
✅ done — validato end-to-end |
Screenshot remoto via MediaProjection + endpoint HTTP |
✅ done (consent auto-tappato, zero operator interaction) |
authorized_keys fleet-wide sync (ETag, atomic write) |
✅ done |
| Controllo remoto interattivo — stream MJPEG + iniezione tap/swipe via HTTP | ✅ done client-side — da testare su HW reale |
Stack tecnologico
| Layer | Scelta |
|---|---|
| Linguaggio | Kotlin 2.2.21 |
| Build | Gradle 9.4.1 (wrapper) + AGP 9.2.0 |
| JVM toolchain | 21 |
| Min / target SDK | 28 / 34 |
| HTTP (player) | OkHttp 4.12 |
| HTTP (launcher) | java.net.HttpURLConnection (solo stdlib — dex piccola) |
| JSON | Gson 2.10.1 + TolerantConfigParser custom |
| Async | Kotlinx Coroutines 1.7.3 |
| WebView | WebView di sistema (Chromium, warm-up al boot) |
| Video nativo | androidx.media3 / ExoPlayer 1.3.1 |
| IPC | AIDL — ILauncherWatchdog nel modulo :protocol |
| Test | JUnit 4 + kotlin-test, unit JVM (:app:testDebugUnitTest) |
Layout repo
KipangaPlayer/
├── app/ :app — cloud.kipanga.player
├── launcher/ :launcher — cloud.kipanga.launcher (Device Owner)
│ └── src/main/jniLibs/<abi>/libdropbear.so — SSH server cross-compiled (committato)
├── protocol/ :protocol — Android library, solo contratto AIDL
├── tools/
│ ├── provision.sh — install soft-kiosk (dev)
│ ├── setup_device_owner.sh — promuove launcher a Device Owner
│ ├── kipanga-field-setup.sh — provisioning multi-device onsite
│ ├── enable-wireless-adb.sh — helper USB → tcp:5555
│ ├── install_tunnel_key.sh — converte + installa la chiave del reverse tunnel
│ ├── qr_provisioning_template.json — template QR factory-reset
│ └── build-dropbear.sh — cross-compile del server SSH
├── docs/ — vedi sezione Documentazione sopra
└── README.md
Build rapida
# Debug, entrambe le APK
./gradlew :app:assembleDebug :launcher:assembleDebug
# Unit test del player
./gradlew :app:testDebugUnitTest
# Install soft-kiosk su device (dev)
tools/provision.sh
Setup completo, struttura dei moduli e convenzioni →
docs/dev/ONBOARDING.md.
Pipeline a runtime (in breve)
Boot → MainActivity launcher → DO policies applied → player lanciato → config
pollata da node.kipanga.cloud → registration se status_code ∈ {0,5} →
gallery sync → page render → metronome rotation. Watchdog AIDL ogni 10 s; se
silenzio > 30 s il launcher force-restart il player. Flag dal server:
do_refresh=1 (restart pulito), do_upgrade=1 (re-fetch template firmware),
do_apk_upgrade=1 (silent self-update).
Quadro completo → docs/dev/ARCHITECTURE.md.