A thin native shell around the canonical single-file HTML app. The whole web app lives at the repo root; this directory only contains the Android project (Gradle, Kotlin, Manifest, resources) and bundles the HTML + manifest + service worker + icons into the APK at build time.
- F-Droid listing. F-Droid only builds from a real source repo with a Gradle setup, and it strongly prefers wrapped HTML apps over raw web links. This wrapper produces an APK that F-Droid can build, sign, and push to its repo, with auto-update on every git tag.
- Sideload-friendly APK. Anyone who'd rather have a .apk than open the HTML in their browser can grab the release artefact and install. No Play Store account, no F-Droid client needed.
- Future Play Store via TWA. A separate Bubblewrap project will reuse the published PWA — different artefact, same web codebase.
android/
├── build.gradle.kts ← top-level (plugin pinning only)
├── settings.gradle.kts
├── gradle.properties
├── gradle/wrapper/ ← gradle-wrapper.properties is checked in;
│ gradle-wrapper.jar must be generated once
│ (see "First-time setup" below)
└── app/
├── build.gradle.kts ← module config + bundleWebApp Copy task
├── proguard-rules.pro
└── src/main/
├── AndroidManifest.xml
├── java/io/github/zerotonin/flatgym/MainActivity.kt
├── res/
│ ├── values/ (strings, colors, themes)
│ ├── xml/ (backup, data-extraction, network-security)
│ ├── mipmap-*/ (legacy + adaptive launcher icons)
│ └── mipmap-anydpi-v26/ (adaptive-icon XML)
└── assets/ ← gitignored, populated by `bundleWebApp`
Requires JDK 17+ and Gradle 8.7+ on PATH (any Linux package manager will
do — apt install openjdk-17-jdk gradle on Debian/Ubuntu).
cd android
gradle wrapper --gradle-version 8.7 # one-time, creates gradle-wrapper.jarAfter that, all build commands use ./gradlew — no system Gradle needed.
cd android
./gradlew assembleDebug # debug APK at app/build/outputs/apk/debug/
./gradlew assembleRelease # release APK (debug-signed; F-Droid resigns)The first build downloads Gradle 8.7 + the Android Gradle Plugin + the
Android SDK packages it needs (~500 MB of caches under ~/.gradle/). The
Android SDK itself must already be installed and ANDROID_HOME set; the
easiest path is to install Android Studio once.
bundleWebApp runs automatically before every build and stages the web
assets from the repo root into app/src/main/assets/. If you change
gym-tracker.html and rebuild, the new HTML lands in the APK without any
manual sync.
adb install -r app/build/outputs/apk/debug/app-debug.apkOr on a Syncthing-synced phone, just drop the APK into the synced folder and tap it.
Bundled in the APK:
- The full Flatgym HTML app at
assets/index.html manifest.webmanifest,sw.js,icons/
Loaded over the network at runtime (requires INTERNET permission):
- The lazy-fetched exercise-details JSON from
raw.githubusercontent.com/yuhonas/free-exercise-dbon first?click. - External reference pages — but those are routed to the system browser
via
Intent.ACTION_VIEW, never rendered in-WebView.
A future v0.16.x will inline the exercise dataset and drop the INTERNET
permission entirely. That's what F-Droid's NetworkAccess anti-feature
flag tracks; for v0.15.x we declare it honestly.
The WebView serves the bundled assets through
WebViewAssetLoader.AssetsHandler, which surfaces them at
https://appassets.androidplatform.net/assets/.... Three reasons:
- Real origin —
localStorageis partitioned per-origin; afile://URL would give weaker isolation and trip various WebView quirks. - Service-worker eligibility — SWs require HTTPS or localhost; the asset-loader URL satisfies the WebView's HTTPS check.
- No
file://exposure — the manifest disablesallowFileAccess, so a strayfile:link can't pivot to the device's file system.
versionName and versionCode are pinned in app/build.gradle.kts:
val flatgymVersionName = "0.15.0"
val flatgymVersionCode = 15000 // major*10000 + minor*100 + patchBump these in the same commit as the corresponding package.json and
gym-tracker.html VERSION constant.
- Push a
v0.15.0git tag from the repo root. - Open a PR against f-droid/fdroiddata
with a metadata YAML describing the build. Template lives at
metadata/io.github.zerotonin.flatgym.ymlonce we cut the first submission. - F-Droid's build farm checks out the tag, runs
./gradlew assembleReleaseinandroid/, signs with the F-Droid key, and publishes.