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>
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 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:
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:enableOnBackInvokedCallbackis 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:usesCleartextTrafficis templated in app-wide. AnetworkSecurityConfigresource 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.