# Running the Android client locally The Android app is the same Vue frontend and Rust core as the desktop, built by Tauri v2 mobile. This sheet is the local setup; CI's copy of it is the `ci-tauri-android` image (see `ci-requirements.md`). **Open this directory in Android Studio:** ``` desktop/src-tauri/gen/android ``` Two things must be true first, and both fail confusingly if they aren't. ## 1. Gradle must run on JDK 17 Android Studio defaults to its own bundled JDK, which is currently 25. That produces: > Incompatible Gradle JVM version — The project's Gradle version 8.14.3 is > incompatible with the Gradle JVM version 25 currently selected to run Gradle > build. Fix: `Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JDK` → **17**. If none is listed, `Download JDK…` → version 17, vendor Eclipse Temurin. Prefer 17 explicitly over Android Studio's "apply a compatible JDK" quick-fix, which will likely pick 21. 17 is what `ci-tauri-android` pins, and matching it means a local build and a CI build resolve identically. **Why 8.14.3 and not Gradle 9:** `cargo tauri android init` generated the wrapper pin, and Gradle 9 removed `project.exec`, which the generated `buildSrc/.../BuildTask.kt` still uses. The wrapper, the AGP pin and that file are all tracked in this repo, so the bump is ours to make whenever it is worth doing — it is scaffolding we inherited, not a requirement of Tauri. Tauri's own Android layer targets `compileSdk 36` and registers back handling through `OnBackPressedDispatcher`, so the library is current; only the template trails. ## 2. The Gradle glue has to be generated once `settings.gradle` does `apply from: 'tauri.settings.gradle'`, and that file — with `app/tauri.build.gradle.kts`, `app/tauri.properties`, `app/src/main/assets/tauri.conf.json` and the compiled `.so` files — is generated per build and gitignored. A fresh clone does not have them, and settings evaluation happens before any Gradle task, so the sync fails before anything can generate them. From `desktop/src-tauri`: ```sh cargo tauri android build --debug --target x86_64 ``` After that, Android Studio syncs cleanly. ## Prerequisites Gradle shells out to `cargo tauri android android-studio-script` on every build, so the Rust toolchain is required on the machine running Android Studio — the CI image cannot stand in for it. ```sh rustup toolchain install 1.97.1 rustup target add aarch64-linux-android x86_64-linux-android cargo install tauri-cli --version 2.11.4 --locked ``` Via the SDK Manager, matching `CI-tauri-android/versions.env`: | | version | why it matters | |---|---|---| | Platform | API 36 | `compileSdk` / `targetSdk` | | Build-Tools | 35.0.0 | AGP 8.11's default | | **NDK** | 28.2.13676358 | the Rust core cannot cross-compile without it | | Platform-Tools | latest | `adb` | ```sh export ANDROID_HOME=$HOME/Android/Sdk export NDK_HOME=$ANDROID_HOME/ndk/28.2.13676358 ``` Node is needed too — `beforeBuildCommand` runs `npm ci && npm run build`, because `generate_context!` compiles the frontend into the binary. ## Emulator Create an AVD with an **x86_64** system image, API 24 or newer (`minSdk = 24`). CI builds arm64-v8a and x86_64, so either runs, but x86_64 executes natively on a desktop instead of being translated. ## The dev loop Android Studio's Run button rebuilds the whole Rust core each time. For iteration, with an emulator already running: ```sh cd desktop/src-tauri cargo tauri android dev ``` That starts Vite, wires `adb reverse` so the emulator reaches `localhost:5173`, and hot-reloads frontend changes without a rebuild. Android Studio earns its keep for the debugger, logcat and layout inspection. ## Known gaps, so they are not mistaken for bugs - **Safe areas / viewport** are not handled yet (task 2706) — content may sit under a notch or the gesture bar. Deliberately left until a device could verify it. - **`android:enableOnBackInvokedCallback`** is absent from the manifest, so predictive-back animations will not engage on Android 13+. Tauri registers the dispatcher correctly; only the opt-in flag is missing. - **`android:usesCleartextTraffic`** is templated in app-wide. A `networkSecurityConfig` resource is the better shape — see Scribe note 2437, which hit this on Minstrel. - Debug builds are large and slow to start. Do not read either as the product.