vojo/docs/ai/android.md

63 lines
3.1 KiB
Markdown

# 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/<variant>/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 <ip>:<pair-port> <code>`
3. `adb connect <ip>:<connect-port>`
The pair port and the connect port are different — don't mix them up.