Bazel 教學課程:建構 Android 應用程式

回報問題 查看原始碼

注意:使用 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.xmlsrc/main/java/com/example/bazel/AndroidManifest.xml
Android 來源檔案 src/main/java/com/example/bazel/MainActivity.javaGreeter.java
資源檔案目錄 src/main/java/com/example/bazel/res/

使用 Bazel 進行建構

設定工作區

「工作區」是一個目錄,包含一或多個軟體專案的來源檔案,且其根目錄中有一個 WORKSPACE 檔案。

WORKSPACE 檔案可能是空白檔案,或含有建構專案所需的外部依附元件參照。

首先,請執行下列指令來建立空白的 WORKSPACE 檔案:

OS 指令
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 變數:

OS 指令
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"

上述指令只會為目前的殼層工作階段設定變數。如要將這些值區設為永久性,請執行下列指令:

OS 指令
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)

您也可以加入 pathapi_levelbuild_tools_version 屬性,明確指定 Android SDK 的絕對路徑、API 級別和建構工具版本。如未指定 api_levelbuild_tools_versionandroid_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 屬性明確指定路徑。

詳情請參閱搭配 Bazel 使用 Android Native Development Kit

api_level 是 SDK 和 NDK 目標的 Android API 版本,例如 Android 6.0 為 23,Android 7.1 為 25。如未明確設定,api_level 會預設為 android_sdk_repositoryandroid_ndk_repository 可用的最高 API 級別。

您不需要為 SDK 和 NDK 將 API 級別設為相同的值。 本頁面提供從 Android 版本到支援 NDK 的 API 級別的對應圖。

建立 BUILD 檔案

BUILD 檔案會說明一組建構輸出內容之間的關係,例如 aapt 的編譯 Android 資源或 javac 的類別檔案及其依附元件。這些依附元件可能是工作區或其他建構輸出內容的來源檔案 (Java、C++)。BUILD 檔案是以 Starlark 這個語言編寫。

BUILD 檔案是 Bazel 概念的一部分,稱為套件階層。套件階層是一種邏輯結構,會重疊在工作區的目錄結構。每個套件都是一個目錄 (及其子目錄),包含一組相關的來源檔案和 BUILD 檔案。套件也包含任何子目錄,但不包括內含其 BUILD 檔案的子目錄。套件名稱BUILD 檔案相對於 WORKSPACE 的路徑。

請注意,Bazel 的套件階層在概念上與 BUILD 檔案所在的 Android 應用程式目錄 (Java 套件階層) 不同,但目錄的整理方式可能相同。

以本教學課程中的簡易 Android 應用程式來說,src/main/ 中的來源檔案會包含單一 Bazel 套件。較為複雜的專案可能會有多個巢狀套件。

新增 android_library 規則

BUILD 檔案包含多種不同類型的 Bazel 宣告,其中最重要的類型是建構規則,可指示 Bazel 如何從一組來源檔案或其他依附元件建構中繼或最終軟體輸出內容。Bazel 提供 android_libraryandroid_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 屬性會參照您在上述 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 檔案:

OS 指令
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 偵錯橋接器中的操作說明設定裝置使用 adb。您也可以選擇在 Android Studio 的 Android Emulator 上安裝應用程式。請先確認模擬器正在執行,再執行下列指令。

輸入下列指令:

bazel mobile-install //src/main:app

接著,請找出並啟動「Bazel 教學課程應用程式」:

Bazel 教學課程應用程式

圖 2. Bazel 教學課程應用程式。

恭喜!您已安裝第一個 Bazel 建構的 Android 應用程式。

請注意,mobile-install 子指令也支援 --incremental 旗標,可用於僅部署應用程式自上次部署後變更的部分。

此程式庫也支援 --start_app 旗標,以便在安裝後立即啟動應用程式。

其他資訊

如需詳細資訊,請參閱以下頁面:

祝你建造愉快!