# Mobile build & release Capacitor 6 wrapper. Android only today; iOS project exists but requires macOS + Xcode to produce an `.ipa`. ## One-time setup ### Keystore ```bash keytool -genkeypair -v -keystore ~/pedscribe-release.jks \ -keyalg RSA -keysize 2048 -validity 10000 -alias pedscribe ``` Store the password in a password manager. Back up the `.jks` file off the machine. Losing it = can't sign updates; Play Store requires signature continuity (unless you're on Play App Signing). ### Android Studio (optional, IDE workflow only) ```bash export CAPACITOR_ANDROID_STUDIO_PATH="/snap/android-studio/current/bin/studio.sh" npx cap open android ``` ## CI build (preferred) Tag-triggered. Push any `vX.Y.Z` tag → `.github/workflows/android-release.yml` builds a signed APK on a GitHub runner and attaches it to the matching release. Required repo secrets (set once, via Settings → Secrets and variables → Actions or `gh secret set`): - `ANDROID_KEYSTORE_BASE64` — `base64 -w0 ~/pedscribe-release.jks` - `ANDROID_KEYSTORE_PASSWORD` - `ANDROID_KEY_ALIAS` — `pedscribe` - `ANDROID_KEY_PASSWORD` Tag a release: ```bash # conventional-commits prefix auto-tags (see CONTRIBUTING.md) git commit -m "feat: ..." && git push # auto-version workflow bumps minor git commit -m "fix: ..." && git push # auto-version workflow bumps patch # or force an exact version scripts/release.sh 6.2.0 --push ``` APK lands at the GitHub release; `/releases/latest` link in the login page resolves to it automatically. Obtanium subscribers (`github.com//`) pick up the update on next poll. ## Local build (fallback / debugging) ```bash cd mobile npm install npx cap sync android cd android ./gradlew assembleRelease \ -Pandroid.injected.signing.store.file=$HOME/pedscribe-release.jks \ -Pandroid.injected.signing.store.password='' \ -Pandroid.injected.signing.key.alias=pedscribe \ -Pandroid.injected.signing.key.password='' ``` Output: `android/app/build/outputs/apk/release/app-release.apk` For Play Store, swap `assembleRelease` → `bundleRelease`; output: `.aab` under `bundle/release/`. ### Single-quote the password Keystore passwords with shell metacharacters (`)`, `$`, `!`, space, etc.) must be single-quoted. Backslash line continuations get eaten by some terminal paste handlers — prefer one-line commands. ## Reinstall on device ```bash adb install -r android/app/build/outputs/apk/release/app-release.apk ``` `-r` keeps app data (saved server URL, auth token in Keystore, IndexedDB). ## Gotchas - **JDK 17 only.** Newer JDK (21/25) breaks Android Gradle Plugin. Set `org.gradle.java.home=/usr/lib/jvm/java-17-openjdk-amd64` in `~/.gradle/gradle.properties` if the system default is different. - **QEMU multi-arch Docker builds fail** with SIGILL on native modules (argon2). Docker Hub workflow is x86-only. Use a native ARM runner if you need ARM64. - **`npx cap` must run inside `mobile/`**, not repo root. - **Foreground recording on Android 14+** requires `foregroundServiceType="microphone"` in `AndroidManifest.xml` plus the 3-arg `startForeground(id, notif, TYPE_MICROPHONE)`. Already applied. - **Mic "denied" after permission grant** — WebView intercepts the prompt. Fix: long-press app icon → App info → Permissions → Microphone → Allow. ## Files Note on `com.pedshub.scribe`: that's the Android applicationId — the OS-level unique identifier for this app. Chosen by reverse-DNS of `pedshub.com`. It is **not** a reference to the separate PedsHub Quiz app; they share a prefix by coincidence. Don't rename it — Android treats applicationId as the primary key; renaming breaks Play Store update continuity and forces every installed user to uninstall + reinstall. | Path | Purpose | |---|---| | `mobile/capacitor.config.json` | appId, name, WebView config, plugin opts | | `mobile/src/` | launcher HTML (server URL entry) | | `mobile/android/app/src/main/java/com/pedshub/scribe/MainActivity.java` | JS bridge + WebView mic permission | | `mobile/android/app/src/main/java/com/pedshub/scribe/AudioRecordingService.java` | foreground service for background recording | | `mobile/android/app/src/main/AndroidManifest.xml` | permissions, intents, backup rules | | `.github/workflows/android-release.yml` | CI build |