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.