Hướng dẫn này trình bày cách tạo một ứng dụng Android đơn giản bằng Bazel.
Bazel hỗ trợ việc tạo ứng dụng Android bằng quy tắc Android.
Hướng dẫn này dành cho người dùng Windows, macOS và Linux và không yêu cầu kinh nghiệm về việc phát triển ứng dụng Android hoặc Bazel. Bạn không cần viết bất kỳ mã Android nào trong hướng dẫn này.
Kiến thức bạn sẽ học được
Trong hướng dẫn này, bạn sẽ tìm hiểu cách:
- Thiết lập môi trường bằng cách cài đặt Bazel và Android Studio, đồng thời tải dự án mẫu xuống.
- Thiết lập không gian làm việc Bazel chứa mã nguồn cho ứng dụng và tệp
WORKSPACE
xác định cấp cao nhất của thư mục không gian làm việc. - Cập nhật tệp
WORKSPACE
để chứa các tệp tham chiếu đến các phần phụ thuộc bên ngoài bắt buộc, chẳng hạn như SDK Android. - Tạo tệp
BUILD
. - Tạo ứng dụng bằng Bazel.
- Triển khai và chạy ứng dụng trên trình mô phỏng Android hoặc thiết bị thực.
Trước khi bắt đầu
Cài đặt Bazel
Trước khi bắt đầu hướng dẫn, hãy cài đặt phần mềm sau:
- Bazel. Để cài đặt, hãy làm theo hướng dẫn cài đặt.
- Android Studio. Để cài đặt, hãy làm theo các bước tải Android Studio xuống. Thực thi trình hướng dẫn thiết lập để tải SDK xuống và định cấu hình môi trường của bạn.
- (Không bắt buộc) Git. Sử dụng
git
để tải dự án ứng dụng Android xuống.
Tải dự án mẫu
Đối với dự án mẫu, hãy sử dụng một dự án ứng dụng Android cơ bản trong kho lưu trữ ví dụ của Bazel.
Ứng dụng này có một nút duy nhất in lời chào khi được nhấp vào:
Hình 1. Lời chào trên nút ứng dụng Android.
Sao chép kho lưu trữ bằng git
(hoặc tải tệp ZIP xuống trực tiếp):
git clone https://github.com/bazelbuild/examples
Dự án mẫu cho hướng dẫn này nằm trong examples/android/tutorial
. Trong phần còn lại của hướng dẫn, bạn sẽ thực thi các lệnh trong thư mục này.
Xem lại các tệp nguồn
Hãy xem các tệp nguồn của ứng dụng.
.
├── 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
Các tệp và thư mục chính là:
Tên | Vị trí |
---|---|
Tệp kê khai Android | src/main/AndroidManifest.xml và src/main/java/com/example/bazel/AndroidManifest.xml |
Tệp nguồn Android | src/main/java/com/example/bazel/MainActivity.java và Greeter.java |
Thư mục tệp tài nguyên | src/main/java/com/example/bazel/res/ |
Tạo bằng Bazel
Thiết lập không gian làm việc
Không gian làm việc là một thư mục chứa các tệp nguồn cho một hoặc nhiều dự án phần mềm và có một tệp WORKSPACE
ở thư mục gốc.
Tệp WORKSPACE
có thể trống hoặc có thể chứa các tệp tham chiếu đến các phần phụ thuộc bên ngoài cần thiết để tạo dự án.
Trước tiên, hãy chạy lệnh sau để tạo tệp WORKSPACE
trống:
Hệ điều hành | Lệnh |
---|---|
Linux, macOS | touch WORKSPACE |
Windows (Command Prompt) | type nul > WORKSPACE |
Windows (PowerShell) | New-Item WORKSPACE -ItemType file |
Chạy Bazel
Giờ đây, bạn có thể kiểm tra xem Bazel có chạy đúng cách hay không bằng lệnh:
bazel info workspace
Nếu Bazel in đường dẫn của thư mục hiện tại, thì bạn đã sẵn sàng! Nếu tệp WORKSPACE
không tồn tại, bạn có thể thấy thông báo lỗi như sau:
ERROR: The 'info' command is only supported from within a workspace.
Tích hợp với SDK Android
Bazel cần chạy công cụ bản dựng SDK Android để tạo ứng dụng. Điều này có nghĩa là bạn cần thêm một số thông tin vào tệp WORKSPACE
để Bazel biết nơi tìm thấy các thông tin đó.
Thêm dòng sau vào tệp WORKSPACE
:
android_sdk_repository(name = "androidsdk")
Thao tác này sẽ sử dụng SDK Android tại đường dẫn được tham chiếu bởi biến môi trường ANDROID_HOME
và tự động phát hiện cấp độ API cao nhất cũng như phiên bản mới nhất của các công cụ xây dựng được cài đặt trong vị trí đó.
Bạn có thể đặt biến ANDROID_HOME
thành vị trí của SDK Android. Tìm đường dẫn đến SDK đã cài đặt bằng Trình quản lý SDK của Android Studio.
Giả sử SDK được cài đặt ở các vị trí mặc định, bạn có thể sử dụng các lệnh sau để đặt biến ANDROID_HOME
:
Hệ điều hành | Lệnh |
---|---|
Linux | export ANDROID_HOME=$HOME/Android/Sdk/ |
macOS | export ANDROID_HOME=$HOME/Library/Android/sdk |
Windows (Command Prompt) | set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk |
Windows (PowerShell) | $env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk" |
Các lệnh trên chỉ đặt biến cho phiên shell hiện tại. Để đặt các tuỳ chọn này thành vĩnh viễn, hãy chạy các lệnh sau:
Hệ điều hành | Lệnh |
---|---|
Linux | echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc |
macOS | echo "export ANDROID_HOME=$HOME/Library/Android/Sdk/" >> ~/.bashrc |
Windows (Command Prompt) | setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk" |
Windows (PowerShell) | [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User) |
Bạn cũng có thể chỉ định rõ ràng đường dẫn tuyệt đối của SDK Android, cấp độ API và phiên bản công cụ xây dựng cần sử dụng bằng cách thêm các thuộc tính path
, api_level
và build_tools_version
. Nếu bạn không chỉ định api_level
và build_tools_version
, thì quy tắc android_sdk_repository
sẽ sử dụng phiên bản mới nhất tương ứng có trong SDK. Bạn có thể chỉ định bất kỳ tổ hợp nào của các thuộc tính này, miễn là các thuộc tính đó có trong SDK, ví dụ:
android_sdk_repository(
name = "androidsdk",
path = "/path/to/Android/sdk",
api_level = 25,
build_tools_version = "30.0.3"
)
Trên Windows, lưu ý rằng thuộc tính path
phải sử dụng đường dẫn kiểu kết hợp, tức là đường dẫn Windows có dấu gạch chéo xuôi:
android_sdk_repository(
name = "androidsdk",
path = "c:/path/to/Android/sdk",
)
Không bắt buộc: Nếu muốn biên dịch mã gốc vào ứng dụng Android, bạn cũng cần tải Android NDK xuống và cho Bazel biết nơi tìm thấy mã đó bằng cách thêm dòng sau vào tệp WORKSPACE
:
android_ndk_repository(name = "androidndk")
Tương tự như android_sdk_repository
, đường dẫn đến Android NDK được suy ra từ biến môi trường ANDROID_NDK_HOME
theo mặc định. Bạn cũng có thể chỉ định đường dẫn một cách rõ ràng bằng thuộc tính path
trên android_ndk_repository
.
Để biết thêm thông tin, hãy đọc bài viết Sử dụng Bộ phát triển gốc Android với Bazel.
api_level
là phiên bản API Android mà SDK và NDK nhắm đến – ví dụ: 23 cho Android 6.0 và 25 cho Android 7.1. Nếu không được đặt rõ ràng, api_level
sẽ mặc định là cấp độ API cao nhất hiện có cho android_sdk_repository
và android_ndk_repository
.
Bạn không cần thiết lập các cấp độ API thành cùng một giá trị cho SDK và NDK. Trang này chứa bản đồ từ các bản phát hành Android đến các cấp độ API được NDK hỗ trợ.
Tạo tệp BUILD
Tệp BUILD
mô tả mối quan hệ giữa một tập hợp các đầu ra bản dựng, chẳng hạn như tài nguyên Android đã biên dịch từ aapt
hoặc tệp lớp từ javac
và các phần phụ thuộc của chúng. Các phần phụ thuộc này có thể là tệp nguồn (Java, C++) trong không gian làm việc hoặc các đầu ra bản dựng khác. Các tệp BUILD
được viết bằng một ngôn ngữ có tên là Starlark.
Tệp BUILD
là một phần của khái niệm trong Bazel được gọi là hệ phân cấp gói.
Hệ phân cấp gói là một cấu trúc logic phủ lên cấu trúc thư mục trong không gian làm việc của bạn. Mỗi gói là một thư mục (và các thư mục con của thư mục đó) chứa một nhóm tệp nguồn liên quan và một tệp BUILD
. Gói này cũng bao gồm mọi thư mục con, ngoại trừ những thư mục chứa tệp BUILD
riêng. Tên gói là đường dẫn đến tệp BUILD
so với WORKSPACE
.
Xin lưu ý rằng hệ phân cấp gói của Bazel về mặt khái niệm khác với hệ phân cấp gói Java của thư mục Ứng dụng Android nơi tệp BUILD
nằm, mặc dù các thư mục có thể được sắp xếp giống hệt nhau.
Đối với ứng dụng Android đơn giản trong hướng dẫn này, các tệp nguồn trong src/main/
bao gồm một gói Bazel duy nhất. Một dự án phức tạp hơn có thể có nhiều gói lồng nhau.
Thêm quy tắc android_library
Tệp BUILD
chứa một số loại khai báo khác nhau cho Bazel. Loại quan trọng nhất là quy tắc bản dựng. Quy tắc này cho Bazel biết cách tạo đầu ra phần mềm trung gian hoặc cuối cùng từ một nhóm tệp nguồn hoặc các phần phụ thuộc khác. Bazel cung cấp hai quy tắc xây dựng, android_library
và android_binary
, mà bạn có thể sử dụng để tạo ứng dụng Android.
Trong hướng dẫn này, trước tiên, bạn sẽ sử dụng quy tắc android_library
để yêu cầu Bazel tạo một mô-đun thư viện Android từ mã nguồn ứng dụng và tệp tài nguyên. Sau đó, bạn sẽ sử dụng quy tắc android_binary
để cho Bazel biết cách tạo gói ứng dụng Android.
Tạo một tệp BUILD
mới trong thư mục src/main/java/com/example/bazel
và khai báo một mục tiêu android_library
mới:
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/**"]),
)
Quy tắc bản dựng android_library
chứa một tập hợp các thuộc tính chỉ định thông tin mà Bazel cần để tạo mô-đun thư viện từ các tệp nguồn.
Ngoài ra, hãy lưu ý rằng tên của quy tắc là greeter_activity
. Bạn sẽ tham chiếu quy tắc bằng cách sử dụng tên này làm phần phụ thuộc trong quy tắc android_binary
.
Thêm quy tắc android_binary
Quy tắc android_binary
sẽ tạo gói ứng dụng Android (tệp .apk
) cho ứng dụng của bạn.
Tạo một tệp BUILD
mới trong thư mục src/main/
và khai báo một mục tiêu android_binary
mới:
src/main/BUILD
:
android_binary(
name = "app",
manifest = "AndroidManifest.xml",
deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)
Ở đây, thuộc tính deps
tham chiếu đến kết quả của quy tắc greeter_activity
mà bạn đã thêm vào tệp BUILD
ở trên. Điều này có nghĩa là khi Bazel tạo đầu ra của quy tắc này, trước tiên, Bazel sẽ kiểm tra xem đầu ra của quy tắc thư viện greeter_activity
đã được tạo và cập nhật hay chưa. Nếu không, Bazel sẽ tạo tệp đó rồi sử dụng kết quả đó để tạo tệp gói ứng dụng.
Bây giờ, hãy lưu và đóng tệp.
Tạo ứng dụng
Hãy thử tạo ứng dụng! Chạy lệnh sau để tạo mục tiêu android_binary
:
bazel build //src/main:app
Lệnh con build
hướng dẫn Bazel tạo mục tiêu tiếp theo. Mục tiêu được chỉ định là tên của quy tắc bản dựng bên trong tệp BUILD
, cùng với đường dẫn gói tương ứng với thư mục không gian làm việc của bạn. Đối với ví dụ này, mục tiêu là app
và đường dẫn gói là //src/main/
.
Xin lưu ý rằng đôi khi bạn có thể bỏ qua đường dẫn gói hoặc tên mục tiêu, tuỳ thuộc vào thư mục đang hoạt động hiện tại của bạn tại dòng lệnh và tên của mục tiêu. Để biết thêm thông tin chi tiết về nhãn và đường dẫn mục tiêu, hãy xem phần Nhãn.
Bazel sẽ bắt đầu tạo ứng dụng mẫu. Trong quá trình tạo, kết quả sẽ xuất hiện tương tự như sau:
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
Tìm kết quả của bản dựng
Bazel đặt kết quả của cả thao tác bản dựng trung gian và cuối cùng trong một tập hợp thư mục đầu ra cho mỗi người dùng, mỗi không gian làm việc. Các thư mục này được liên kết tượng trưng từ các vị trí sau ở cấp cao nhất của thư mục dự án, trong đó WORKSPACE
là:
bazel-bin
lưu trữ các tệp thực thi nhị phân và các đầu ra bản dựng có thể chạy khácbazel-genfiles
lưu trữ các tệp nguồn trung gian do các quy tắc Bazel tạo rabazel-out
lưu trữ các loại đầu ra bản dựng khác
Bazel lưu trữ tệp .apk
Android được tạo bằng quy tắc android_binary
trong thư mục bazel-bin/src/main
, trong đó tên thư mục con src/main
được lấy từ tên của gói Bazel.
Tại lời nhắc lệnh, hãy liệt kê nội dung của thư mục này và tìm tệp app.apk
:
Hệ điều hành | Lệnh |
---|---|
Linux, macOS | ls bazel-bin/src/main |
Windows (Command Prompt) | dir bazel-bin\src\main |
Windows (PowerShell) | ls bazel-bin\src\main |
Chạy ứng dụng
Giờ đây, bạn có thể triển khai ứng dụng cho một trình mô phỏng hoặc thiết bị Android đã kết nối từ dòng lệnh bằng lệnh bazel
mobile-install
. Lệnh này sử dụng Cầu gỡ lỗi Android (adb
) để giao tiếp với thiết bị. Bạn phải thiết lập thiết bị để sử dụng adb
theo hướng dẫn trong Cầu gỡ lỗi Android trước khi triển khai. Bạn cũng có thể chọn cài đặt ứng dụng trên trình mô phỏng Android có trong Android Studio. Đảm bảo trình mô phỏng đang chạy trước khi thực thi lệnh bên dưới.
Nhập thông tin sau:
bazel mobile-install //src/main:app
Tiếp theo, hãy tìm và chạy "Ứng dụng hướng dẫn về Bazel":
Hình 2. Ứng dụng hướng dẫn về Bazel.
Xin chúc mừng! Bạn vừa cài đặt ứng dụng Android đầu tiên được tạo bằng Bazel.
Xin lưu ý rằng lệnh con mobile-install
cũng hỗ trợ cờ --incremental
. Bạn có thể dùng cờ này để chỉ triển khai những phần của ứng dụng đã thay đổi kể từ lần triển khai gần đây nhất.
Ứng dụng này cũng hỗ trợ cờ --start_app
để khởi động ứng dụng ngay sau khi cài đặt.
Tài liệu đọc thêm
Để biết thêm thông tin chi tiết, hãy xem các trang sau:
- Mở vấn đề trên GitHub
- Thông tin khác về mobile-install
- Tích hợp các phần phụ thuộc bên ngoài như AppCompat, Guava và JUnit từ các kho lưu trữ Maven bằng cách sử dụng rules_jvm_external
- Chạy các chương trình kiểm thử Robolectric bằng tính năng tích hợp robolectric-bazel.
- Kiểm thử ứng dụng bằng kiểm thử đo lường Android
- Tích hợp mã C và C++ vào ứng dụng Android bằng NDK
- Xem thêm các dự án mẫu Bazel về:
Chúc bạn xây dựng vui vẻ!