{ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; }; outputs = { self, nixpkgs, flake-utils, }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs { inherit system; config = { # The Android SDK components and Android Studio are unfree, and the # SDK requires accepting its license non-interactively. allowUnfree = true; android_sdk.accept_license = true; }; }; buildToolsVersion = "35.0.0"; # A minimal SDK: just the pieces needed to compile & assemble the app. # (No emulator/system-image here — those live in the `emulate` output.) androidComposition = pkgs.androidenv.composeAndroidPackages { platformVersions = [ "35" ]; buildToolsVersions = [ buildToolsVersion ]; includeEmulator = false; includeSystemImages = false; includeNDK = false; }; androidSdk = androidComposition.androidsdk; androidHome = "${androidSdk}/libexec/android-sdk"; # The built app, referenced by both `packages.default` and the emulator. musicRemote = pkgs.callPackage ./package.nix { inherit androidSdk androidHome buildToolsVersion; }; applicationId = "ca.ksamad.musicremote"; in { formatter = pkgs.nixfmt-rfc-style; # `nix build` -> reproducible debug APK in ./result/music-remote.apk packages.default = musicRemote; # `nix develop` -> command-line dev shell (gradle + SDK wired up). devShells.default = pkgs.mkShell { buildInputs = [ pkgs.jdk17 pkgs.gradle androidSdk ]; ANDROID_HOME = androidHome; ANDROID_SDK_ROOT = androidHome; # Same NixOS aapt2 fix as in package.nix, but as a Gradle system prop # so plain `gradle assembleDebug` works inside the shell. GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${androidHome}/build-tools/${buildToolsVersion}/aapt2"; shellHook = '' echo "music-remote dev shell — try: gradle assembleDebug" ''; }; # `nix develop .#studio` -> full Android Studio (GUI + emulator manager). devShells.studio = pkgs.mkShell { buildInputs = [ pkgs.androidStudioPackages.stable ]; }; # `nix run .#emulate` -> boots an emulator, then installs and launches the # app on it. `app` points at the built package directory (the script globs # `*.apk` inside it); `package`/`activity` make it auto-start after boot. packages.emulate = pkgs.androidenv.emulateApp { name = "emulate-MusicRemote"; platformVersion = "35"; abiVersion = "x86_64"; # Bare AOSP image. This app only needs the base Android framework # (TCP/HTTP networking for the MPD client); it uses no Google Play # Services APIs, so `google_apis`/`_playstore` would just be extra # weight. Switch to "google_apis" only if you add a Google SDK. systemImageType = "default"; app = musicRemote; package = applicationId; activity = "${applicationId}.MainActivity"; }; } ); }