| ## OpenClaw Android App |
|
|
| Status: **extremely alpha**. The app is actively being rebuilt from the ground up. |
|
|
| ### Rebuild Checklist |
|
|
| - [x] New 4-step onboarding flow |
| - [x] Connect tab with `Setup Code` + `Manual` modes |
| - [x] Encrypted persistence for gateway setup/auth state |
| - [x] Chat UI restyled |
| - [x] Settings UI restyled and de-duplicated (gateway controls moved to Connect) |
| - [x] QR code scanning in onboarding |
| - [x] Performance improvements |
| - [x] Streaming support in chat UI |
| - [x] Request camera/location and other permissions in onboarding/settings flow |
| - [x] Push notifications for gateway/chat status updates |
| - [x] Security hardening (biometric lock, token handling, safer defaults) |
| - [x] Voice tab full functionality |
| - [x] Screen tab full functionality |
| - [ ] Full end-to-end QA and release hardening |
|
|
| ## Open in Android Studio |
|
|
| - Open the folder `apps/android`. |
|
|
| ## Build / Run |
|
|
| ```bash |
| cd apps/android |
| ./gradlew :app:assembleDebug |
| ./gradlew :app:installDebug |
| ./gradlew :app:testDebugUnitTest |
| ``` |
|
|
| ## Kotlin Lint + Format |
|
|
| ```bash |
| pnpm android:lint |
| pnpm android:format |
| ``` |
|
|
| Android framework/resource lint (separate pass): |
|
|
| ```bash |
| pnpm android:lint:android |
| ``` |
|
|
| Direct Gradle tasks: |
|
|
| ```bash |
| cd apps/android |
| ./gradlew :app:ktlintCheck :benchmark:ktlintCheck |
| ./gradlew :app:ktlintFormat :benchmark:ktlintFormat |
| ./gradlew :app:lintDebug |
| ``` |
|
|
| `gradlew` auto-detects the Android SDK at `~/Library/Android/sdk` (macOS default) if `ANDROID_SDK_ROOT` / `ANDROID_HOME` are unset. |
|
|
| ## Macrobenchmark (Startup + Frame Timing) |
|
|
| ```bash |
| cd apps/android |
| ./gradlew :benchmark:connectedDebugAndroidTest |
| ``` |
|
|
| Reports are written under: |
|
|
| - `apps/android/benchmark/build/reports/androidTests/connected/` |
|
|
| ## Perf CLI (low-noise) |
|
|
| Deterministic startup measurement + hotspot extraction with compact CLI output: |
|
|
| ```bash |
| cd apps/android |
| ./scripts/perf-startup-benchmark.sh |
| ./scripts/perf-startup-hotspots.sh |
| ``` |
|
|
| Benchmark script behavior: |
|
|
| - Runs only `StartupMacrobenchmark#coldStartup` (10 iterations). |
| - Prints median/min/max/COV in one line. |
| - Writes timestamped snapshot JSON to `apps/android/benchmark/results/`. |
| - Auto-compares with previous local snapshot (or pass explicit baseline: `--baseline <old-benchmarkData.json>`). |
|
|
| Hotspot script behavior: |
|
|
| - Ensures debug app installed, captures startup `simpleperf` data for `.MainActivity`. |
| - Prints top DSOs, top symbols, and key app-path clues (Compose/MainActivity/WebView). |
| - Writes raw `perf.data` path for deeper follow-up if needed. |
|
|
| ## Run on a Real Android Phone (USB) |
|
|
| 1) On phone, enable **Developer options** + **USB debugging**. |
| 2) Connect by USB and accept the debugging trust prompt on phone. |
| 3) Verify ADB can see the device: |
|
|
| ```bash |
| adb devices -l |
| ``` |
|
|
| 4) Install + launch debug build: |
|
|
| ```bash |
| pnpm android:install |
| pnpm android:run |
| ``` |
|
|
| If `adb devices -l` shows `unauthorized`, re-plug and accept the trust prompt again. |
|
|
| ### USB-only gateway testing (no LAN dependency) |
|
|
| Use `adb reverse` so Android `localhost:18789` tunnels to your laptop `localhost:18789`. |
|
|
| Terminal A (gateway): |
|
|
| ```bash |
| pnpm openclaw gateway --port 18789 --verbose |
| ``` |
|
|
| Terminal B (USB tunnel): |
|
|
| ```bash |
| adb reverse tcp:18789 tcp:18789 |
| ``` |
|
|
| Then in app **Connect → Manual**: |
|
|
| - Host: `127.0.0.1` |
| - Port: `18789` |
| - TLS: off |
|
|
| ## Hot Reload / Fast Iteration |
|
|
| This app is native Kotlin + Jetpack Compose. |
|
|
| - For Compose UI edits: use Android Studio **Live Edit** on a debug build (works on physical devices; project `minSdk=31` already meets API requirement). |
| - For many non-structural code/resource changes: use Android Studio **Apply Changes**. |
| - For structural/native/manifest/Gradle changes: do full reinstall (`pnpm android:run`). |
| - Canvas web content already supports live reload when loaded from Gateway `__openclaw__/canvas/` (see `docs/platforms/android.md`). |
|
|
| ## Connect / Pair |
|
|
| 1) Start the gateway (on your main machine): |
|
|
| ```bash |
| pnpm openclaw gateway --port 18789 --verbose |
| ``` |
|
|
| 2) In the Android app: |
|
|
| - Open the **Connect** tab. |
| - Use **Setup Code** or **Manual** mode to connect. |
|
|
| 3) Approve pairing (on the gateway machine): |
|
|
| ```bash |
| openclaw devices list |
| openclaw devices approve <requestId> |
| ``` |
|
|
| More details: `docs/platforms/android.md`. |
|
|
| ## Permissions |
|
|
| - Discovery: |
| - Android 13+ (`API 33+`): `NEARBY_WIFI_DEVICES` |
| - Android 12 and below: `ACCESS_FINE_LOCATION` (required for NSD scanning) |
| - Foreground service notification (Android 13+): `POST_NOTIFICATIONS` |
| - Camera: |
| - `CAMERA` for `camera.snap` and `camera.clip` |
| - `RECORD_AUDIO` for `camera.clip` when `includeAudio=true` |
|
|
| ## Integration Capability Test (Preconditioned) |
|
|
| This suite assumes setup is already done manually. It does **not** install/run/pair automatically. |
|
|
| Pre-req checklist: |
|
|
| 1) Gateway is running and reachable from the Android app. |
| 2) Android app is connected to that gateway and `openclaw nodes status` shows it as paired + connected. |
| 3) App stays unlocked and in foreground for the whole run. |
| 4) Open the app **Screen** tab and keep it active during the run (canvas/A2UI commands require the canvas WebView attached there). |
| 5) Grant runtime permissions for capabilities you expect to pass (camera/mic/location/notification listener/location, etc.). |
| 6) No interactive system dialogs should be pending before test start. |
| 7) Canvas host is enabled and reachable from the device (do not run gateway with `OPENCLAW_SKIP_CANVAS_HOST=1`; startup logs should include `canvas host mounted at .../__openclaw__/`). |
| 8) Local operator test client pairing is approved. If first run fails with `pairing required`, approve latest pending device pairing request, then rerun: |
| 9) For A2UI checks, keep the app on **Screen** tab; the node now auto-refreshes canvas capability once on first A2UI reachability failure (TTL-safe retry). |
|
|
| ```bash |
| openclaw devices list |
| openclaw devices approve --latest |
| ``` |
|
|
| Run: |
|
|
| ```bash |
| pnpm android:test:integration |
| ``` |
|
|
| Optional overrides: |
|
|
| - `OPENCLAW_ANDROID_GATEWAY_URL=ws://...` (default: from your local OpenClaw config) |
| - `OPENCLAW_ANDROID_GATEWAY_TOKEN=...` |
| - `OPENCLAW_ANDROID_GATEWAY_PASSWORD=...` |
| - `OPENCLAW_ANDROID_NODE_ID=...` or `OPENCLAW_ANDROID_NODE_NAME=...` |
|
|
| What it does: |
|
|
| - Reads `node.describe` command list from the selected Android node. |
| - Invokes advertised non-interactive commands. |
| - Skips `screen.record` in this suite (Android requires interactive per-invocation screen-capture consent). |
| - Asserts command contracts (success or expected deterministic error for safe-invalid calls like `sms.send` and `notifications.actions`). |
|
|
| Common failure quick-fixes: |
|
|
| - `pairing required` before tests start: |
| - approve pending device pairing (`openclaw devices approve --latest`) and rerun. |
| - `A2UI host not reachable` / `A2UI_HOST_NOT_CONFIGURED`: |
| - ensure gateway canvas host is running and reachable, keep the app on the **Screen** tab. The app will auto-refresh canvas capability once; if it still fails, reconnect app and rerun. |
| - `NODE_BACKGROUND_UNAVAILABLE: canvas unavailable`: |
| - app is not effectively ready for canvas commands; keep app foregrounded and **Screen** tab active. |
|
|
| ## Contributions |
|
|
| This Android app is currently being rebuilt. |
| Maintainer: @obviyus. For issues/questions/contributions, please open an issue or reach out on Discord. |
|
|