# Runic Gateway — Android app A native Android client for a Runic Gateway shard's **public site + player self-service**. It is **purely an API client of the website backend** — it never talks to the `link/` sidecar or the game shard directly, and it ships none of the shard/sidecar wiring. It surfaces the same content and player features as the website's browser client, **minus every administrative/management console**. The authoritative design contract is [`docs/android/PLAN.md`](https://gitea.whitlocktech.com/RunicGateway/docs) in the `RunicGateway/docs` repo. The authoritative API reference is the committed OpenAPI spec at `website/server/swagger/swagger-output.json`. ## Status **M0 — repo scaffold.** Gradle + Compose + Hilt skeleton with CI (lint + unit test + debug build). The functional Kotlin pass (M1–M4) and the design pass (M5) follow — see the plan's milestones (§9). ## Stack | Concern | Choice | |---|---| | Language / UI | Kotlin + Jetpack Compose (Material 3) | | Navigation | Navigation-Compose, single-activity | | HTTP | Retrofit + OkHttp, `kotlinx.serialization` | | Async | Coroutines + Flow | | DI | Hilt | | Prefs / base URL | Jetpack DataStore | | Tokens at rest | EncryptedSharedPreferences | | Images | Coil | | Min SDK | Android 10 (API 29) | | Target / compile SDK | 35 | Dependency and plugin versions are pinned in [`gradle/libs.versions.toml`](gradle/libs.versions.toml). ## Build Requires **JDK 17** and the Android SDK (`ANDROID_HOME` / `local.properties`). ```bash ./gradlew assembleDebug # build a debug APK -> app/build/outputs/apk/debug/ ./gradlew test # JVM unit tests ./gradlew lint # Android lint ./gradlew installDebug # install on a connected device/emulator ``` The app self-configures its server URL on first run (PLAN.md §3), so a single build works against any shard's website — there is no compiled-in API host. ## CI `.gitea/workflows/pr-checks.yml` gates PRs into `main` with `./gradlew lint test assembleDebug` on the org's self-hosted runner (JDK 17 + Android SDK). Debug builds are auto-signed, so the gate needs no secrets. **This pipeline is verified green end-to-end on the runner** (M0). A signed **release** APK attached to a Gitea release comes at M6. The workflow carries a few runner-specific accommodations (each explained in comments in the file), because this self-hosted runner differs from a stock GitHub runner: - **JDK 17 is installed via `apt`** (not `actions/setup-java`) — the runner can't resolve `api.adoptium.net`, while the Ubuntu mirrors are reachable. - **SDK packages are installed explicitly** via `sdkmanager`, with `set +o pipefail` so `yes` dying of `SIGPIPE` doesn't fail the step. - **`gradlew` is `chmod +x`'d in the run step** — the runner's checkout does not preserve the git executable bit, so `./gradlew` alone fails with "Permission denied". ## Contributing See [`CONTRIBUTING.md`](CONTRIBUTING.md). **AI-assisted contributions must be disclosed** (org policy): tick the PR box naming the tool and add a `Co-Authored-By` trailer to AI-authored commits. Licensed **GPL-3.0-or-later**.