# Android (Capacitor) ## Requirements - Node >= 22 - JDK 17+ (21 used in practice) - Android SDK with platform 36 + build-tools 36.0.0 - SDK location: `/usr/lib/android-sdk`, also set in `android/local.properties` ## Config - [`capacitor.config.ts`](../../capacitor.config.ts) — `appId: chat.vojo.app`, `webDir: dist` - `android/` — generated Android Studio project, `targetSdkVersion 36`, `compileSdkVersion 36`, `minSdkVersion 24` ## Build scripts ```bash npm run build:android:debug # full chain: build → sync → debug APK npm run build:android:release # full chain: build → sync → release APK npm run build:android:aab # full chain: build → sync → release AAB npm run android:sync # sync dist/ → android assets npm run android:apk:debug # gradle debug build only ``` **APK output**: `android/app/build/outputs/apk/debug/app-debug.apk` ## Versioning `versionCode` and `versionName` auto-derived from `package.json` version: ``` versionCode = major * 1_000_000 + minor * 1_000 + patch ``` ## Key architecture decisions - **Bundled build.** `dist/` is copied into the APK — not loaded remotely in a WebView. - **Service Worker stays active.** Critical for authenticated Matrix media (MSC3916 / Matrix spec v1.11+). DO NOT disable. `resolveServiceWorkerRequests` default `true`. - **Edge-to-edge.** `EdgeToEdge.enable()` in `MainActivity.java` + `windowLayoutInDisplayCutoutMode: shortEdges`. - **External links.** Opened via `@capacitor/browser` plugin — see [`src/app/utils/capacitor.ts`](../../src/app/utils/capacitor.ts). - **Safe-area coloring.** `body` background-color is bound to the folds theme variable `var(--oq6d070)` for consistent safe-area coloring. - **Safe-area insets.** Applied on `#root` (not `body`) so the theme background extends behind the system bars. ## VSCode tasks See [`.vscode/tasks.json`](../../.vscode/tasks.json): - `Deploy to vojo.chat` (Ctrl+Shift+D) — web deploy - `Deploy to Android (ADB)` (Ctrl+Shift+A) — build + `adb install` ## Push string resources (generated) Push notification text for Android is generated from `public/locales/{en,ru}.json` (namespace `Push`) by `scripts/gen-push-strings.mjs`. The Gradle build runs this automatically via `GeneratePushStringsTask` registered in `android/app/build.gradle` through AGP `addGeneratedSourceDirectory` — output goes to `build/generated/res/push//values{,-ru}/push_strings.xml`. No manual step needed; `./gradlew assembleDebug` handles it. The task requires `node` in `PATH`. Terminal builds and CI inherit it from the shell. **macOS Android Studio with nvm/fnm:** the GUI app may not see nvm-managed node. Workaround: set `NODE_BIN=/path/to/node` in `android/gradle.properties` (the task reads it via `project.findProperty('NODE_BIN')`) or launch AS from a shell that sources your node manager (`open -a "Android Studio"`). ## ADB wireless workflow 1. On the phone, enable Wireless debugging, tap "Pair device with pairing code" — note IP, port, 6-digit code. 2. `adb pair : ` 3. `adb connect :` The pair port and the connect port are different — don't mix them up.