{
  # UsageNote: to run the emulator
  #   nix -L run .#emulate-android-x86_64
  #
  # UsageNote: to run load gradle into $PATH
  #   nix -L develop
  description = "Nix flake to develop for Android";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  # ExplanationNote: an alternative way to install Android tools,
  # not sure if it's better than nixpkgs' machinery at anything.
  # Just here for reference.
  inputs.android-nixpkgs = {
    url = "github:tadfisher/android-nixpkgs";

    # ExplanationNote:
    # The main branch follows the "canary" channel of the Android SDK
    # repository. Use another android-nixpkgs branch to explicitly
    # track an SDK release channel.
    #
    # url = "github:tadfisher/android-nixpkgs/stable";
    # url = "github:tadfisher/android-nixpkgs/beta";
    # url = "github:tadfisher/android-nixpkgs/preview";
    # url = "github:tadfisher/android-nixpkgs/canary";

    # ExplanationNote: replace the "nixpkgs" input for the "android-nixpkgs" flake.
    inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs =
    inputs:
    let
      systems = [
        "x86_64-linux"
        "x86_64-darwin"
        "aarch64-linux"
        "aarch64-darwin"
      ];
    in
    inputs.flake-utils.lib.eachSystem systems (
      system:
      let
        pkgs = import inputs.nixpkgs {
          inherit system;
          config = {
            android_sdk.accept_license = true;
            allowUnfreePredicate =
              pkg:
              builtins.elem (pkgs.lib.getName pkg) [
                # ExplanationNote: android-emulate-app (see below) is unfree by transitivity
                "android-emulate-app"
                "android-sdk-build-tools"
                "android-sdk-cmdline-tools"
                "android-sdk-emulator"
                "android-sdk-ndk"
                "android-sdk-platform-tools"
                "android-sdk-platforms"
                "android-sdk-tools"
                "android-studio-stable"
                "android-sdk-system-image-${androidPlatformVersion}-google_apis-x86_64"
                "android-sdk-system-image-${androidPlatformVersion}-google_apis-arm64-v8a"
                "android-sdk-system-image-${androidPlatformVersion}-google_apis-armeabi-v7a"
              ];
          };
        };
        androidPlatformVersion = "34";
        androidBuildToolsVersion = "34.0.0";
        androidCmakeVersion = "3.22.1";
        androidSdkArgs = {
          cmakeVersions = [ androidCmakeVersion ];
          platformVersions = [ androidPlatformVersion ];
          abiVersions = [
            "arm64-v8a"
            "armeabi-v7a"
            "x86_64"
          ];
          systemImageTypes = [
            "google_apis"
            #"google_apis_playstore"
          ];
          platformToolsVersion = "34.0.1";
          ndkVersions = [ "23.1.7779620" ];
          buildToolsVersions = [ androidBuildToolsVersion ];

          includeNDK = true;
          #includeEmulator = true;
          #includeSystemImages = true;
          extraLicenses = [
            "android-sdk-license"
            #"android-sdk-preview-license"
            #"android-googletv-license"
            #"android-sdk-arm-dbt-license"
            #"google-gdk-license"
            #"intel-android-extra-license"
            #"intel-android-sysimage-license"
            #"mips-android-sysimage-license"
          ];
        };
        androidComposition = pkgs.androidenv.composeAndroidPackages androidSdkArgs;
        androidEmulateApp =
          args:
          pkgs.androidenv.emulateApp (
            {
              name = "android-emulate-app";
              app = null;
              deviceName = "device";
              package = "";

              # ToDo: set this when the emulator will be working
              # for emulate-android-armeabi-v7a
              # or emulate-android-arm64-v8a
              #app = ".";
              #package = "chat.simplex.app";
              #activity = "chat.simplex.app.MainActivity";

              sdkExtraArgs = androidSdkArgs // {
                emulatorVersion = "35.6.2";
              };
              platformVersion = androidPlatformVersion;
              systemImageType = "google_apis";

              # ExplanationNote: workaround `-gpu host` not working
              # on my Vulkan system.
              androidEmulatorFlags = "-gpu guest";

              configOptions = {
                "hw.keyboard" = "yes";
                # FixMe: Not working for me:
                # WARNING | emuglConfig_get_vulkan_hardware_gpu: Failed to create vulkan instance error code: -9
                # See https://issuetracker.google.com/issues/356896486
                #"hw.gpu.enabled" = "yes";
              };
            }
            // args
          );
      in
      {
        packages = rec {
          default = emulate-android-x86_64;

          emulate-android-x86_64 = androidEmulateApp { abiVersion = "x86_64"; };

          # FailureNote: PANIC: Avd's CPU Architecture 'arm64' is not supported by the QEMU2 emulator on x86_64 host.
          # ExplanationNote: https://developer.android.com/studio/releases/emulator#support_for_arm_binaries_on_android_9_and_11_system_images
          # If you were previously unable to use the Android Emulator because
          # your app depended on ARM binaries, you can now use the Android 9
          # x86 system image or any Android 11 system image to run your app –
          # it is no longer necessary to download a specific system image to
          # run ARM binaries. These Android 9 and Android 11 system images
          # support ARM by default and provide dramatically improved
          # performance when compared to those with full ARM emulation.
          emulate-android-arm64-v8a = androidEmulateApp { abiVersion = "arm64-v8a"; };

          # FailureNote: PANIC: CPU Architecture 'arm' is not supported by the QEMU2 emulator, (the classic engine is deprecated!)
          # Note: only androidPlatformVersion <= 25 still provide images for this ABI
          # See nixpkgs/pkgs/development/mobile/androidenv/repo.json
          emulate-android-armeabi-v7a = androidEmulateApp { abiVersion = "armeabi-v7a"; };

          android-sdk = inputs.android-nixpkgs.sdk (
            sdkPkgs: with sdkPkgs; [
              cmdline-tools-latest
              build-tools-34-0-0
              platform-tools
              platforms-android-34
              emulator
            ]
          );
        };

        devShell =
          let
            zipAlignPath = "${androidComposition.androidsdk}/libexec/android-sdk/build-tools/${androidBuildToolsVersion}/zipalign";
          in
          pkgs.mkShell {
            buildInputs = [
              (pkgs.android-studio.withSdk androidComposition.androidsdk)
              (pkgs.writeShellScriptBin "zipalign" ''exec ${zipAlignPath} "$@"'')
              androidComposition.androidsdk
              androidComposition.platform-tools
              pkgs.gradle
              pkgs.gradle.jdk
            ];
            shellHook = ''
              # Note: ANDROID_HOME is deprecated. Use ANDROID_SDK_ROOT.
              export ANDROID_SDK_ROOT="${androidComposition.androidsdk}/libexec/android-sdk"
              export ANDROID_NDK_ROOT="${androidComposition.androidsdk}/libexec/android-sdk/ndk-bundle"
              export PATH="$(echo "$ANDROID_SDK_ROOT/cmake/${androidCmakeVersion}".*/bin):$PATH"

              # Use the same androidBuildToolsVersion
              # and a statically linked aapt2 to workaround a dynamic linking failure.
              export GRADLE_OPTS="-Dorg.gradle.project.android.aapt2FromMavenOverride=$ANDROID_SDK_ROOT/build-tools/${androidBuildToolsVersion}/aapt2";
            '';
          };
      }
    );
}