aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/docs/tutorial/android-app.md
blob: 20db3e2ac81f787ba728d3e50f96a16bd5798244 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
---
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. You'll do
the following:

*   [Set up your environment](#set-up-your-environment)
    *   [Install Bazel](#install-bazel)
    *   [Install Android Studio](#install-android-studio)
    *   [Get the sample project](#get-the-sample-project)
*   [Set up a workspace](#set-up-a-workspace)
    *   [Create a WORKSPACE file](#create-a-workspace-file)
    *   [Update the WORKSPACE file](#update-the-workspace-file)
*   [Review the source files](#review-the-source-files)
*   [Create a BUILD file](#create-a-build-file)
    *   [Add an android_library rule](#add-an-android_library-rule)
    *   [Add an android_binary rule](#add_an-android_binary-rule)
*   [Build the app](#build-the-app)
*   [Find the build outputs](#find-the-build-outputs)
*   [Run the app](#run-the-app)
*   [Review  your work](#review-your-work)

## Set up your environment

To get started, install Bazel and Android Studio, and get the sample project.

### Install Bazel

Follow the [installation instructions](../install.md) to install Bazel and
its dependencies.

### Install Android Studio

Download and install Android Studio as described in [Install Android Studio](https://developer.android.com/sdk/index.html).

The installer does not automatically set the `ANDROID_HOME` variable.
Set it to the location of the Android SDK, which defaults to `$HOME/Android/Sdk/`
.

For example:

`export ANDROID_HOME=$HOME/Android/Sdk/`

For convenience, add the above statement to your `~/.bashrc` file.

### Get the sample project

You also need to get the sample project for the tutorial from GitHub. The repo
has two branches: `source-only` and `master`. The `source-only` branch contains
the source files for the project only. You'll use the files in this branch in
this tutorial. The `master` branch contains both the source files and completed
Bazel `WORKSPACE` and `BUILD` files. You can use the files in this branch to
check your work when you've completed the tutorial steps.

Enter the following at the command line to get the files in the `source-only`
branch:

```bash
cd $HOME
git clone -b source-only https://github.com/bazelbuild/examples
```

The `git clone` command creates a directory named `$HOME/examples/`. This
directory contains several sample projects for Bazel. The project files for this
tutorial are in `$HOME/examples/tutorial/android`.

## Set up a workspace

A [workspace](../build-ref.html#workspaces) is a directory that contains the
source files for one or more software projects, as well as a `WORKSPACE` file
and `BUILD` files that contain the instructions that Bazel uses to build
the software. The workspace may also contain symbolic links to output
directories.

A workspace directory can be located anywhere on your filesystem and is denoted
by the presence of the `WORKSPACE` file at its root. In this tutorial, your
workspace directory is `$HOME/examples/tutorial/`, which contains the sample
project files you cloned from the GitHub repo in the previous step.

Note that Bazel itself doesn't make any requirements about how you organize
source files in your workspace. The sample source files in this tutorial are
organized according to conventions for the target platform.

For your convenience, set the `$WORKSPACE` environment variable now to refer to
your workspace directory. At the command line, enter:

```bash
export WORKSPACE=$HOME/examples/tutorial
```

### Create a WORKSPACE file

Every workspace must have a text file named `WORKSPACE` located in the top-level
workspace directory. This file may be empty or it may contain references
to [external dependencies](../external.html) required to build the
software.

For now, you'll create an empty `WORKSPACE` file, which simply serves to
identify the workspace directory. In later steps, you'll update the file to add
external dependency information.

Enter the following at the command line:

```bash
touch $WORKSPACE/WORKSPACE
```
This creates the empty `WORKSPACE` file.

### Update the WORKSPACE file

Bazel needs to run the Android SDK
[build tools](https://developer.android.com/tools/revisions/build-tools.html)
and uses the SDK libraries 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.  Note that this step is not required when you build for other platforms.
For example, Bazel automatically detects the location of Java, C++ and
Objective-C compilers from settings in your environment.

Add the following lines to your `WORKSPACE` file:

```python
android_sdk_repository(
    name = "androidsdk"
)
```

This will use the Android SDK 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.

Alternatively, you can explicitly specify the location 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. You can specify any
subset of these attributes:

```python
android_sdk_repository(
    name = "androidsdk",
    path = "/path/to/Android/sdk",
    api_level = 25,
    build_tools_version = "26.0.1"
)
```

**Optional:** This is not required by this tutorial, but 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 rule to your `WORKSPACE`
file:

```python
android_ndk_repository(
    name = "androidndk"
)
```

`api_level` is the version of the Android API the SDK and the NDK target
(for example, 23 for Android 6.0 and 25 for Android 7.1). If not explicitly
set, `api_level` will default 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 web page](https://developer.android.com/ndk/guides/stable_apis.html)
contains a map from Android releases to NDK-supported API levels.

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`.

## Review the source files

Let's take a look at the source files for the app. These are located in
`$WORKSPACE/android/`.

The key files and directories are:

<table class="table table-condensed table-striped">
<thead>
<tr>
<td>Name</td>
<td>Location</td>
</tr>
</thead>
<tbody>
<tr>
<td>Manifest file</td>
<td><code>src/main/java/com/google/bazel/example/android/AndroidManifest.xml</code></td>
</tr>
<tr>
<td>Activity source file</td>
<td><code>src/main/java/com/google/bazel/example/android/activities/MainActivity.java</code></td>
</tr>
<tr>
<td>Resource file directory</td>
<td><code>src/main/java/com/google/bazel/example/android/res/</code></td>
</tr>
</tbody>
</table>

Note that you're just looking at these files now to become familiar with the
structure of the app. You don't have to edit any of the source files to complete
this tutorial.

## Create a BUILD file

A [`BUILD` file](../build-ref.html#BUILD_files) is a text file that describes
the relationship between a set of build outputs -- for example, compiled
software libraries or executables -- and their dependencies. These dependencies
may be source files in your workspace or other build outputs. `BUILD` files are
written in the Bazel *build language*.

`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 name of the
directory where the `BUILD` file is located.

Note that this package hierarchy is distinct from, but coexists with, the Java
package hierarchy for your Android app.

For the simple Android app in this tutorial, we'll consider all the source files
in `$WORKSPACE/android/` to comprise a single Bazel package. A more complex
project may have many nested packages.

At a command-line prompt, open your new `BUILD` file for editing:

```bash
vi $WORKSPACE/android/BUILD
```

### Add an android_library rule

A `BUILD` file contains several different types of instructions 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 how to build an
[Android library module](http://developer.android.com/tools/projects/index.html#LibraryProjects)
from the app source code and resource files. Then you'll use the
`android_binary` rule to tell it how to build the Android application package.

Add the following to your `BUILD` file:

```python
android_library(
  name = "activities",
  srcs = glob(["src/main/java/com/google/bazel/example/android/activities/*.java"]),
  custom_package = "com.google.bazel.example.android.activities",
  manifest = "src/main/java/com/google/bazel/example/android/activities/AndroidManifest.xml",
  resource_files = glob(["src/main/java/com/google/bazel/example/android/activities/res/**"]),
)
```

As you can see, 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 `activities`. 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.

Add the following to your build file:

```python
android_binary(
    name = "android",
    custom_package = "com.google.bazel.example.android",
    manifest = "src/main/java/com/google/bazel/example/android/AndroidManifest.xml",
    resource_files = glob(["src/main/java/com/google/bazel/example/android/res/**"]),
    deps = [":activities"],
)
```

Here, the `deps` attribute references the output of the `activities` 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 `activities` library
rule has been built and is up-to-date. If not, it builds it and then uses that
output to build the application package file.

Now, save and close the file. You can compare your `BUILD` file to the
[completed example](https://github.com/bazelbuild/examples/blob/master/tutorial/android/BUILD)
in the `master` branch of the GitHub repo.

## Build the app

You use the
[`bazel`](../user-manual.html) command-line tool to run builds, execute
unit tests and perform other operations in Bazel. This tool is located in the
`output` subdirectory of the location where you installed Bazel. During
[installation](../install.md), you probably added this location to your
path.

Before you build the sample app, make sure that your current working directory
is inside your Bazel workspace:

```bash
cd $WORKSPACE
```

Now, enter the following to build the sample app:

```bash
bazel build //android:android
```

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. 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 now launches and builds the sample app. During the build process, its
output will appear similar to the following:

```bash
INFO: Found 1 target...
Target //android:android up-to-date:
  bazel-bin/android/android_deploy.jar
  bazel-bin/android/android_unsigned.apk
  bazel-bin/android/android.apk
INFO: Elapsed time: 7.237s, Critical Path: 5.81s
```

## Find the build outputs

Bazel stores 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:

* `$WORKSPACE/bazel-bin`, which stores binary executables and other runnable
   build outputs
* `$WORKSPACE/bazel-genfiles`, which stores intermediary source files that are
   generated by Bazel rules
* `$WORKSPACE/bazel-out`, which stores other types of build outputs

Bazel stores the Android `.apk` file generated using the `android_binary` rule
in the `bazel-bin/android/` directory, where the subdirectory name `android` is
derived from the name of the Bazel package.

At a command prompt, list the contents of this directory and find the
`android.apk` file:

```bash
ls $WORKSPACE/bazel-bin/android
```

## Run the app

**NOTE:** The app launches standalone but requires a backend server in order to
produce output. See the README file in the sample project directory to find out
how to build the backend server.

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 //android:android
```

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.

## 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](workspace.md) that contained 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
*   Created a `BUILD` file
*   Ran Bazel to build the app
*   Deployed and ran the app on an Android emulator and device

The built app is located in the `$WORKSPACE/bazel-bin` directory.

Note that completed `WORKSPACE` and `BUILD` files for this tutorial are located
in the
[master branch](https://github.com/bazelbuild/examples/tree/master/tutorial)
of the GitHub repo. You can compare your work to the completed files for
additional help or troubleshooting.