Expose /account-deletion/ without auth (steps, soft-delete retention copy, support path) and document the Play listing URL in Android checklists.
5.2 KiB
Android (Capacitor)
Ship the CRA web build as an Android app via Capacitor.
One codebase: llm-fe/ → web + Android + iOS WebView.
Build & Play deploy steps: android/README.md.
iOS sibling: IOS.md / ios/README.md.
Prerequisites for blockers already merged: JWT-only auth (#22), WebSocket lifecycle (#23), HashRouter (#24).
Prerequisites
- Node.js 20 (matches CI; Capacitor 7.x)
- JDK 17+ (OpenJDK fine)
- Android Studio (Ladybug+) with Android SDK Platform 35, build-tools, and an emulator or device
- Set
ANDROID_HOME(or open the project once in Android Studio solocal.propertiesis generated)
One-time / day-to-day
cd llm-fe
npm ci
npm run build:mobile # loads .env.mobile → CRA build → cap sync android
npm run android:open # opens android/ in Android Studio
Or sync only after an existing build/:
npm run android:sync
Environment
| File | Purpose |
|---|---|
.env.mobile |
Endpoints baked into the mobile bundle (build:mobile) |
.env.production |
Web prod deploys (build / build:prod) |
.env.beta |
Web beta deploys |
Default .env.mobile matches production (chatbackend.aimloperations.com). Point it at beta to flip the shell without touching web deploys. Optional gitignored override: .env.mobile.local.
RevenueCat IAP (#100)
Native billing uses @revenuecat/purchases-capacitor (Capacitor 7 → package 11.x). Web keeps Stripe Checkout / Customer Portal.
Set public SDK keys in .env.mobile (empty placeholders OK until store apps ship):
| Variable | Purpose |
|---|---|
REACT_APP_REVENUECAT_APPLE_API_KEY |
iOS public SDK key |
REACT_APP_REVENUECAT_GOOGLE_API_KEY |
Android public SDK key |
REACT_APP_REVENUECAT_OFFERING_ID |
Optional offering pin (else current) |
After install / key changes: npm run build:mobile (runs cap sync). More detail: MONETIZATION.md.
Versioning
In android/app/build.gradle:
- versionName — user-visible string; keep aligned with
package.jsonversion(currently0.1.0) - versionCode — integer; must increase for every Play Store upload
Bump both before each store release.
Icons / splash
Source art lives in llm-fe/assets/:
icon.png/splash.png/splash-dark.png— Capacitor inputs (Hesychia meander mark)logo-source.png— cropped square masterlogo-mark-transparent.png— circular mark with transparent corners (web / in-app)
In-app UI also imports src/llm-fe/assets/brand/hesychia-mark.png.
Regenerate Android densities after changing source art:
npm run assets:generate
Same command also regenerates iOS Assets.xcassets (see IOS.md).
Signing (upload keystore)
Never commit keystores. Store outside the repo (e.g. host secrets / password manager).
keytool -genkey -v -keystore ~/Documents/secrets/aiml-chat-upload.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias aiml-chat-upload
Create llm-fe/android/keystore.properties (gitignored):
storeFile=/absolute/path/to/aiml-chat-upload.jks
storePassword=...
keyAlias=aiml-chat-upload
keyPassword=...
Release App Bundle:
cd llm-fe/android
./gradlew bundleRelease
# → app/build/outputs/bundle/release/app-release.aab
Debug APK (no signing props needed):
./gradlew assembleDebug
Manual QA checklist
On emulator and physical device:
- Login / logout / password reset flows
- Chat streaming + markdown / code blocks
- Charts (
recharts) - Dark / light theme
- Hardware back: navigates history, exits at root
- Keyboard does not cover compose input; notch/safe-area OK
- Background → resume keeps or reconnects WebSocket
- Airplane mode → restore reconnects
Play Store (internal testing first)
Out of band ops (not automated here):
- Google Play developer account
- Privacy policy URL (product site / legal)
- Account deletion URL (Data safety / Account deletion) → public page:
- Canonical:
https://hesychia.ai/account-deletion/ - Legacy host until DNS cutover:
https://chat.aimloperations.com/account-deletion/ - Capacitor HashRouter:
/#/account-deletion/
- Canonical:
- Data safety form (JWT auth, chat content, analytics if Tianji runs in WebView)
- Screenshots for phone (+ tablet if targeting)
- Upload
.aabto internal testing track before production
In-app delete remains Account → Delete my account (DELETE /api/user/). The public URL
above is for Play reviewers and users who never open the app (#103).