注意:使用 Bazel 建構 Android 應用程式時有一些已知的限制。請造訪 GitHub 的 team-Android 熱門清單,查看已知問題清單。雖然 Bazel 團隊和開放原始碼軟體 (OSS) 貢獻者積極解決已知問題,但使用者應注意,Android Studio 並未正式支援 Bazel 專案。
本教學課程將說明如何使用 Bazel 建構簡單的 Android 應用程式。
Bazel 支援使用 Android 規則建構 Android 應用程式。
本教學課程適用於 Windows、macOS 和 Linux 使用者,不需要具備 Bazel 或 Android 應用程式開發經驗。您不需要在本教學課程中編寫任何 Android 程式碼。
課程內容
在本教學課程中,您會瞭解如何執行下列作業:
- 請安裝 Bazel 和 Android Studio,然後下載範例專案,設定環境。
- 設定 Bazel 工作區,其中包含應用程式原始碼和
WORKSPACE
檔案,可識別工作區目錄的頂層。 - 更新
WORKSPACE
檔案,納入必要外部依附元件 (例如 Android SDK) 的參照。 - 建立
BUILD
檔案。 - 使用 Bazel 建構應用程式。
- 在 Android 模擬器或實體裝置上部署及執行應用程式。
事前準備
安裝 Bazel
開始本教學課程前,請先安裝下列軟體:
- Bazel。如要安裝,請按照安裝說明操作。
- Android Studio。如要安裝,請按照下載 Android Studio 的步驟操作。執行設定精靈,下載 SDK 並設定環境。
- (選用) Git。使用
git
下載 Android 應用程式專案。
取得範例專案
針對範例專案,請在 Bazel 的範例存放區中使用基本的 Android 應用程式專案。
這個應用程式只有一個按鈕,點選後會顯示問候語:
圖 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
檔案可能為空白,也可能包含建構專案所需的外部依附元件參照。
首先,請執行下列指令來建立空白的 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 Manager 找出已安裝 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" |
上述指令只會為目前的殼層工作階段設定變數。如要永久顯示這些資料,請執行下列指令:
作業系統 | 指令 |
---|---|
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) |
您也可以加入 path
、api_level
和 build_tools_version
屬性,明確指定 Android SDK 的絕對路徑、API 級別,以及要使用的建構工具版本。如未指定 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_HOME
環境變數推斷 Android NDK 的路徑。您也可以在 android_ndk_repository
上使用 path
屬性,明確指定路徑。
詳情請參閱「使用 Android Native Development Kit 搭配 Bazel」。
api_level
是 SDK 和 NDK 指定的 Android API 版本,例如 Android 6.0 為 23,Android 7.1 為 25。如未明確設定,api_level
會預設為 android_sdk_repository
和 android_ndk_repository
可用的最高 API 級別。
您不必將 SDK 和 NDK 的 API 級別設為相同值。這個頁面包含從 Android 版本到 NDK 支援 API 級別的對照表。
建立 BUILD 檔案
BUILD
檔案會說明一組建構輸出項目 (例如 aapt
中的編譯 Android 資源,或 javac
中的類別檔案) 與其依附元件之間的關係。這些依附元件可能是工作區或其他建構輸出的來源檔案 (Java、C++)。BUILD
檔案是以名為 Starlark 的語言編寫。
BUILD
檔案是 Bazel 中稱為套件階層的概念的一部分。套件階層是邏輯結構,會疊加工作區中的目錄結構。每個「套件」都是一個目錄 (及其子目錄),其中包含相關的來源檔案組合和 BUILD
檔案。套件也包含所有子目錄,不包括包含自己的 BUILD
檔案的子目錄。套件名稱是相對於 WORKSPACE
的 BUILD
檔案路徑。
請注意,Bazel 的套件階層在概念上與 Android 應用程式目錄的 Java 套件階層 (即 BUILD
檔案的所在位置) 不同,雖然目錄的整理方式可能相同。
針對本教學課程中的簡易 Android 應用程式,src/main/
中的來源檔案內含單一 Bazel 套件。較複雜的專案可能會有許多巢狀套件。
新增 android_library 規則
BUILD
檔案包含幾種不同類型的 Bazel 宣告。最重要的類型是建構規則,這會告知 Bazel 如何從一組來源檔案或其他依附元件建構中繼或最終軟體輸出。Bazel 提供兩個可用來建構 Android 應用程式的建構規則:android_library
和 android_binary
。
在本教學課程中,您會先使用 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
屬性會參照您在上述 BUILD
檔案中新增的 greeter_activity
規則輸出內容。換句話說,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
會儲存二進位可執行檔和其他可執行的建構輸出內容bazel-genfiles
會儲存由 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 裝置或模擬器。這個指令會使用 Android Debug Bridge (adb
) 與裝置通訊。您必須先按照 Android Debug Bridge 中的操作說明設定裝置,才能使用 adb
。您也可以選擇在 Android Studio 內附的 Android 模擬器上安裝應用程式。請先確認模擬器正在執行,再執行下列指令。
輸入下列指令:
bazel mobile-install //src/main:app
接著,尋找並啟動「Bazel Tutorial App」:
圖 2. Bazel 教學應用程式。
恭喜!您剛安裝第一個使用 Bazel 建構的 Android 應用程式。
請注意,mobile-install
子命令也支援 --incremental
標記,可用於只部署自上次部署以來已變更的應用程式部分。
它也支援使用 --start_app
標記,在安裝時立即啟動應用程式。
延伸閱讀
詳情請參閱下列頁面:
- 在 GitHub 上提出問題
- 進一步瞭解 mobile-install
- 使用 rules_jvm_external 整合來自 Maven 存放區的外部依附元件,例如 AppCompat、Guava 和 JUnit
- 使用 robolectric-bazel 整合執行 Robolectric 測試。
- 使用 Android 檢測設備測試測試應用程式
- 使用 NDK 將 C 和 C++ 程式碼整合至 Android 應用程式
- 查看更多下列 Bazel 專案範例:
祝您建構愉快!