Files
thoughtsync/docs/android-dev.md
T
bvandeusenandClaude Opus 5 c28f2bc00e docs: how to run the Android client locally (task 1864)
Two things stop a fresh clone from opening in Android Studio, and both fail with
errors that name the wrong culprit — so they are written down rather than
rediscovered.

Android Studio runs Gradle on its bundled JDK 25, which Gradle 8.14.3 rejects
with an "Incompatible Gradle JVM version" message that reads like a project
misconfiguration. And settings.gradle applies tauri.settings.gradle, which is
generated per build and gitignored, so sync fails before anything can create it —
one CLI build fixes that permanently.

Also records why the Gradle pin is what it is, since the question came up and the
answer was not what it first looked like: the wrapper, the AGP pin and the
buildSrc file using the removed project.exec are all TRACKED in this repo. It is
scaffolding tauri android init wrote once, ours to bump when it is worth doing,
not a constraint of the framework. Tauri's own Android layer targets compileSdk
36 and registers back handling through OnBackPressedDispatcher — the library is
current, only the generated template trails.

Known gaps are listed so a tester does not file them as bugs: no safe-area
handling yet (2706), no enableOnBackInvokedCallback so predictive back will not
animate, and the templated app-wide usesCleartextTraffic that Minstrel already
hit as a Play Protect smell.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 22:46:38 -04:00

4.3 KiB

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

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.

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

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.