| --- | |
| layout: documentation | |
| title: Build Tutorial - Android | |
| --- | |
| # Introduction to Bazel: Building an Android App | |
| In this tutorial, you will learn how to build a simple Android app using Bazel. | |
| Bazel supports building Android apps using the | |
| [Android rules](../be/android.html). | |
| This tutorial is intended for Windows, macOS and Linux users and does not | |
| require experience with Bazel or Android app development. You do not need to | |
| write any Android code in this tutorial. | |
| ## Prerequisites | |
| You will need to install the following software: | |
| * **Bazel.** To install, follow the [installation instructions](../install.md). | |
| * **Android Studio.** To install, follow the steps to [download Android | |
| Studio](https://developer.android.com/sdk/index.html). | |
| * (Optional) **Git.** We will use `git` to download the Android app project. | |
| ## Getting started | |
| We will be using a basic Android app project in [Bazel's examples | |
| repository](https://github.com/bazelbuild/examples). | |
| This app has a single button that prints a greeting when clicked. | |
| <img src="/assets/android_tutorial_app.png" alt="screenshot of tutorial app" | |
| width="700"> | |
| Clone the repository with `git` (or [download the ZIP file | |
| directly](https://github.com/bazelbuild/examples/archive/master.zip)): | |
| ``` bash | |
| git clone git@github.com:bazelbuild/examples.git bazel-examples | |
| cd bazel-examples/android/tutorial | |
| ``` | |
| For the rest of the tutorial, you will be executing commands in this directory. | |
| ## Review the source files | |
| Let's take a look at the source files for the app. | |
| ``` | |
| . | |
| ├── README.md | |
| └── src | |
| └── main | |
| ├── AndroidManifest.xml | |
| └── java | |
| └── com | |
| └── example | |
| └── bazel | |
| ├── AndroidManifest.xml | |
| ├── Greeter.java | |
| ├── MainActivity.java | |
| └── res | |
| ├── layout | |
| │ └── activity_main.xml | |
| └── values | |
| ├── colors.xml | |
| └── strings.xml | |
| ``` | |
| The key files and directories are: | |
| | Name | Location | | |
| | Android manifest files | `src/main/AndroidManifest.xml` and `src/main/java/com/example/bazel/AndroidManifest.xml` | | |
| | Android source files | `src/main/java/com/example/bazel/MainActivity.java` and `Greeter.java` | | |
| | Resource file directory | `src/main/java/com/example/bazel/res/` | | |
| ## Initialize the project's workspace | |
| A [workspace](../build-ref.html#workspace) is a directory that contains the | |
| source files for one or more software projects, and has a `WORKSPACE` file at | |
| its root. | |
| The `WORKSPACE` file may be empty or may contain references to [external | |
| dependencies](../external.html) required to build your project. | |
| First, run the following command to create an empty `WORKSPACE` file: | |
| | Linux, macOS | `touch WORKSPACE` | | |
| | Windows (Command Prompt) | `type nul > WORKSPACE` | | |
| | Windows (PowerShell) | `New-Item WORKSPACE -ItemType file` | | |
| ### Running Bazel | |
| You can now check if Bazel is running correctly with the command: | |
| ```bash | |
| bazel info workspace | |
| ``` | |
| If Bazel prints the path of the current directory, you're good to go! If the | |
| `WORKSPACE` file does not exist, you may see an error message like: | |
| ``` | |
| ERROR: The 'info' command is only supported from within a workspace. | |
| ``` | |
| ## Integrate with the Android SDK | |
| Bazel needs to run the Android SDK [build | |
| tools](https://developer.android.com/tools/revisions/build-tools.html) to build | |
| the app. This means that you need to add some information to your `WORKSPACE` | |
| file so that Bazel knows where to find them. | |
| Add the following line to your `WORKSPACE` file: | |
| ```python | |
| android_sdk_repository(name = "androidsdk") | |
| ``` | |
| This will use the Android SDK at the path referenced by the `ANDROID_HOME` | |
| environment variable, and automatically detect the highest API level and the | |
| latest version of build tools installed within that location. | |
| You can set the `ANDROID_HOME` variable to the location of the Android SDK. Find | |
| the path to the installed SDK using Android Studio's [SDK | |
| Manager](https://developer.android.com/studio/intro/update#sdk-manager). | |
| For example, as the default SDK path is in your home directory for Linux and | |
| macOS, and `LOCALAPPDATA` for Windows, you can use the following commands to set | |
| the `ANDROID_HOME` variable: | |
| | Linux, macOS | `export ANDROID_HOME=$HOME/Android/Sdk/` | | |
| | Windows (Command Prompt) | `set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk` | | |
| | Windows (PowerShell) | `$env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk"` | | |
| The above commands set the variable only for the current shell session. To make | |
| them permanent, run the following commands: | |
| | Linux, macOS | `echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc` | | |
| | Windows (Command Prompt) | `setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk"` | | |
| | Windows (PowerShell) | `[System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User)` | | |
| You can also explicitly specify the absolute path of the Android SDK, | |
| the API level, and the version of build tools to use by including the `path`, | |
| `api_level`, and `build_tools_version` attributes. If `api_level` and | |
| `build_tools_version` are not specified, the `android_sdk_repository` rule will | |
| use the respective latest version available in the SDK. You can specify any | |
| combination of these attributes, as long as they are present in the SDK, for | |
| example: | |
| ```python | |
| android_sdk_repository( | |
| name = "androidsdk", | |
| path = "/path/to/Android/sdk", | |
| api_level = 25, | |
| build_tools_version = "26.0.1" | |
| ) | |
| ``` | |
| On Windows, note that the `path` attribute must use the mixed-style path, that | |
| is, a Windows path with forward slashes: | |
| ```python | |
| android_sdk_repository( | |
| name = "androidsdk", | |
| path = "c:/path/to/Android/sdk", | |
| ) | |
| ``` | |
| **Optional:** If you want to compile native code into your Android app, you | |
| also need to download the [Android | |
| NDK](https://developer.android.com/ndk/downloads/index.html) | |
| and tell Bazel where to find it by adding the following line to your `WORKSPACE` file: | |
| ```python | |
| android_ndk_repository(name = "androidndk") | |
| ``` | |
| Similar to `android_sdk_repository`, the path to the Android NDK is inferred | |
| from the `ANDROID_NDK_HOME` environment variable by default. The path can also | |
| be explicitly specified with a `path` attribute on `android_ndk_repository`. | |
| For more information, read [Using the Android Native Development Kit with | |
| Bazel](../android-ndk.html). | |
| `api_level` is the version of the Android API that the SDK and NDK | |
| target - for example, 23 for Android 6.0 and 25 for Android 7.1. If not | |
| explicitly set, `api_level` defaults to the highest available API level for | |
| `android_sdk_repository` and `android_ndk_repository`. | |
| It's not necessary to set the API levels to the same value for the SDK and NDK. | |
| [This page](https://developer.android.com/ndk/guides/stable_apis.html) contains | |
| a map from Android releases to NDK-supported API levels. | |
| ## Create a BUILD file | |
| A [`BUILD` file](../build-ref.html#BUILD_files) describes the relationship | |
| between a set of build outputs, like compiled Android resources from `aapt` or | |
| class files from `javac`, and their dependencies. These dependencies may be | |
| source files (Java, C++) in your workspace or other build outputs. `BUILD` files | |
| are written in a language called **Starlark**. | |
| `BUILD` files are part of a concept in Bazel known as the *package hierarchy*. | |
| The package hierarchy is a logical structure that overlays the directory | |
| structure in your workspace. Each [package](../build-ref.html#packages) is a | |
| directory (and its subdirectories) that contains a related set of source files | |
| and a `BUILD` file. The package also includes any subdirectories, excluding | |
| those that contain their own `BUILD` file. The *package name* is the path to the | |
| `BUILD` file relative to the `WORKSPACE`. | |
| Note that Bazel's package hierarchy is conceptually different from the Java | |
| package hierarchy of your Android App directory where the `BUILD` file is | |
| located. , although the directories may be organized identically. | |
| For the simple Android app in this tutorial, the source files in `src/main/` | |
| comprise a single Bazel package. A more complex project may have many nested | |
| packages. | |
| ### Add an android_library rule | |
| A `BUILD` file contains several different types of declarations for Bazel. The | |
| most important type is the [build rule](../build-ref.html#funcs), which tells | |
| Bazel how to build an intermediate or final software output from a set of source | |
| files or other dependencies. | |
| Bazel provides two build rules, `android_library` and `android_binary`, that you | |
| can use to build an Android app. For this tutorial, you'll first use the | |
| [`android_library`](../be/android.html#android_library) rule to tell Bazel to | |
| build an [Android library | |
| module](http://developer.android.com/tools/projects/index.html#LibraryProjects) | |
| from the app source code and resource files. You'll then use the | |
| `android_binary` rule to tell Bazel how to build the Android application package. | |
| Create a new `BUILD` file in the `src/main/java/com/example/bazel` directory, | |
| and declare a new `android_library` target: | |
| `src/main/java/com/example/bazel/BUILD`: | |
| ```python | |
| package( | |
| default_visibility = ["//src:__subpackages__"], | |
| ) | |
| android_library( | |
| name = "greeter_activity", | |
| srcs = [ | |
| "Greeter.java", | |
| "MainActivity.java", | |
| ], | |
| manifest = "AndroidManifest.xml", | |
| resource_files = glob(["res/**"]), | |
| ) | |
| ``` | |
| The `android_library` build rule contains a set of attributes that specify the | |
| information that Bazel needs to build a library module from the source files. | |
| Note also that the name of the rule is `greeter_activity`. You'll reference the | |
| rule using this name as a dependency in the `android_binary` rule. | |
| ### Add an android_binary rule | |
| The [`android_binary`](../be/android.html#android_binary) rule builds | |
| the Android application package (`.apk` file) for your app. | |
| Create a new `BUILD` file in the `src/main/` directory, | |
| and declare a new `android_binary` target: | |
| `src/main/BUILD`: | |
| ```python | |
| android_binary( | |
| name = "app", | |
| manifest = "AndroidManifest.xml", | |
| deps = ["//src/main/java/com/example/bazel:greeter_activity"], | |
| ) | |
| ``` | |
| Here, the `deps` attribute references the output of the `greeter_activity` rule | |
| you added to the `BUILD` file above. This means that when Bazel builds the | |
| output of this rule it checks first to see if the output of the | |
| `greeter_activity` library rule has been built and is up-to-date. If not, Bazel | |
| builds it and then uses that output to build the application package file. | |
| Now, save and close the file. | |
| ## Build the app | |
| Let's try building the app! Run the following command to build the | |
| `android_binary` target: | |
| ```bash | |
| bazel build //src/main:app | |
| ``` | |
| The [`build`](../user-manual.html#build) subcommand instructs Bazel to build the | |
| target that follows. The target is specified as the name of a build rule inside | |
| a `BUILD` file, with along with the package path relative to your workspace | |
| directory. For this example, the target is `app` and the package path is | |
| `//src/main/`. | |
| Note that you can sometimes omit the package path or target name, depending on | |
| your current working directory at the command line and the name of the target. | |
| See [Labels](../build-ref.html#labels) in the *Bazel Concepts and Terminology* | |
| page for more information about target labels and paths. | |
| Bazel will start to build the sample app. During the build process, its output | |
| will appear similar to the following: | |
| ```bash | |
| INFO: Analysed target //src/main:app (0 packages loaded, 0 targets configured). | |
| INFO: Found 1 target... | |
| Target //src/main:app up-to-date: | |
| bazel-bin/src/main/app_deploy.jar | |
| bazel-bin/src/main/app_unsigned.apk | |
| bazel-bin/src/main/app.apk | |
| ``` | |
| ## Locate the build outputs | |
| Bazel puts the outputs of both intermediate and final build operations in a set | |
| of per-user, per-workspace output directories. These directories are symlinked | |
| from the following locations at the top-level of the project directory, where | |
| the `WORKSPACE` is: | |
| * `bazel-bin` stores binary executables and other runnable build outputs | |
| * `bazel-genfiles` stores intermediary source files that are generated by | |
| Bazel rules | |
| * `bazel-out` stores other types of build outputs | |
| Bazel stores the Android `.apk` file generated using the `android_binary` rule | |
| in the `bazel-bin/src/main` directory, where the subdirectory name `src/main` is | |
| derived from the name of the Bazel package. | |
| At a command prompt, list the contents of this directory and find the `app.apk` | |
| file: | |
| | Linux, macOS | `ls bazel-bin/src/main` | | |
| | Windows (Command Prompt) | `dir bazel-bin\src\main` | | |
| | Windows (PowerShell) | `ls bazel-bin\src\main` | | |
| ## Run the app | |
| You can now deploy the app to a connected Android device or emulator from the | |
| command line using the [`bazel | |
| mobile-install`](../user-manual.html#mobile-install) command. This command uses | |
| the Android Debug Bridge (`adb`) to communicate with the device. You must set up | |
| your device to use `adb` following the instructions in [Android Debug | |
| Bridge](http://developer.android.com/tools/help/adb.html) before deployment. You | |
| can also choose to install the app on the Android emulator included in Android | |
| Studio. Make sure the emulator is running before executing the command below. | |
| Enter the following: | |
| ```bash | |
| bazel mobile-install //src/main:app | |
| ``` | |
| Next, find and launch the "Bazel Tutorial App", which looks as follows: | |
| <img src="/assets/android_tutorial_before.png" alt="screenshot of tutorial app" width="500"> | |
| **Congratulations! You have just installed your first Bazel-built Android app.** | |
| Note that the `mobile-install` subcommand also supports the | |
| [`--incremental`](../user-manual.html#mobile-install) flag that can be used to | |
| deploy only those parts of the app that have changed since the last deployment. | |
| It also supports the `--start_app` flag to start the app immediately upon | |
| installing it. | |
| ## Review your work | |
| In this tutorial, you used Bazel to build an Android app. To accomplish that, | |
| you: | |
| * Set up your environment by installing Bazel and Android Studio, and | |
| downloading the sample project. | |
| * Set up a Bazel [workspace](../be/workspace.md) that contains the source code | |
| for the app and a `WORKSPACE` file that identifies the top level of the | |
| workspace directory. | |
| * Updated the `WORKSPACE` file to contain references to the required | |
| external dependencies, like the Android SDK. | |
| * Created a `BUILD` file. | |
| * Built the app with Bazel. | |
| * Deployed and ran the app on an Android emulator or physical device. | |
| ## Further reading | |
| You now know the basics of building an Android project with Bazel. Here are some | |
| other pages to check out: | |
| * More information on [mobile-install](../mobile-install.md) | |
| * Integrate external dependencies like AppCompat, Guava and JUnit from Maven | |
| repositories using [rules_jvm_external](https://github.com/bazelbuild/rules_jvm_external) | |
| * Run Robolectric tests with the [robolectric-bazel](https://github.com/robolectric/robolectric-bazel) | |
| integration. | |
| * Testing your app with [Android instrumentation tests](../android-instrumentation-test.md) | |
| * Integrating C and C++ code into your Android app with the [NDK](../android-ndk.md) | |
| * See more Bazel example projects of: | |
| * [a Kotlin app](https://github.com/bazelbuild/rules_jvm_external/tree/master/examples/android_kotlin_app) | |
| * [Robolectric testing](https://github.com/bazelbuild/rules_jvm_external/tree/master/examples/android_local_test) | |
| * [Espresso testing](https://github.com/bazelbuild/rules_jvm_external/tree/master/examples/android_instrumentation_test) | |
| Happy building! |