注意:在使用 Bazel 构建 Android 应用时存在已知的限制。 如需查看已知问题的列表,请访问 GitHub team-Android 热门列表。虽然 Bazel 团队和开源软件 (OSS) 贡献者在积极解决已知问题,但用户应注意,Android Studio 并不正式支持 Bazel 项目。
本教程介绍了如何使用 Bazel 构建简单的 Android 应用。
Bazel 支持使用 Android 规则。
本教程适用于 Windows、macOS 和 Linux 用户, 需要有 Bazel 或 Android 应用开发经验。您无需 编写本教程中的任何 Android 代码。
学习内容
在本教程中,您将学习如何:
- 通过安装 Bazel 和 Android Studio 来设置环境,并且 下载示例项目。
- 设置包含源代码的 Bazel 工作区
一个
WORKSPACE
文件,用于标识应用的顶层 工作区目录中。 - 更新
WORKSPACE
文件以包含对所需 外部依赖项,例如 Android SDK - 创建
BUILD
文件。 - 使用 Bazel 构建应用。
- 在 Android 模拟器或实体设备上部署并运行应用。
准备工作
安装 Bazel
在开始学习本教程之前,请安装以下软件:
- Bazel。如需安装,请按照安装说明操作。
- Android Studio -若要安装,请按照下载 Android 应用的步骤操作 工作室。 执行设置向导,以下载 SDK 并配置您的环境。
- (可选)Git.使用
git
下载 Android 应用项目。
获取示例项目
对于示例项目,请使用 Bazel 的示例代码库。
此应用只有一个按钮,可在用户点击时输出问候语:
图 1. Android 应用按钮问候语。
使用 git
克隆代码库(或下载 ZIP 文件)
):
git clone https://github.com/bazelbuild/examples
本教程的示例项目位于 examples/android/tutorial
中。对于
您将在此目录中执行命令。
查看源文件
查看应用的源文件。
.
├── 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
关键文件和目录如下:
名称 | 位置 |
---|---|
Android 清单文件 | src/main/AndroidManifest.xml 和src/main/java/com/example/bazel/AndroidManifest.xml |
Android 源文件 | src/main/java/com/example/bazel/MainActivity.java 和Greeter.java |
资源文件目录 | src/main/java/com/example/bazel/res/ |
使用 Bazel 构建
设置工作区
工作区是一个目录,其中包含
一个或多个软件项目的源文件,并且 WORKSPACE
文件位于
其根。
WORKSPACE
文件可能为空,或可能包含对 external
所需的依赖项。
首先,运行以下命令创建一个空的 WORKSPACE
文件:
操作系统 | 命令 |
---|---|
Linux、macOS | touch WORKSPACE |
Windows(命令提示符) | type nul > WORKSPACE |
Windows (PowerShell) | New-Item WORKSPACE -ItemType file |
运行 Bazel
您现在可以使用以下命令检查 Bazel 是否正常运行:
bazel info workspace
如果 Bazel 输出了当前目录的路径,那就大功告成了!如果
WORKSPACE
文件不存在,您可能会看到如下错误消息:
ERROR: The 'info' command is only supported from within a workspace.
与 Android SDK 集成
Bazel 需要运行 Android SDK
构建工具
构建应用也就是说,您需要将一些信息添加到
WORKSPACE
文件,以便 Bazel 知道在哪里可以找到它们。
将以下行添加到 WORKSPACE
文件中:
android_sdk_repository(name = "androidsdk")
这将使用 ANDROID_HOME
引用的路径中的 Android SDK
环境变量,并自动检测最高 API 级别和
最新版本的构建工具。
您可以将 ANDROID_HOME
变量设置为 Android SDK 的位置。查找
使用 Android Studio 的 SDK 的已安装 SDK 的路径
管理员。
假设 SDK 安装到默认位置,您可以使用以下代码
设置 ANDROID_HOME
变量的命令:
操作系统 | 命令 |
---|---|
Linux | export ANDROID_HOME=$HOME/Android/Sdk/ |
macOS | export ANDROID_HOME=$HOME/Library/Android/sdk |
Windows(命令提示符) | set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk |
Windows (PowerShell) | $env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk" |
上述命令仅针对当前 shell 会话设置变量。为了让 它们是永久性的,请运行以下命令:
操作系统 | 命令 |
---|---|
Linux | echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc |
macOS | echo "export ANDROID_HOME=$HOME/Library/Android/Sdk/" >> ~/.bashrc |
Windows(命令提示符) | setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk" |
Windows (PowerShell) | [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User) |
您也可以明确指定 Android SDK 的绝对路径,
添加 path
,了解 API 级别和要使用的构建工具版本;
api_level
和 build_tools_version
属性。如果 api_level
且
build_tools_version
未指定,则android_sdk_repository
规则将
请使用 SDK 中提供的相应最新版本。您可以指定任何
只要这些属性出现在 SDK 中,您就可以随时使用它们
示例:
android_sdk_repository(
name = "androidsdk",
path = "/path/to/Android/sdk",
api_level = 25,
build_tools_version = "30.0.3"
)
请注意,在 Windows 上,path
属性必须使用混合样式路径,
是带有正斜杠的 Windows 路径:
android_sdk_repository(
name = "androidsdk",
path = "c:/path/to/Android/sdk",
)
可选:如果您要将原生代码编译到 Android 应用中,请执行以下操作:
还需要下载 Android
NDK
然后在 WORKSPACE
文件中添加以下这行代码,告诉 Bazel 在哪里可以找到它:
android_ndk_repository(name = "androidndk")
与 android_sdk_repository
类似,系统会推断 Android NDK 的路径
从 ANDROID_NDK_HOME
环境变量运行。路径还可以
使用 android_ndk_repository
的 path
属性明确指定。
有关详情,请参阅将 Android 原生开发套件与 Bazel。
api_level
是 SDK 和 NDK 的 Android API 版本
目标 - 例如,23 表示 Android 6.0,25 表示 Android 7.1。如果不是
api_level
默认为
android_sdk_repository
和android_ndk_repository
。
您无需为 SDK 和 NDK 将 API 级别设置为相同的值。 此页面 包含从 Android 版本到 NDK 支持的 API 级别的映射。
创建 BUILD 文件
BUILD
文件描述了
一组构建输出(例如来自 aapt
或
来自 javac
的类文件及其依赖项。这些依赖项可能
源文件(Java、C++)或其他构建输出。BUILD
个文件
都是用一种名为 Starlark 的语言编写的。
BUILD
文件是 Bazel 中一个名为“软件包层次结构”的概念的一部分。
软件包层次结构是叠加在目录之上的逻辑结构
结构。每个 package 都是一个
包含一组相关源文件的目录(及其子目录)
和 BUILD
文件。该包还包含除以下项之外的任何子目录:
那些包含自己的 BUILD
文件的对象。“package name”是
BUILD
文件(相对于 WORKSPACE
)。
请注意,Bazel 的软件包层次结构在概念上与 Java 中
BUILD
文件所在 Android 应用目录的软件包层次结构
但目录的结构可能完全相同。
对于本教程中的简单 Android 应用,src/main/
中的源文件
运行单个 Bazel 软件包更复杂的项目可能会有多个嵌套项。
软件包
添加 android_library 规则
BUILD
文件包含多种不同类型的 Bazel 声明。通过
最重要的类型是
build 规则,用于指示
Bazel 如何基于一组来源构建中间或最终软件输出
文件或其他依赖项Bazel 提供了两条构建规则
android_library
和
android_binary
,可用于
构建 Android 应用
在本教程中,您将首先使用
android_library
规则,指示 Bazel 构建 Android 库
模块
从应用源代码和资源文件获取。然后,您将使用
android_binary
规则,告知 Bazel 如何构建 Android 应用软件包。
在 src/main/java/com/example/bazel
目录中创建一个新的 BUILD
文件,
并声明一个新的 android_library
目标:
src/main/java/com/example/bazel/BUILD
:
package(
default_visibility = ["//src:__subpackages__"],
)
android_library(
name = "greeter_activity",
srcs = [
"Greeter.java",
"MainActivity.java",
],
manifest = "AndroidManifest.xml",
resource_files = glob(["res/**"]),
)
android_library
构建规则包含一组属性,用于指定
Bazel 从源文件构建库模块所需的信息。
另请注意,规则的名称为 greeter_activity
。您将引用
在 android_binary
规则中使用此名称作为依赖项的规则。
添加 android_binary 规则
android_binary
规则构建
应用的 Android 应用软件包(.apk
文件)。
在 src/main/
目录中创建一个新的 BUILD
文件,
并声明一个新的 android_binary
目标:
src/main/BUILD
:
android_binary(
name = "app",
manifest = "AndroidManifest.xml",
deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)
在这里,deps
属性引用了 greeter_activity
规则的输出
添加到上述 BUILD
文件中。这意味着,当 Bazel 构建
那么它首先会检查该规则的输出,
greeter_activity
库规则已构建且处于最新状态。如果没有,则使用 Bazel
构建应用,然后使用该输出构建应用软件包文件。
现在,保存并关闭该文件。
构建应用
尝试构建应用!运行以下命令以构建
android_binary
目标:
bazel build //src/main:app
build
子命令会指示 Bazel 构建
目标。目标被指定为其中某个构建规则的名称
一个 BUILD
文件,以及相对于工作区的软件包路径
目录。在此示例中,目标是 app
,软件包路径为
//src/main/
。
请注意,您有时可以省略软件包路径或目标名称,具体取决于 命令行中的当前工作目录以及目标的名称。 如需详细了解目标标签和路径,请参阅标签。
Bazel 将开始构建示例应用。在构建流程中 将如下所示:
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
找到构建输出
Bazel 会将中间构建操作和最终构建操作的输出
每个用户和每个工作区的输出目录数量。这些目录通过符号链接
项目目录顶层的以下位置,其中
WORKSPACE
为:
bazel-bin
存储二进制可执行文件和其他可运行 build 输出bazel-genfiles
存储由 Cloud SDK 生成的中间源文件 Bazel 规则bazel-out
存储其他类型的构建输出
Bazel 会存储使用 android_binary
规则生成的 Android .apk
文件
bazel-bin/src/main
目录中,子目录名称为 src/main
从 Bazel 软件包的名称派生而来。
在命令提示符处,列出此目录的内容并找到 app.apk
文件:
操作系统 | 命令 |
---|---|
Linux、macOS | ls bazel-bin/src/main |
Windows(命令提示符) | dir bazel-bin\src\main |
Windows (PowerShell) | ls bazel-bin\src\main |
运行应用
您现在可以通过
使用 bazel
mobile-install
命令创建命令行。此命令使用
Android 调试桥 (adb
) 以便与设备进行通信。您必须设置
您的设备按照 Android 调试中的说明使用 adb
在部署前建立桥接器。您
也可以选择在 Android 随附的 Android 模拟器上安装应用
Studio。在执行以下命令之前,请确保模拟器正在运行。
输入以下内容:
bazel mobile-install //src/main:app
接下来,找到并启动“Bazel 教程应用”:
图 2. Bazel 教程应用。
恭喜!您刚刚安装了您的第一个使用 Bazel 构建的 Android 应用。
请注意,mobile-install
子命令还支持
--incremental
标记,可用于
仅部署自上次部署以来发生更改的应用程序部分。
它还支持使用 --start_app
标志,以便在应用发生时立即启动应用
安装它。
深入阅读
如需了解详情,请参阅以下页面:
- GitHub 上的待解决问题
- 详细了解移动设备安装
- 从 Maven 集成外部依赖项,例如 AppCompat、Guava 和 JUnit 使用 rules_jvm_external 的代码库
- 使用 robolectric-bazel 运行 Robolectric 测试 集成。
- 使用 Android 插桩测试来测试您的应用
- 使用 NDK 将 C 和 C++ 代码集成到您的 Android 应用中
- 查看更多以下 Bazel 示例项目:
祝您构建顺利!