3.8 KiB
Encore
A minimal, modern Android app: Kotlin + Jetpack Compose (Material 3), built and tested with Nix.
Jetpack Compose is the modern Android UI framework — declarative Kotlin UI that has replaced the old XML layouts. Material 3 is Google's current design system, wired up here with dynamic (wallpaper-based) color on Android 12+.
Layout
flake.nix Nix entrypoint: dev shells, SDK, package, emulator
package.nix Reproducible APK build (nixpkgs-style derivation)
deps.json Lockfile of Gradle/Maven deps (generated — see below)
settings.gradle.kts Gradle project + repositories
build.gradle.kts Root build script (declares plugin versions)
gradle/libs.versions.toml Version catalog: all dependency/plugin versions
app/
build.gradle.kts The :app module (Android + Compose config)
src/main/
AndroidManifest.xml App/activity declaration
kotlin/ca/ksamad/encore/
MainActivity.kt Entry activity; sets the Compose content
Theme.kt Material 3 theme (dynamic color)
res/values/ strings.xml, themes.xml
src/test/kotlin/... A plain JVM unit test
Everyday Development (Recommended)
Use the dev shell — it puts a JDK, Gradle, and the Android SDK on your PATH with the right environment variables set:
nix develop
gradle assembleDebug # build the debug APK -> app/build/outputs/apk/debug/
gradle testDebugUnitTest # run unit tests
gradle tasks # see everything available
The debug APK is unsigned but installable on a device/emulator:
adb install app/build/outputs/apk/debug/app-debug.apk
Android Studio
For the GUI editor, Compose previews, and device manager:
nix develop .#studio
android-studio
Open this folder as an existing project. (Android Studio manages its own SDK; the command-line flow above is fully independent of it.)
Emulator
nix run .#emulate
Reproducible Build with Nix
nix build # -> ./result/encore.apk
Unlike gradle assembleDebug, this build runs fully offline: every Gradle/Maven
dependency is pinned by hash in deps.json, and Nix supplies the Android SDK. It also
runs the unit tests (testDebugUnitTest) as its check phase, so a green nix build means
both "it assembles" and "tests pass". This is what you'd use in CI for a reproducible
artifact.
Note:
package.nixandapp/build.gradle.ktscontain a few small workarounds, active only during dependency capture (gated on theIN_GRADLE_UPDATE_DEPSenv var), that stop Nix's "resolve every configuration" sweep from tripping over internal AGP/Kotlin configurations. They don't affect the dev shell or the actual build. See the comments inapp/build.gradle.ktsfor the details.
Regenerating deps.json
Any time you change a dependency or plugin version (i.e. edit
gradle/libs.versions.toml or a build.gradle.kts), regenerate the lockfile:
nix build .#default.mitmCache.updateScript
./result # runs the build under a proxy, rewrites ./deps.json
Then commit the updated deps.json. (It works by recording Gradle's dependency
downloads through a man-in-the-middle proxy and storing their hashes — see
package.nix.)
Docs
docs/device-testing.md— build & install onto a real Android device/DAP over USB (and the NixOSadbnotes).docs/TODO.md— near-term roadmap / known bugs.
Version notes
Pinned in gradle/libs.versions.toml: AGP 8.7.3, Kotlin 2.0.21, Compose BOM 2024.10.01,
compiled against compileSdk 35, minSdk 24. Nix supplies Gradle 8.14. If you bump
these, keep AGP/Kotlin/Gradle mutually compatible and regenerate deps.json.