Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1# Android {#android} 2 3The Android build environment provides three major features and a number of 4supporting features. 5 6## Using androidenv with Android Studio {#using-androidenv-with-android-studio} 7 8Use the `android-studio-full` attribute for a very complete Android SDK, including system images: 9 10```nix 11buildInputs = [ android-studio-full ]; 12``` 13 14This is identical to: 15 16```nix 17buildInputs = [ androidStudioPackages.stable.full ]; 18``` 19 20Alternatively, you can pass composeAndroidPackages to the `withSdk` passthru: 21 22```nix 23buildInputs = [ 24 (android-studio.withSdk (androidenv.composeAndroidPackages { 25 includeNDK = true; 26 }).androidsdk) 27]; 28``` 29 30These will export ANDROID_SDK_ROOT and ANDROID_NDK_ROOT to the SDK and NDK directories 31in the specified Android build environment. 32 33## Deploying an Android SDK installation with plugins {#deploying-an-android-sdk-installation-with-plugins} 34 35Alternatively, you can deploy the SDK separately with a desired set of plugins, or subsets of an SDK. 36 37```nix 38with import <nixpkgs> {}; 39 40let 41 androidComposition = androidenv.composeAndroidPackages { 42 cmdLineToolsVersion = "8.0"; 43 toolsVersion = "26.1.1"; 44 platformToolsVersion = "30.0.5"; 45 buildToolsVersions = [ "30.0.3" ]; 46 includeEmulator = false; 47 emulatorVersion = "30.3.4"; 48 platformVersions = [ "28" "29" "30" ]; 49 includeSources = false; 50 includeSystemImages = false; 51 systemImageTypes = [ "google_apis_playstore" ]; 52 abiVersions = [ "armeabi-v7a" "arm64-v8a" ]; 53 cmakeVersions = [ "3.10.2" ]; 54 includeNDK = true; 55 ndkVersions = ["22.0.7026061"]; 56 useGoogleAPIs = false; 57 useGoogleTVAddOns = false; 58 includeExtras = [ 59 "extras;google;gcm" 60 ]; 61 }; 62in 63androidComposition.androidsdk 64``` 65 66The above function invocation states that we want an Android SDK with the above 67specified plugin versions. By default, most plugins are disabled. Notable 68exceptions are the tools, platform-tools and build-tools sub packages. 69 70The following parameters are supported: 71 72* `cmdLineToolsVersion `, specifies the version of the `cmdline-tools` package to use 73* `toolsVersion`, specifies the version of the `tools` package. Notice `tools` is 74 obsolete, and currently only `26.1.1` is available, so there's not a lot of 75 options here, however, you can set it as `null` if you don't want it. 76* `platformsToolsVersion` specifies the version of the `platform-tools` plugin 77* `buildToolsVersions` specifies the versions of the `build-tools` plugins to 78 use. 79* `includeEmulator` specifies whether to deploy the emulator package (`false` 80 by default). When enabled, the version of the emulator to deploy can be 81 specified by setting the `emulatorVersion` parameter. 82* `cmakeVersions` specifies which CMake versions should be deployed. 83* `includeNDK` specifies that the Android NDK bundle should be included. 84 Defaults to: `false`. 85* `ndkVersions` specifies the NDK versions that we want to use. These are linked 86 under the `ndk` directory of the SDK root, and the first is linked under the 87 `ndk-bundle` directory. 88* `ndkVersion` is equivalent to specifying one entry in `ndkVersions`, and 89 `ndkVersions` overrides this parameter if provided. 90* `includeExtras` is an array of identifier strings referring to arbitrary 91 add-on packages that should be installed. 92* `platformVersions` specifies which platform SDK versions should be included. 93 94For each platform version that has been specified, we can apply the following 95options: 96 97* `includeSystemImages` specifies whether a system image for each platform SDK 98 should be included. 99* `includeSources` specifies whether the sources for each SDK version should be 100 included. 101* `useGoogleAPIs` specifies that for each selected platform version the 102 Google API should be included. 103* `useGoogleTVAddOns` specifies that for each selected platform version the 104 Google TV add-on should be included. 105 106For each requested system image we can specify the following options: 107 108* `systemImageTypes` specifies what kind of system images should be included. 109 Defaults to: `default`. 110* `abiVersions` specifies what kind of ABI version of each system image should 111 be included. Defaults to: `armeabi-v7a`. 112 113Most of the function arguments have reasonable default settings. 114 115You can specify license names: 116 117* `extraLicenses` is a list of license names. 118 You can get these names from repo.json or `querypackages.sh licenses`. The SDK 119 license (`android-sdk-license`) is accepted for you if you set accept_license 120 to true. If you are doing something like working with preview SDKs, you will 121 want to add `android-sdk-preview-license` or whichever license applies here. 122 123Additionally, you can override the repositories that composeAndroidPackages will 124pull from: 125 126* `repoJson` specifies a path to a generated repo.json file. You can generate this 127 by running `generate.sh`, which in turn will call into `mkrepo.rb`. 128* `repoXmls` is an attribute set containing paths to repo XML files. If specified, 129 it takes priority over `repoJson`, and will trigger a local build writing out a 130 repo.json to the Nix store based on the given repository XMLs. 131 132```nix 133{ 134 repoXmls = { 135 packages = [ ./xml/repository2-1.xml ]; 136 images = [ 137 ./xml/android-sys-img2-1.xml 138 ./xml/android-tv-sys-img2-1.xml 139 ./xml/android-wear-sys-img2-1.xml 140 ./xml/android-wear-cn-sys-img2-1.xml 141 ./xml/google_apis-sys-img2-1.xml 142 ./xml/google_apis_playstore-sys-img2-1.xml 143 ]; 144 addons = [ ./xml/addon2-1.xml ]; 145 }; 146} 147``` 148 149When building the above expression with: 150 151```bash 152$ nix-build 153``` 154 155The Android SDK gets deployed with all desired plugin versions. 156 157We can also deploy subsets of the Android SDK. For example, to only the 158`platform-tools` package, you can evaluate the following expression: 159 160```nix 161with import <nixpkgs> {}; 162 163let 164 androidComposition = androidenv.composeAndroidPackages { 165 # ... 166 }; 167in 168androidComposition.platform-tools 169``` 170 171## Using predefined Android package compositions {#using-predefined-android-package-compositions} 172 173In addition to composing an Android package set manually, it is also possible 174to use a predefined composition that contains a fairly complete set of Android packages: 175 176The following Nix expression can be used to deploy the entire SDK: 177 178```nix 179with import <nixpkgs> {}; 180 181androidenv.androidPkgs.androidsdk 182``` 183 184It is also possible to use one plugin only: 185 186```nix 187with import <nixpkgs> {}; 188 189androidenv.androidPkgs.platform-tools 190``` 191 192## Spawning emulator instances {#spawning-emulator-instances} 193 194For testing purposes, it can also be quite convenient to automatically generate 195scripts that spawn emulator instances with all desired configuration settings. 196 197An emulator spawn script can be configured by invoking the `emulateApp {}` 198function: 199 200```nix 201with import <nixpkgs> {}; 202 203androidenv.emulateApp { 204 name = "emulate-MyAndroidApp"; 205 platformVersion = "28"; 206 abiVersion = "x86"; # armeabi-v7a, mips, x86_64 207 systemImageType = "google_apis_playstore"; 208} 209``` 210 211Additional flags may be applied to the Android SDK's emulator through the runtime environment variable `$NIX_ANDROID_EMULATOR_FLAGS`. 212 213It is also possible to specify an APK to deploy inside the emulator 214and the package and activity names to launch it: 215 216```nix 217with import <nixpkgs> {}; 218 219androidenv.emulateApp { 220 name = "emulate-MyAndroidApp"; 221 platformVersion = "24"; 222 abiVersion = "armeabi-v7a"; # mips, x86, x86_64 223 systemImageType = "default"; 224 app = ./MyApp.apk; 225 package = "MyApp"; 226 activity = "MainActivity"; 227} 228``` 229 230In addition to prebuilt APKs, you can also bind the APK parameter to a 231`buildApp {}` function invocation shown in the previous example. 232 233## Notes on environment variables in Android projects {#notes-on-environment-variables-in-android-projects} 234 235* `ANDROID_HOME` should point to the Android SDK. In your Nix expressions, this should be 236 `${androidComposition.androidsdk}/libexec/android-sdk`. Note that `ANDROID_SDK_ROOT` is deprecated, 237 but if you rely on tools that need it, you can export it too. 238* `ANDROID_NDK_ROOT` should point to the Android NDK, if you're doing NDK development. 239 In your Nix expressions, this should be `${ANDROID_HOME}/ndk-bundle`. 240 241If you are running the Android Gradle plugin, you need to export GRADLE_OPTS to override aapt2 242to point to the aapt2 binary in the Nix store as well, or use a FHS environment so the packaged 243aapt2 can run. If you don't want to use a FHS environment, something like this should work: 244 245```nix 246let 247 buildToolsVersion = "30.0.3"; 248 249 # Use buildToolsVersion when you define androidComposition 250 androidComposition = <...>; 251in 252pkgs.mkShell rec { 253 ANDROID_HOME = "${androidComposition.androidsdk}/libexec/android-sdk"; 254 ANDROID_NDK_ROOT = "${ANDROID_HOME}/ndk-bundle"; 255 256 # Use the same buildToolsVersion here 257 GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_HOME}/build-tools/${buildToolsVersion}/aapt2"; 258} 259``` 260 261If you are using cmake, you need to add it to PATH in a shell hook or FHS env profile. 262The path is suffixed with a build number, but properly prefixed with the version. 263So, something like this should suffice: 264 265```nix 266let 267 cmakeVersion = "3.10.2"; 268 269 # Use cmakeVersion when you define androidComposition 270 androidComposition = <...>; 271in 272pkgs.mkShell rec { 273 ANDROID_HOME = "${androidComposition.androidsdk}/libexec/android-sdk"; 274 ANDROID_NDK_ROOT = "${ANDROID_HOME}/ndk-bundle"; 275 276 # Use the same cmakeVersion here 277 shellHook = '' 278 export PATH="$(echo "$ANDROID_HOME/cmake/${cmakeVersion}".*/bin):$PATH" 279 ''; 280} 281``` 282 283Note that running Android Studio with ANDROID_HOME set will automatically write a 284`local.properties` file with `sdk.dir` set to $ANDROID_HOME if one does not already 285exist. If you are using the NDK as well, you may have to add `ndk.dir` to this file. 286 287An example shell.nix that does all this for you is provided in examples/shell.nix. 288This shell.nix includes a shell hook that overwrites local.properties with the correct 289sdk.dir and ndk.dir values. This will ensure that the SDK and NDK directories will 290both be correct when you run Android Studio inside nix-shell. 291 292## Notes on improving build.gradle compatibility {#notes-on-improving-build.gradle-compatibility} 293 294Ensure that your buildToolsVersion and ndkVersion match what is declared in androidenv. 295If you are using cmake, make sure its declared version is correct too. 296 297Otherwise, you may get cryptic errors from aapt2 and the Android Gradle plugin warning 298that it cannot install the build tools because the SDK directory is not writeable. 299 300```gradle 301android { 302 buildToolsVersion "30.0.3" 303 ndkVersion = "22.0.7026061" 304 externalNativeBuild { 305 cmake { 306 version "3.10.2" 307 } 308 } 309} 310 311``` 312 313## Querying the available versions of each plugin {#querying-the-available-versions-of-each-plugin} 314 315repo.json provides all the options in one file now. 316 317A shell script in the `pkgs/development/mobile/androidenv/` subdirectory can be used to retrieve all 318possible options: 319 320```bash 321./querypackages.sh packages 322``` 323 324The above command-line instruction queries all package versions in repo.json. 325 326## Updating the generated expressions {#updating-the-generated-expressions} 327 328repo.json is generated from XML files that the Android Studio package manager uses. 329To update the expressions run the `generate.sh` script that is stored in the 330`pkgs/development/mobile/androidenv/` subdirectory: 331 332```bash 333./generate.sh 334``` 335 336## Building an Android application with Ant {#building-an-android-application-with-ant} 337 338In addition to the SDK, it is also possible to build an Ant-based Android 339project and automatically deploy all the Android plugins that a project 340requires. Most newer Android projects use Gradle, and this is included for historical 341purposes. 342 343```nix 344with import <nixpkgs> {}; 345 346androidenv.buildApp { 347 name = "MyAndroidApp"; 348 src = ./myappsources; 349 release = true; 350 351 # If release is set to true, you need to specify the following parameters 352 keyStore = ./keystore; 353 keyAlias = "myfirstapp"; 354 keyStorePassword = "mykeystore"; 355 keyAliasPassword = "myfirstapp"; 356 357 # Any Android SDK parameters that install all the relevant plugins that a 358 # build requires 359 platformVersions = [ "24" ]; 360 361 # When we include the NDK, then ndk-build is invoked before Ant gets invoked 362 includeNDK = true; 363} 364``` 365 366Aside from the app-specific build parameters (`name`, `src`, `release` and 367keystore parameters), the `buildApp {}` function supports all the function 368parameters that the SDK composition function (the function shown in the 369previous section) supports. 370 371This build function is particularly useful when it is desired to use 372[Hydra](https://nixos.org/hydra): the Nix-based continuous integration solution 373to build Android apps. An Android APK gets exposed as a build product and can be 374installed on any Android device with a web browser by navigating to the build 375result page.