Files
nixpkgs/pkgs/development/mobile/androidenv/examples/shell-without-emulator.nix
T
Morgan Jones 03d6e4bc46 androidenv: support nonstandard SDK versions
Google have been releasing 'nonstandard' SDK versions for a while. Named
things like CANARY, UpsideDownCake, 36x, and so on, androidenv has been
generally unable to use them, instead preferring Google's officially
supported Android SDKs corresponding to the
[API levels](https://apilevels.com/) (e.g. "35" or "36").

Updates to those SDK versions have generally come in the form of
updates to Google's repositories that repo.json picks up.
These are mostly noneventful for end users, unless a user experienced a
bug in an API definition, then it tended to be picked up with an
androidenv repo update.

API 36.1 changes this. It's not just a number (so it doesn't correspond
to a unique API level). The previous attempt in #470569 simply preferred
the newer version to attempt to emulate the old behavior.

Unfortunately, this now requires a Gradle change (see #472561). So this
means we should just support all the strange SDK versions now and have a
test for it.

Note that only depending on "latest" (the default) will properly pick
these up as the latest, but using a min and max SDK version or
numLatestPlatformVersions > 1 will create a range of SDK versions as
before, which means you may miss (e.g.) 36.1 but will still have 36.
Considering that this requires `compileSdk "android-36.1"`
instead of a simple `compileSdk 36` in Gradle, it's recommended to
explicitly specify platformVersions if you depend on this change,
or use the defaults, where it will only install the latest.
2025-12-22 23:45:00 -08:00

165 lines
4.6 KiB
Nix

{
# To test your changes in androidEnv run `nix-shell android-sdk-with-emulator-shell.nix`
# If you copy this example out of nixpkgs, use these lines instead of the next.
# This example pins nixpkgs: https://nix.dev/tutorials/first-steps/towards-reproducibility-pinning-nixpkgs.html
/*
nixpkgsSource ? (fetchTarball {
name = "nixpkgs-20.09";
url = "https://github.com/NixOS/nixpkgs/archive/20.09.tar.gz";
sha256 = "1wg61h4gndm3vcprdcg7rc4s1v3jkm5xd7lw8r2f67w502y94gcy";
}),
pkgs ? import nixpkgsSource {
config.allowUnfree = true;
},
*/
# If you want to use the in-tree version of nixpkgs:
pkgs ? import ../../../../.. {
config.allowUnfree = true;
},
licenseAccepted ? pkgs.callPackage ../license.nix { },
}:
# Copy this file to your Android project.
let
# If you copy this example out of nixpkgs, something like this will work:
/*
androidEnvNixpkgs = fetchTarball {
name = "androidenv";
url = "https://github.com/NixOS/nixpkgs/archive/<fill me in from Git>.tar.gz";
sha256 = "<fill me in with nix-prefetch-url --unpack>";
};
androidEnv = pkgs.callPackage "${androidEnvNixpkgs}/pkgs/development/mobile/androidenv" {
inherit pkgs;
licenseAccepted = true;
};
*/
inherit (pkgs) lib;
# Otherwise, just use the in-tree androidenv:
androidEnv = pkgs.callPackage ./.. {
inherit pkgs licenseAccepted;
};
sdkArgs = {
includeNDK = false;
includeSystemImages = false;
includeEmulator = false;
platformVersions = [
"UpsideDownCake"
"36"
"36x"
"latest"
"CANARY"
];
# Accepting more licenses declaratively:
extraLicenses = [
# Already accepted for you with the global accept_license = true or
# licenseAccepted = true on androidenv.
# "android-sdk-license"
# These aren't, but are useful for more uncommon setups.
"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 = androidEnv.composeAndroidPackages sdkArgs;
androidSdk = androidComposition.androidsdk;
platformTools = androidComposition.platform-tools;
latestSdkVersion = lib.foldl' (
s: x: if lib.strings.compareVersions (toString x) s > 0 then toString x else s
) "0" androidComposition.platformVersions;
jdk = pkgs.jdk;
in
pkgs.mkShell {
name = "androidenv-example-without-emulator-demo";
packages = [
androidSdk
platformTools
jdk
];
LANG = "C.UTF-8";
LC_ALL = "C.UTF-8";
JAVA_HOME = jdk.home;
# Note: ANDROID_HOME is deprecated. Use ANDROID_SDK_ROOT.
ANDROID_SDK_ROOT = "${androidSdk}/libexec/android-sdk";
shellHook = ''
# Write out local.properties for Android Studio.
cat <<EOF > local.properties
# This file was automatically generated by nix-shell.
sdk.dir=$ANDROID_SDK_ROOT
EOF
'';
passthru.tests = {
shell-without-emulator-sdkmanager-packages-test =
pkgs.runCommand "shell-without-emulator-sdkmanager-packages-test"
{
nativeBuildInputs = [
androidSdk
jdk
];
}
''
output="$(sdkmanager --list)"
installed_packages_section=$(echo "''${output%%Available Packages*}" | awk 'NR>4 {print $1}')
echo "installed_packages_section: ''${installed_packages_section}"
packages=(
"build-tools" "cmdline-tools" \
"platform-tools" "platforms;android-${toString latestSdkVersion}"
)
for package in "''${packages[@]}"; do
if [[ ! $installed_packages_section =~ "$package" ]]; then
echo "$package package was not installed."
exit 1
fi
done
touch "$out"
'';
shell-without-emulator-sdkmanager-excluded-packages-test =
pkgs.runCommand "shell-without-emulator-sdkmanager-excluded-packages-test"
{
nativeBuildInputs = [
androidSdk
jdk
];
}
''
output="$(sdkmanager --list)"
installed_packages_section=$(echo "''${output%%Available Packages*}" | awk 'NR>4 {print $1}')
excluded_packages=(
"emulator" "ndk"
)
for package in "''${excluded_packages[@]}"; do
if [[ $installed_packages_section =~ "$package" ]]; then
echo "$package package was installed, while it was excluded!"
exit 1
fi
done
touch "$out"
'';
};
}