- Kotlin 98.7%
- Just 1.3%
|
All checks were successful
Release / build (push) Successful in 2m45s
Co-authored-by: PatillaCode <patillacode@gmail.com> Co-committed-by: PatillaCode <patillacode@gmail.com> |
||
|---|---|---|
| .forgejo/workflows | ||
| .idea/codeStyles | ||
| app | ||
| docs | ||
| engine | ||
| gradle | ||
| .gitignore | ||
| build.gradle.kts | ||
| CLAUDE.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| justfile | ||
| README.md | ||
| settings.gradle.kts | ||
scoundrel-android
Native Android port of Scoundrel (Kotlin + Jetpack Compose). Same rules and art, reimagined for touch: drag a monster left to fight bare-handed, right to strike with your weapon, watch the damage preview live under your thumb.
Self-hosted distribution only — no Play Store, no Google Play Services.
Status
Feature-complete: engine, gestures/haptics, collections/themes, i18n (en/es), stats, sound effects, launcher icon, and signed CI releases. Daily challenge is deliberately deferred. See the implementation plan for phase-by-phase detail.
Commands
just test # ./gradlew :engine:test — pure Kotlin/JVM, no Android SDK needed
just check # test + lint
just dev # install debug build on a connected device
just sync-art # copy PNGs from ../scoundrel/src/collections (sibling checkout required)
just build # assemble debug APK
just release X.Y.Z
Structure
engine/— pure Kotlin/JVM game rules (Deck.kt,Rng.kt,Engine.kt), zero Android imports.EngineTest.ktis a direct port of the web repo'sengine.test.ts, plus seed-determinism tests (newGame(seed)makes a run reproducible;avoidRoomreshuffles using the sameRngcarried inGameState, not a global).app/— Jetpack Compose UI. Single Activity, oneGameViewModel, no DI, no navigation library.
Requirements
Android Studio (Otter 3 Feature Drop or later — AGP 9's built-in Kotlin support needs
it), SDK Platform 37 (compileSdk; Compose 1.12 requires it — targetSdk stays 36,
see app/build.gradle.kts), an x86_64 emulator image or a physical device. See the
implementation plan for full environment setup.
Releasing
Distribution is a signed APK attached to a Forgejo release — no Play Store, no Google Play Services.
just release 0.1.0 # tags v0.1.0 and pushes; release.yml does the rest
That push triggers .forgejo/workflows/release.yml, which runs the tests, builds a
signed app-release.apk, and attaches it to a new Forgejo release under the repo's
Releases tab. Download the APK from there and share that link with anyone.
Signing. Every release build must be cryptographically signed with the same key,
so Android can prove all updates to the app came from the same publisher. The
signing key lives in ~/.android-keystores/scoundrel.jks — outside the repo,
gitignored, and not recoverable if lost: back it up somewhere durable, since
losing it means the app can never be upgraded in place again (a "new" version would
be a different app to Android). CI is handed the same key through 5 repo secrets
(Settings → Actions → Secrets):
| Secret | What it is |
|---|---|
RELEASE_KEYSTORE_B64 |
the keystore file itself, base64-encoded (base64 -i ~/.android-keystores/scoundrel.jks) |
RELEASE_STORE_PASSWORD |
password to open the keystore file |
RELEASE_KEY_PASSWORD |
password for the signing key inside it (same value — PKCS12 keystores don't support separate ones) |
RELEASE_KEY_ALIAS |
the key's name inside the keystore (scoundrel) |
FORGEJO_TOKEN |
a Forgejo access token (repo write scope) so CI can create the release and upload the APK via the API |
Before every new release, bump versionCode (+1) and versionName in
app/build.gradle.kts — Android uses versionCode to decide whether an installed
APK counts as an upgrade.
Installing (sideloading)
There's no app store step. On the phone:
- Download the
.apkfrom the release's Releases page. - Tap it. Android will ask to allow installs from that source (browser/file manager) the first time — allow it once.
- It installs like any other app.
This is the same mechanism F-Droid and most non-Play-Store apps use.
Obtainium setup
For automatic update checks instead of downloading each release by hand, add this repo to Obtainium. Tap the button below from your phone:
That opens Obtainium's Add App screen with the URL pre-filled, but self-hosted Forgejo
instances aren't auto-detected (only codeberg.org is) — you still need to manually
set Override Source to Forgejo (Codeberg) before confirming, or it fails with
"could not find a suitable release". This applies whether you got here via the button
or typed the URL in yourself: https://forgejo.patilla.es/patillacode/scoundrel-android.
Once added, Obtainium polls the Releases page and prompts you to install when a new version is published.