pediatric-ai-scribe-v3/docs/mobile-build.md
Daniel 8ae47feeff build: drop the Android APK workflows; CI is the Docker image and the web app
Requested: no more Android building, focus on the Docker app build and
the web app.

android-apk.yml also ran on every push to every branch, so every commit
started an APK build beside the one workflow anyone was watching. Worse,
its runner — ped-ai-android-runner — advertises the same forgejo-local
label as the general runner, so it was also picking up the Docker build
job and dying instantly with "'runs-on' key not defined". That is why
docker-build showed a failure next to a success on the same commit.

Removed: .forgejo/workflows/android-apk.yml, and the two GitHub APK
workflows, which never ran at all — there is no GitHub remote on this
repo, only forgejo.

The Capacitor project under mobile/ is untouched and still builds by
hand; docs/mobile-build.md now says plainly that nothing builds it for
you.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-12 22:24:17 +02:00

5.4 KiB

Mobile Build And Release

The CI build has been removed. .forgejo/workflows/android-apk.yml and the two GitHub APK workflows are gone: CI now covers the Docker image and the web app only. The Capacitor project under mobile/ is still here and still builds by hand with the Gradle commands below — nothing builds it for you.

Capacitor 6 wrapper around the hosted Ped-AI web app. The launcher defaults to https://app.pedshub.com, lets the user change the server URL, and stores that URL locally. Android is buildable on Linux. The iOS project exists but requires macOS and Xcode to produce an .ipa.

This is not a separate native clinical app. The native shell provides WebView hosting, microphone permission plumbing, secure storage, and mobile packaging for the same authenticated web app.

One-time setup

Keystore

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)

export CAPACITOR_ANDROID_STUDIO_PATH="/snap/android-studio/current/bin/studio.sh"
npx cap open android

Required repo secrets (set once, via Settings → Secrets and variables → Actions or gh secret set):

  • ANDROID_KEYSTORE_BASE64base64 -w0 ~/pedscribe-release.jks
  • ANDROID_KEYSTORE_PASSWORD
  • ANDROID_KEY_ALIASpedscribe
  • ANDROID_KEY_PASSWORD
  • GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_B64 — base64 of your Google Play service account JSON (optional). If present, the same tag build also runs bundleRelease and uploads the AAB to Play's internal track.

Optional Play Store flow:

  • Service account must have permissions to edit releases on the app in Play.
  • Build task is bundleRelease, tracked as com.pedshub.scribe.
  • Upload lane is fastlane/android publish_internal (under mobile/android/fastlane).

Tag a release:

# 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 X.Y.Z --push

APK lands on the Forgejo release. Obtainium can still track git.danvics.com/danvics/pediatric-ai-scribe-v3 releases automatically. Play Store upload is handled automatically for tagged builds only when GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_B64 is configured.

Local build (fallback / debugging)

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='<pass>' \
  -Pandroid.injected.signing.key.alias=pedscribe \
  -Pandroid.injected.signing.key.password='<pass>'

Output: android/app/build/outputs/apk/release/app-release.apk For Play Store, swap assembleReleasebundleRelease; output: .aab under bundle/release/.

If web assets or Capacitor config changed, run npx cap sync android from mobile/ before building.

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

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 and server URL entry, defaulting to https://app.pedshub.com
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
mobile/android/fastlane/Fastfile internal Play track upload lane