aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/versions/master/docs/tutorial/android-app.md
blob: dcb837696f9b63622f243a2c6af5b44c64276c21 (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
---
layout: documentation
title: Tutorial - Build an Android App
---

# Tutorial - Build an Android App

The sample Android app in this tutorial is a very simple application that makes
an HTTP connection to the [backend server](backend-server.md) and displays the
resulting response.

Here, you'll do the following:

*   Review the source files for the app
*   Update the `WORKSPACE` file
*   Create a `BUILD` file
*   Run the build
*   Find the build outputs
*   Run the app

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

## 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",
    # Replace with path to Android SDK on your system
    path = "/Users/username/Library/Android/sdk",
    # Replace with the Android SDK API level
    api_level = 23,
    # Replace with the version in sdk/build-tools/
    build_tools_version="23.0.0"
)
```

**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",
    # Replace with path to Android NDK on your system
    path = "/Users/username/Library/Android/ndk",
    # Replace with the Android NDK API level
    api_level = 21
)
```

`api_level` is the version of the Android API the SDK and the NDK target
(for example, 19 for Android K and 21 for Android L). 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.

## Create a BUILD file

A [`BUILD` file](/docs/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 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](/docs/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](/docs/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`](/docs/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`](/docs/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.

## Run the build

You use the
[`bazel`](/docs/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](/docs/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`](/docs/bazel-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](/docs/build-ref.html#labels) in
*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

You can now deploy the app to a connected Android device or emulator from the
command line using the
[`bazel mobile-install`](http://bazel.build/docs/bazel-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.

Enter the following:

```bash
$ bazel mobile-install //android:android
```

Note that the `mobile-install` subcommand also supports the
[`--incremental`](http://bazel.build/docs/bazel-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.

## What's next

Now that you've built a sample app for Android, it's time to do the same for
the [iOS app](ios-app.md).