fix(android): support source-based APK builds

Co-authored-by: Anton Lazarev <22821309+antonok-edm@users.noreply.github.com>
This commit is contained in:
Mohamed Boudra
2026-07-12 11:55:00 +00:00
co-authored by Anton Lazarev
parent c05e337cde
commit 7b7bcc1032
6 changed files with 87 additions and 4 deletions
+25
View File
@@ -13,6 +13,18 @@ EAS profiles: `development`, `production`, and `production-apk` in `packages/app
`development` uses Android `debug`.
## Version codes
`packages/app/app.config.js` derives Android `versionCode` from the package version with:
```text
1_000_000 + major * 1_000_000 + minor * 1_000 + patch
```
Prerelease metadata is ignored, so `0.1.102-beta.1` and `0.1.102` both produce `1001102`. The same value is used as the iOS `buildNumber` because `packages/app/eas.json` uses EAS's local app version source. The `1_000_000` floor keeps the local formula above prior EAS remote counters during the transition. Do not re-enable EAS remote version counters or Android `autoIncrement`; F-Droid and other source-based builders need the native build number to be visible in the repo.
The formula reserves three digits each for minor and patch. If either reaches `1000`, change the formula before cutting that release.
## Local build + install
From repo root:
@@ -38,6 +50,19 @@ npx cross-env APP_VARIANT=production expo run:android --variant=release
rm -rf android
```
## F-Droid / source-only Android builds
F-Droid builds should set `PASEO_FDROID_BUILD=1` when running Expo prebuild:
```bash
cd packages/app
PASEO_FDROID_BUILD=1 APP_VARIANT=production npx expo prebuild --platform android --clean --non-interactive
cd android
./gradlew assembleRelease
```
That env var is intentionally narrow. It enables `expo.autolinking.android.buildFromSource: [".*"]` so Expo modules are built from source instead of linked from precompiled AARs, and it applies `expo-gradle-jvmargs` with `-Xmx4096m` and `-XX:MaxMetaspaceSize=1024m` for the larger source build. Normal local and EAS builds leave those settings off.
### React version lockstep
Keep `react` and `react-dom` pinned to the React version embedded by the current `react-native` release. React Native `0.81.x` embeds `react-native-renderer` `19.1.0`, so `packages/app` must use React `19.1.0`. Bumping React to a newer patch can build successfully but crash at JS startup on Android with `Incompatible React versions`, leaving the app on the native splash screen.
+2
View File
@@ -188,6 +188,8 @@ iOS and Android store builds are not in `.github/workflows`. They are triggered
- **iOS (TestFlight + App Store)** — EAS builds with profile `production`, uploads to TestFlight, and a Fastlane lane submits the build for App Store review.
- **Android APK (GitHub Release asset)** — separate, via `.github/workflows/android-apk-release.yml`. This is the only Android-related workflow that lives in this repo.
EAS uses the local app version source. `packages/app/app.config.js` derives Android `versionCode` and iOS `buildNumber` from the package version as `1_000_000 + major * 1_000_000 + minor * 1_000 + patch`, ignoring prerelease metadata. Rebuilding the same tag produces the same native build number; if a store has already accepted a binary and you need a different binary, cut a new patch instead of relying on EAS remote auto-increment.
There is no `release-mobile.yml` in this repo. Earlier versions of these docs referenced one — that workflow was removed and the EAS GitHub app handles tag triggering directly.
### Watching mobile builds from the terminal