blob: 57d4764d068e4d6fe369d58f6d626e4ae10adcec [file] [log] [blame] [view]
David Chenc4af8282016-01-20 11:06:35 +00001---
dzc22b85a22017-05-31 20:37:50 +02002layout: documentation
Googler3d70c312017-08-09 00:23:38 +02003title: Build Tutorial - Android
David Chenc4af8282016-01-20 11:06:35 +00004---
dzc22b85a22017-05-31 20:37:50 +02005
Jingwen Chen92b14d32018-11-12 09:19:16 -08006# Introduction to Bazel: Building an Android App
dzc22b85a22017-05-31 20:37:50 +02007
Jingwen Chen92b14d32018-11-12 09:19:16 -08008In this tutorial, you will learn how to build a simple Android app using Bazel.
dzc22b85a22017-05-31 20:37:50 +02009
Jingwen Chen92b14d32018-11-12 09:19:16 -080010Bazel supports building Android apps using the [Android
11rules](https://docs.bazel.build/versions/master/be/android.html).
dzc22b85a22017-05-31 20:37:50 +020012
Jingwen Chen92b14d32018-11-12 09:19:16 -080013This tutorial is intended for Windows, macOS and Linux users and does not
14require experience with Bazel or Android app development. You do not need to
15write any Android code in this tutorial.
Googler3d70c312017-08-09 00:23:38 +020016
Jingwen Chen92b14d32018-11-12 09:19:16 -080017## Prerequisites
Googler3d70c312017-08-09 00:23:38 +020018
Jingwen Chen92b14d32018-11-12 09:19:16 -080019You will need to install the following software:
Googler3d70c312017-08-09 00:23:38 +020020
Jingwen Chen92b14d32018-11-12 09:19:16 -080021* **Bazel.** To install, follow the [installation instructions](../install.md).
22* **Android Studio.** To install, follow the steps to [download Android
23 Studio](https://developer.android.com/sdk/index.html).
24* (Optional) **Git.** We will use `git` to download the Android app project.
Googler3d70c312017-08-09 00:23:38 +020025
Jingwen Chen92b14d32018-11-12 09:19:16 -080026## Getting started
Googler3d70c312017-08-09 00:23:38 +020027
Jingwen Chen92b14d32018-11-12 09:19:16 -080028We will be using a basic Android app project in [Bazel's examples
29repository](https://github.com/bazelbuild/examples).
Googler3d70c312017-08-09 00:23:38 +020030
Jingwen Chen92b14d32018-11-12 09:19:16 -080031This app has a single button that prints a greeting when clicked.
32
33<img src="/assets/android_tutorial_app.png" alt="screenshot of tutorial app"
34width="700">
35
36Clone the repository with `git` (or [download the ZIP file
37directly](https://github.com/bazelbuild/examples/archive/master.zip)):
38
39``` bash
40git clone git@github.com:bazelbuild/examples.git bazel-examples
41cd bazel-examples/android/tutorial
42```
43
44For the rest of the tutorial, you will be executing commands in this directory.
45
46## Review the source files
47
48Let's take a look at the source files for the app.
49
50```
Googler3d70c312017-08-09 00:23:38 +020051.
Jingwen Chen92b14d32018-11-12 09:19:16 -080052├── README.md
53└── src
54 └── main
55 ├── AndroidManifest.xml
56 └── java
57 └── com
58 └── example
59 └── bazel
60 ├── AndroidManifest.xml
61 ├── Greeter.java
62 ├── MainActivity.java
63 └── res
64 ├── layout
65 │   └── activity_main.xml
66 └── values
67 ├── colors.xml
68 └── strings.xml
Googler3d70c312017-08-09 00:23:38 +020069```
70
Jingwen Chen92b14d32018-11-12 09:19:16 -080071The key files and directories are:
Googler3d70c312017-08-09 00:23:38 +020072
Jingwen Chen92b14d32018-11-12 09:19:16 -080073| Name | Location |
74| Android manifest files | `src/main/AndroidManifest.xml` and `src/main/java/com/example/bazel/AndroidManifest.xml` |
75| Android source files | `src/main/java/com/example/bazel/MainActivity.java` and `Greeter.java` |
76| Resource file directory | `src/main/java/com/example/bazel/res/` |
Googler3d70c312017-08-09 00:23:38 +020077
Jingwen Chen92b14d32018-11-12 09:19:16 -080078## Initialize the project's workspace
Googler3d70c312017-08-09 00:23:38 +020079
Jingwen Chen92b14d32018-11-12 09:19:16 -080080A [workspace](../build-ref.html#workspace) is a directory that contains the
81source files for one or more software projects, and has a `WORKSPACE` file at
82its root.
Googler3d70c312017-08-09 00:23:38 +020083
Jingwen Chen92b14d32018-11-12 09:19:16 -080084The `WORKSPACE` file may be empty or may contain references to [external
85dependencies](../external.html) required to build your project.
Googler3d70c312017-08-09 00:23:38 +020086
Jingwen Chen92b14d32018-11-12 09:19:16 -080087First, run the following command to create an empty `WORKSPACE` file:
88
89| Linux, macOS | `touch WORKSPACE` |
90| Windows (Command Prompt) | `type nul > WORKSPACE` |
91| Windows (PowerShell) | `New-Item WORKSPACE -ItemType file` |
92
93### Running Bazel
94
95You can now check if Bazel is running correctly with the command:
Googler3d70c312017-08-09 00:23:38 +020096
97```bash
Jingwen Chen92b14d32018-11-12 09:19:16 -080098bazel info workspace
Googler3d70c312017-08-09 00:23:38 +020099```
100
Jingwen Chen92b14d32018-11-12 09:19:16 -0800101If Bazel prints the path of the current directory, you're good to go! If the
102`WORKSPACE` file does not exist, you may see an error message like:
Googler3d70c312017-08-09 00:23:38 +0200103
Googler3d70c312017-08-09 00:23:38 +0200104```
Jingwen Chen92b14d32018-11-12 09:19:16 -0800105ERROR: The 'info' command is only supported from within a workspace.
106```
Googler3d70c312017-08-09 00:23:38 +0200107
Jingwen Chen92b14d32018-11-12 09:19:16 -0800108## Integrate with the Android SDK
Googler3d70c312017-08-09 00:23:38 +0200109
Jingwen Chen92b14d32018-11-12 09:19:16 -0800110Bazel needs to run the Android SDK [build
111tools](https://developer.android.com/tools/revisions/build-tools.html) to build
112the app. This means that you need to add some information to your `WORKSPACE`
113file so that Bazel knows where to find them.
Googler3d70c312017-08-09 00:23:38 +0200114
Jingwen Chen92b14d32018-11-12 09:19:16 -0800115Add the following line to your `WORKSPACE` file:
Googler3d70c312017-08-09 00:23:38 +0200116
117```python
Jingwen Chen92b14d32018-11-12 09:19:16 -0800118android_sdk_repository(name = "androidsdk")
Googler3d70c312017-08-09 00:23:38 +0200119```
120
Jingwen Chen92b14d32018-11-12 09:19:16 -0800121This will use the Android SDK at the path referenced by the `ANDROID_HOME`
122environment variable, and automatically detect the highest API level and the
123latest version of build tools installed within that location.
Googler3d70c312017-08-09 00:23:38 +0200124
Jingwen Chen92b14d32018-11-12 09:19:16 -0800125You can set the `ANDROID_HOME` variable to the location of the Android SDK. Find
126the path to the installed SDK using Android Studio's [SDK
127Manager](https://developer.android.com/studio/intro/update#sdk-manager).
128
129For example, as the default SDK path is in your home directory for Linux and
130macOS, and `LOCALAPPDATA` for Windows, you can use the following commands to set
131the `ANDROID_HOME` variable:
132
133| Linux, macOS | `export ANDROID_HOME=$HOME/Android/Sdk/` |
134| Windows (Command Prompt) | `set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk` |
135| Windows (PowerShell) | `$env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk"` |
136
137The above commands set the variable only for the current shell session. To make
138them permanent, run the following commands:
139
140| Linux, macOS | `echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc` |
141| Windows (Command Prompt) | `setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk"` |
142| Windows (PowerShell) | `[System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User)` |
143
144You can also explicitly specify the absolute path of the Android SDK,
145the API level, and the version of build tools to use by including the `path`,
146`api_level`, and `build_tools_version` attributes. If `api_level` and
147`build_tools_version` are not specified, the `android_sdk_repository` rule will
148use the respective latest version available in the SDK. You can specify any
149combination of these attributes, as long as they are present in the SDK, for
150example:
Googler3d70c312017-08-09 00:23:38 +0200151
152```python
153android_sdk_repository(
154 name = "androidsdk",
155 path = "/path/to/Android/sdk",
156 api_level = 25,
dannark5eb684f2017-09-06 02:29:30 +0200157 build_tools_version = "26.0.1"
Googler3d70c312017-08-09 00:23:38 +0200158)
159```
160
Jingwen Chen92b14d32018-11-12 09:19:16 -0800161On Windows, note that the `path` attribute must use the mixed-style path, that
162is, a Windows path with forward slashes:
Googler3d70c312017-08-09 00:23:38 +0200163
164```python
Jingwen Chen92b14d32018-11-12 09:19:16 -0800165android_sdk_repository(
166 name = "androidsdk",
167 path = "c:/path/to/Android/sdk",
Googler3d70c312017-08-09 00:23:38 +0200168)
169```
170
Jingwen Chen92b14d32018-11-12 09:19:16 -0800171**Optional:** If you want to compile native code into your Android app, you
jingwen5d99e3f2018-11-12 13:25:13 -0800172also need to download the [Android
173NDK](https://developer.android.com/ndk/downloads/index.html)
Jingwen Chen92b14d32018-11-12 09:19:16 -0800174and tell Bazel where to find it by adding the following line to your `WORKSPACE` file:
175
176```python
177android_ndk_repository(name = "androidndk")
178```
Googler3d70c312017-08-09 00:23:38 +0200179
180Similar to `android_sdk_repository`, the path to the Android NDK is inferred
181from the `ANDROID_NDK_HOME` environment variable by default. The path can also
182be explicitly specified with a `path` attribute on `android_ndk_repository`.
dzc22b85a22017-05-31 20:37:50 +0200183
Jingwen Chen92b14d32018-11-12 09:19:16 -0800184For more information, read [Using the Android Native Development Kit with
185Bazel](https://docs.bazel.build/versions/master/android-ndk.html).
dzc22b85a22017-05-31 20:37:50 +0200186
Jingwen Chen92b14d32018-11-12 09:19:16 -0800187`api_level` is the version of the Android API that the SDK and NDK
188target - for example, 23 for Android 6.0 and 25 for Android 7.1. If not
189explicitly set, `api_level` defaults to the highest available API level for
190`android_sdk_repository` and `android_ndk_repository`.
dzc22b85a22017-05-31 20:37:50 +0200191
Jingwen Chen92b14d32018-11-12 09:19:16 -0800192It's not necessary to set the API levels to the same value for the SDK and NDK.
193[This page](https://developer.android.com/ndk/guides/stable_apis.html) contains
194a map from Android releases to NDK-supported API levels.
dzc22b85a22017-05-31 20:37:50 +0200195
dzc22b85a22017-05-31 20:37:50 +0200196## Create a BUILD file
197
Jingwen Chen92b14d32018-11-12 09:19:16 -0800198A [`BUILD` file](../build-ref.html#BUILD_files) describes the relationship
199between a set of build outputs, like compiled Android resources from `aapt` or
200class files from `javac`, and their dependencies. These dependencies may be
201source files (Java, C++) in your workspace or other build outputs. `BUILD` files
202are written in a language called **Starlark**.
dzc22b85a22017-05-31 20:37:50 +0200203
Googler3d70c312017-08-09 00:23:38 +0200204`BUILD` files are part of a concept in Bazel known as the *package hierarchy*.
dzc22b85a22017-05-31 20:37:50 +0200205The package hierarchy is a logical structure that overlays the directory
dzc205125b2017-06-26 11:01:47 +0200206structure in your workspace. Each [package](../build-ref.html#packages) is a
dzc22b85a22017-05-31 20:37:50 +0200207directory (and its subdirectories) that contains a related set of source files
208and a `BUILD` file. The package also includes any subdirectories, excluding
Jingwen Chen92b14d32018-11-12 09:19:16 -0800209those that contain their own `BUILD` file. The *package name* is the path to the
210`BUILD` file relative to the `WORKSPACE`.
dzc22b85a22017-05-31 20:37:50 +0200211
Jingwen Chen92b14d32018-11-12 09:19:16 -0800212Note that Bazel's package hierarchy is conceptually different from the Java
213package hierarchy of your Android App directory where the `BUILD` file is
214located. , although the directories may be organized identically.
dzc22b85a22017-05-31 20:37:50 +0200215
Jingwen Chen92b14d32018-11-12 09:19:16 -0800216For the simple Android app in this tutorial, the source files in `src/main/`
217comprise a single Bazel package. A more complex project may have many nested
218packages.
dzc22b85a22017-05-31 20:37:50 +0200219
220### Add an android_library rule
221
Jingwen Chen92b14d32018-11-12 09:19:16 -0800222A `BUILD` file contains several different types of declarations for Bazel. The
dzc205125b2017-06-26 11:01:47 +0200223most important type is the [build rule](../build-ref.html#funcs), which tells
dzc22b85a22017-05-31 20:37:50 +0200224Bazel how to build an intermediate or final software output from a set of source
225files or other dependencies.
226
227Bazel provides two build rules, `android_library` and `android_binary`, that you
228can use to build an Android app. For this tutorial, you'll first use the
Jingwen Chen92b14d32018-11-12 09:19:16 -0800229[`android_library`](../be/android.html#android_library) rule to tell Bazel to
230build an [Android library
231module](http://developer.android.com/tools/projects/index.html#LibraryProjects)
232from the app source code and resource files. You'll then use the
233`android_binary` rule to tell Bazel how to build the Android application package.
dzc22b85a22017-05-31 20:37:50 +0200234
Jingwen Chen92b14d32018-11-12 09:19:16 -0800235Create a new `BUILD` file in the `src/main/java/com/example/bazel` directory,
236and declare a new `android_library` target:
237
238`src/main/java/com/example/bazel/BUILD`:
dzc22b85a22017-05-31 20:37:50 +0200239
240```python
Jingwen Chen92b14d32018-11-12 09:19:16 -0800241package(
242 default_visibility = ["//src:__subpackages__"],
243)
244
dzc22b85a22017-05-31 20:37:50 +0200245android_library(
Jingwen Chen92b14d32018-11-12 09:19:16 -0800246 name = "greeter_activity",
247 srcs = [
248 "Greeter.java",
249 "MainActivity.java",
250 ],
251 manifest = "AndroidManifest.xml",
252 resource_files = glob(["res/**"]),
dzc22b85a22017-05-31 20:37:50 +0200253)
254```
255
Jingwen Chen92b14d32018-11-12 09:19:16 -0800256The `android_library` build rule contains a set of attributes that specify the
257information that Bazel needs to build a library module from the source files.
258Note also that the name of the rule is `greeter_activity`. You'll reference the
259rule using this name as a dependency in the `android_binary` rule.
dzc22b85a22017-05-31 20:37:50 +0200260
261### Add an android_binary rule
262
dzc205125b2017-06-26 11:01:47 +0200263The [`android_binary`](../be/android.html#android_binary) rule builds
dzc22b85a22017-05-31 20:37:50 +0200264the Android application package (`.apk` file) for your app.
265
Jingwen Chen92b14d32018-11-12 09:19:16 -0800266Create a new `BUILD` file in the `src/main/` directory,
267and declare a new `android_binary` target:
268
269`src/main/BUILD`:
dzc22b85a22017-05-31 20:37:50 +0200270
271```python
272android_binary(
Jingwen Chen92b14d32018-11-12 09:19:16 -0800273 name = "app",
274 manifest = "AndroidManifest.xml",
275 deps = ["//src/main/java/com/example/bazel:greeter_activity"],
dzc22b85a22017-05-31 20:37:50 +0200276)
277```
278
Jingwen Chen92b14d32018-11-12 09:19:16 -0800279Here, the `deps` attribute references the output of the `greeter_activity` rule
280you added to the `BUILD` file above. This means that when Bazel builds the
281output of this rule it checks first to see if the output of the
282`greeter_activity` library rule has been built and is up-to-date. If not, Bazel
283builds it and then uses that output to build the application package file.
dzc22b85a22017-05-31 20:37:50 +0200284
Jingwen Chen92b14d32018-11-12 09:19:16 -0800285Now, save and close the file.
dzc22b85a22017-05-31 20:37:50 +0200286
Googler3d70c312017-08-09 00:23:38 +0200287## Build the app
dzc22b85a22017-05-31 20:37:50 +0200288
Jingwen Chen92b14d32018-11-12 09:19:16 -0800289Let's try building the app! Run the following command to build the
290`android_binary` target:
dzc22b85a22017-05-31 20:37:50 +0200291
292```bash
Jingwen Chen92b14d32018-11-12 09:19:16 -0800293bazel build //src/main:app
dzc22b85a22017-05-31 20:37:50 +0200294```
295
Jingwen Chen92b14d32018-11-12 09:19:16 -0800296The [`build`](../user-manual.html#build) subcommand instructs Bazel to build the
297target that follows. The target is specified as the name of a build rule inside
298a `BUILD` file, with along with the package path relative to your workspace
299directory. For this example, the target is `app` and the package path is
300`//src/main/`.
301
302Note that you can sometimes omit the package path or target name, depending on
303your current working directory at the command line and the name of the target.
304See [Labels](../build-ref.html#labels) in the *Bazel Concepts and Terminology*
305page for more information about target labels and paths.
306
307Bazel will start to build the sample app. During the build process, its output
308will appear similar to the following:
dzc22b85a22017-05-31 20:37:50 +0200309
310```bash
Jingwen Chen92b14d32018-11-12 09:19:16 -0800311INFO: Analysed target //src/main:app (0 packages loaded, 0 targets configured).
dzc22b85a22017-05-31 20:37:50 +0200312INFO: Found 1 target...
Jingwen Chen92b14d32018-11-12 09:19:16 -0800313Target //src/main:app up-to-date:
314 bazel-bin/src/main/app_deploy.jar
315 bazel-bin/src/main/app_unsigned.apk
316 bazel-bin/src/main/app.apk
dzc22b85a22017-05-31 20:37:50 +0200317```
318
Jingwen Chen92b14d32018-11-12 09:19:16 -0800319## Locate the build outputs
dzc22b85a22017-05-31 20:37:50 +0200320
Jingwen Chen92b14d32018-11-12 09:19:16 -0800321Bazel puts the outputs of both intermediate and final build operations in a set
322of per-user, per-workspace output directories. These directories are symlinked
323from the following locations at the top-level of the project directory, where
324the `WORKSPACE` is:
dzc22b85a22017-05-31 20:37:50 +0200325
Jingwen Chen92b14d32018-11-12 09:19:16 -0800326* `bazel-bin` stores binary executables and other runnable build outputs
327* `bazel-genfiles` stores intermediary source files that are generated by
328 Bazel rules
329* `bazel-out` stores other types of build outputs
dzc22b85a22017-05-31 20:37:50 +0200330
331Bazel stores the Android `.apk` file generated using the `android_binary` rule
Jingwen Chen92b14d32018-11-12 09:19:16 -0800332in the `bazel-bin/src/main` directory, where the subdirectory name `src/main` is
dzc22b85a22017-05-31 20:37:50 +0200333derived from the name of the Bazel package.
334
Jingwen Chen92b14d32018-11-12 09:19:16 -0800335At a command prompt, list the contents of this directory and find the `app.apk`
336file:
dzc22b85a22017-05-31 20:37:50 +0200337
Jingwen Chen92b14d32018-11-12 09:19:16 -0800338| Linux, macOS | `ls bazel-bin/src/main` |
339| Windows (Command Prompt) | `dir bazel-bin\src\main` |
340| Windows (PowerShell) | `ls bazel-bin\src\main` |
341
dzc22b85a22017-05-31 20:37:50 +0200342
343## Run the app
344
345You can now deploy the app to a connected Android device or emulator from the
Jingwen Chen92b14d32018-11-12 09:19:16 -0800346command line using the [`bazel
347mobile-install`](../user-manual.html#mobile-install) command. This command uses
348the Android Debug Bridge (`adb`) to communicate with the device. You must set up
349your device to use `adb` following the instructions in [Android Debug
350Bridge](http://developer.android.com/tools/help/adb.html) before deployment. You
351can also choose to install the app on the Android emulator included in Android
352Studio. Make sure the emulator is running before executing the command below.
dzc22b85a22017-05-31 20:37:50 +0200353
354Enter the following:
355
356```bash
Jingwen Chen92b14d32018-11-12 09:19:16 -0800357bazel mobile-install //src/main:app
dzc22b85a22017-05-31 20:37:50 +0200358```
359
jingwenac567392018-11-26 12:04:47 -0800360> **Note**: `mobile-install` may not work if your device is running Android 9
361> (Pie). This issue is being tracked
362> [here](https://github.com/bazelbuild/examples/issues/77).
363> As a workaround, use `adb install bazel-bin/src/main/app.apk` to install the
364> APK on the device.
365
Jingwen Chen92b14d32018-11-12 09:19:16 -0800366Next, find and launch the "Bazel Tutorial App", which looks as follows:
367
368<img src="/assets/android_tutorial_before.png" alt="screenshot of tutorial app" width="500">
369
370**Congratulations! You have just installed your first Bazel-built Android app.**
371
dzc22b85a22017-05-31 20:37:50 +0200372Note that the `mobile-install` subcommand also supports the
Jingwen Chen92b14d32018-11-12 09:19:16 -0800373[`--incremental`](../user-manual.html#mobile-install) flag that can be used to
374deploy only those parts of the app that have changed since the last deployment.
375
376It also supports the `--start_app` flag to start the app immediately upon
377installing it.
dzc22b85a22017-05-31 20:37:50 +0200378
Googler3d70c312017-08-09 00:23:38 +0200379## Review your work
dzc22b85a22017-05-31 20:37:50 +0200380
Googler3d70c312017-08-09 00:23:38 +0200381In this tutorial, you used Bazel to build an Android app. To accomplish that,
382you:
383
384* Set up your environment by installing Bazel and Android Studio, and
Jingwen Chen92b14d32018-11-12 09:19:16 -0800385 downloading the sample project.
dannarkdc71908d2018-12-04 08:24:11 -0800386* Set up a Bazel [workspace](../be/workspace.md) that contains the source code
Googler3d70c312017-08-09 00:23:38 +0200387 for the app and a `WORKSPACE` file that identifies the top level of the
Jingwen Chen92b14d32018-11-12 09:19:16 -0800388 workspace directory.
Googler3d70c312017-08-09 00:23:38 +0200389* Updated the `WORKSPACE` file to contain references to the required
Jingwen Chen92b14d32018-11-12 09:19:16 -0800390 external dependencies, like the Android SDK.
391* Created a `BUILD` file.
392* Built the app with Bazel.
393* Deployed and ran the app on an Android emulator or physical device.
Googler3d70c312017-08-09 00:23:38 +0200394
Jingwen Chen92b14d32018-11-12 09:19:16 -0800395## Further reading
Googler3d70c312017-08-09 00:23:38 +0200396
Jingwen Chen92b14d32018-11-12 09:19:16 -0800397You now know the basics of building an Android project with Bazel. Here are some
398other pages to check out:
399
dannarkdc71908d2018-12-04 08:24:11 -0800400* More information on [mobile-install](../mobile-install)
401* Testing your app with [Android instrumentation tests](../android-instrumentation-test.md)
402* Integrating C and C++ code into your Android app with the [NDK](../android-ndk.md)
Jingwen Chen92b14d32018-11-12 09:19:16 -0800403
404Happy building!