1. Trước khi bắt đầu
Trong lớp học lập trình này, bạn tìm hiểu cách xây dựng ứng dụng được tối ưu hoá để chống phân tâm dành cho Android Auto và Android Automotive OS bằng thư viện ứng dụng Android cho Ô tô (Android for Cars App Library). Trước tiên, bạn sẽ thêm khả năng hỗ trợ Android Auto, sau đó chỉ cần thực hiện thêm một vài việc như tạo một biến thể của ứng dụng có thể chạy trên Android Automotive OS. Sau khi ứng dụng này chạy được trên cả hai nền tảng, bạn sẽ xây dựng thêm một màn hình và một số hoạt động tương tác cơ bản!
Không bao gồm
- Hướng dẫn về cách tạo ứng dụng đa phương tiện (âm thanh) cho Android Auto và Android Automotive OS. Xem bài viết Tạo ứng dụng đa phương tiện cho ô tô để biết thông tin về cách tạo loại ứng dụng này.
- Hướng dẫn cách tạo ứng dụng nhắn tin cho Android Auto. Xem bài viết Tạo ứng dụng đa phương tiện cho Android Auto để biết thông tin về cách tạo loại ứng dụng này.
Bạn cần có
- Bản xem trước Android Studio Trình mô phỏng Android Automotive OS chỉ sử dụng được thông qua Bản xem trước Android Studio. Nếu chưa cài đặt Bản xem trước Android Studio, bạn có thể bắt đầu lớp học lập trình bằng bản phát hành ổn định trong khi tải phiên bản xem trước.
- Kinh nghiệm về Kotlin.
- Kinh nghiệm cơ bản về Các dịch vụ Android.
- Kinh nghiệm về tạo thiết bị Android ảo và chạy thiết bị ảo trong Trình mô phỏng Android.
- Kến thức cơ bản về Mô-đun hoá ứng dụng Android.
- Kiến thức cơ bản về Mẫu thiết kế dành cho trình tạo bản dựng.
Sản phẩm bạn sẽ tạo ra
Android Auto | Android Automotive OS |
Kiến thức bạn sẽ học được
- Cách hoạt động của kiến trúc ứng dụng lưu trữ-ứng dụng khách của Thư viện Ứng dụng cho Ô tô (Car App Library).
- Cách viết các lớp
CarAppService
,Session
vàScreen
của riêng bạn. - Cách chia sẻ phương thức triển khai của bạn trên cả Android Auto và Android Automotive OS.
- Cách chạy Android Auto trên máy phát triển của bạn qua Đầu phát trung tâm máy tính.
- Cách chạy trình mô phỏng Android Automotive OS.
2. Bắt đầu thiết lập
Lấy mã nguồn
- Bạn có thể tìm thấy đoạn mã dành cho lớp học lập trình này trong thư mục
car-app-library-fundamentals
trong kho lưu trữ GitHubcar-codelabs
. Để sao chép đoạn mã đó, hãy chạy lệnh sau:
git clone https://github.com/android/car-codelabs.git
- Ngoài ra, bạn có thể tải kho lưu trữ ở dạng định dạng tệp ZIP:
Mở dự án
- Sau khi chạy Android Studio, hãy nhập dự án, chỉ chọn thư mục
car-app-library-fundamentals/start
. Thư mụccar-app-library-fundamentals/end
chứa đoạn mã giải pháp mà bạn có thể tham khảo bất cứ lúc nào nếu gặp khó khăn hoặc đơn giản là xem toàn bộ dự án.
Làm quen với đoạn mã
- Sau khi mở dự án trong Android Studio, hãy dành chút thời gian để xem qua đoạn mã khởi đầu.
Xin lưu ý rằng đoạn mã khởi đầu cho ứng dụng này được chia thành hai mô-đun, :app
và :common:data
.
Mô-đun :app
chứa giao diện người dùng và logic của ứng dụng di động, còn mô-đun :common:data
chứa lớp dữ liệu mô hình Place
và kho lưu trữ dùng để đọc mô hình Place
. Để đơn giản, kho lưu trữ sẽ đọc dữ liệu từ một danh sách cố định giá trị trong mã, nhưng trong ứng dụng thực thì kho lưu trữ có thể dễ dàng đọc dữ liệu từ cơ sở dữ liệu hoặc máy chủ phụ trợ.
Mô-đun :app
bao gồm một phần phụ thuộc trên mô-đun :common:data
để mô-đun đó có thể đọc và thể hiện danh sách mô hình Place
.
3. Tìm hiểu về Thư viện Ứng dụng Android cho Ô tô
Thư viện Ứng dụng Android cho Ô tô (Android for Cars App Library) là một nhóm thư viện Jetpack cho phép nhà phát triển xây dựng ứng dụng để sử dụng trong xe. Thư viện này mang đến một khung theo mẫu cung cấp giao diện người dùng được tối ưu hoá cho quá trình lái xe, đồng thời đảm nhiệm việc điều chỉnh để thích ứng với các cấu hình phần cứng trong ô tô (ví dụ: phương thức nhập, kích thước màn hình và tỷ lệ khung hình). Cả hai điều này sẽ giúp nhà phát triển dễ dàng xây dựng ứng dụng và tự tin rằng ứng dụng đó sẽ hoạt động tốt trên nhiều loại xe chạy cả Android Auto và Android Automotive OS.
Tìm hiểu cách hoạt động
Các ứng dụng được tạo bằng Thư viện Ứng dụng cho Ô tô sẽ không chạy trực tiếp trên Android Auto hoặc Android Automotive OS. Thay vào đó, các ứng dụng đó dựa vào ứng dụng lưu trữ để giao tiếp với ứng dụng khách và kết xuất giao diện người dùng thay mặt cho ứng dụng khách. Bản thân Android Auto là một ứng dụng lưu trữ và Google Automotive App Host là ứng dụng lưu trữ được sử dụng trên các xe sử dụng Android Automotive OS được cài sẵn Google. Sau đây là các lớp chính của Thư viện Ứng dụng cho Ô tô mà bạn phải mở rộng khi tạo ứng dụng của mình:
CarAppService
CarAppService
là một lớp con của lớp Service
của Android và đóng vai trò là điểm vào để các ứng dụng lưu trữ giao tiếp với ứng dụng khách (chẳng hạn như ứng dụng bạn sẽ tạo trong lớp học lập trình này). Mục đích chính của lớp đó là tạo các thực thể Session
mà ứng dụng lưu trữ sẽ tương tác.
Session
Bạn có thể xem Session
là một thực thể của ứng dụng khách chạy từ xa trên màn hình của xe. Giống như các thành phần Android khác, thành phần này có vòng đời riêng có thể dùng để khởi tạo và chia nhỏ các tài nguyên được sử dụng trong suốt quá trình tồn tại của thực thể Session
. Có mối quan hệ một với nhiều giữa CarAppService
và Session
. Ví dụ: một CarAppService
có thể có hai thực thể Session
(một dành cho màn hình chính và một dành cho màn hình phân cụm) dành cho các ứng dụng đi theo chỉ dẫn có hỗ trợ màn hình phân cụm.
Screen
Các thực thể Screen
chịu trách nhiệm tạo giao diện người dùng được kết xuất bởi ứng dụng lưu trữ. Các giao diện người dùng này được thể hiện bằng các lớp Template
, mỗi lớp mô hình hoá một kiểu bố cục cụ thể, chẳng hạn như lưới (grid) hoặc danh sách (list). Mỗi Session
quản lý một ngăn xếp gồm nhiều thực thể Screen
xử lý luồng người dùng thông qua nhiều phần của ứng dụng. Giống như Session
, Screen
cũng có vòng đời riêng mà bạn có thể kết nối vào đó.
Bạn sẽ viết một CarAppService
, Session
và Screen
trong phần Viết CarAppService của lớp học lập trình này, vì vậy đừng lo lắng nếu mọi thứ vẫn chưa ổn.
4. Thiết lập cấu hình ban đầu
Để bắt đầu, hãy thiết lập mô-đun chứa CarAppService
và khai báo các phần phụ thuộc của mô-đun đó.
Tạo mô-đun car-app-service
- Chọn mô-đun
:common
trong cửa sổ Project (Dự án), nhấp chuột phải và chọn New > Module (Mới > Mô-đun). - Trình hướng dẫn của mô-đun này sẽ mở ra, trong đó hãy chọn mẫu Android Library (Thư viện Android) (để mô-đun này có thể được sử dụng làm phần phụ thuộc cho các mô-đun khác) trong danh sách ở phía bên trái, rồi sử dụng các giá trị sau:
- Tên mô-đun:
:common:car-app-service
- Tên gói:
com.example.places.carappservice
- SDK tối thiểu:
API 23: Android 6.0 (Marshmallow)
Thiết lập phần phụ thuộc
- Trong tệp
build.gradle
ở cấp dự án, hãy thêm phần khai báo biến cho các phiên bản Thư viện Ứng dụng cho Ô tô như sau. Việc này giúp bạn dễ dàng sử dụng cùng một phiên bản trên từng mô-đun trong ứng dụng.
build.gradle (Dự án: Places)
buildscript {
ext {
// All versions can be found at https://developer.android.com/jetpack/androidx/releases/car-app
car_app_library_version = '1.3.0-rc01'
...
}
}
- Tiếp theo, hãy thêm hai phần phụ thuộc vào tệp
build.gradle
của mô-đun:common:car-app-service
.
androidx.car.app:app
. Đây là cấu phần phần mềm chính của Thư viện Ứng dụng cho Ô tô và bao gồm tất cả các lớp cốt lõi được sử dụng khi tạo ứng dụng. Có ba cấu phần phần mềm khác tạo nên thư viện này,androidx.car.app:app-projected
tương ứng với chức năng dành riêng cho Android Auto,androidx.car.app:app-automotive
tương ứng với mã chức năng của Android Automotive OS, vàandroidx.car.app:app-testing
tương ứng với một số trình trợ giúp hữu ích cho việc kiểm thử đơn vị. Sau này, bạn sẽ sử dụngapp-projected
vàapp-automotive
trong lớp học lập trình này.:common:data
. Đây chính là mô-đun dữ liệu được ứng dụng di động hiện tại sử dụng và cho phép sử dụng cùng một nguồn dữ liệu cho trải nghiệm trong mọi phiên bản ứng dụng.
build.gradle (Mô-đun :common:car-app-service)
dependencies {
...
implementation "androidx.car.app:app:$car_app_library_version"
implementation project(":common:data")
...
}
Với thay đổi này, biểu đồ phần phụ thuộc cho các mô-đun riêng của ứng dụng sẽ như sau:
Hiện tại, các phần phụ thuộc đã được thiết lập, đã đến lúc viết CarAppService
!
5. Viết CarAppService
- Hãy bắt đầu bằng cách tạo một tệp có tên
PlacesCarAppService.kt
trong góicarappservice
trong mô-đun:common:car-app-service
. - Trong tệp này, hãy tạo một lớp có tên
PlacesCarAppService
, lớp này sẽ mở rộngCarAppService
.
PlacesCarAppService.kt
class PlacesCarAppService : CarAppService() {
override fun createHostValidator(): HostValidator {
return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
}
override fun onCreateSession(): Session {
// PlacesSession will be an unresolved reference until the next step
return PlacesSession()
}
}
Lớp trừu tượng CarAppService
sẽ triển khai các phương thức Service
(ví dụ: onBind
và onUnbind
) cho bạn cũng như ngăn chặn việc ghi đè thêm các phương thức đó để đảm bảo khả năng tương tác thích hợp với các ứng dụng lưu trữ. Bạn chỉ phải triển khai createHostValidator
và onCreateSession
.
HostValidator
mà bạn trả về từ createHostValidator
sẽ được tham chiếu khi CarAppService
đang được liên kết để đảm bảo rằng ứng dụng lưu trữ là đáng tin cậy và mối liên kết đó sẽ gặp lỗi nếu ứng dụng lưu trữ không phù hợp với các tham số mà bạn xác định. Đối với mục đích của lớp học lập trình này (và hoạt động kiểm thử nói chung), ALLOW_ALL_HOSTS_VALIDATOR
sẽ giúp bạn dễ dàng đảm bảo về mặt kết nối cho ứng dụng của mình (nhưng không nên dùng khi phát hành công khai). Hãy xem tài liệu về createHostValidator
để biết thêm về cách định cấu hình đối tượng này cho ứng dụng phát hành công khai.
Đối với một ứng dụng đơn giản như ứng dụng này, onCreateSession
có thể đơn giản là trả về một thực thể Session
. Trong một ứng dụng phức tạp hơn, đây sẽ là nơi phù hợp để khởi tạo các tài nguyên tồn tại lâu dài như các chỉ số. Đồng thời, các ứng dụng khách dùng để ghi nhật ký sẽ được sử dụng trong khi ứng dụng của bạn đang chạy trên xe.
- Sau cùng, bạn cần thêm phần tử
<service>
tương ứng vớiPlacesCarAppService
trong tệpAndroidManifest.xml
của mô-đun:common:car-app-service
để cho phép hệ điều hành (và các ứng dụng khác như ứng dụng lưu trữ) biết nó tồn tại.
AndroidManifest.xml (:common:car-app-service)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!--
This AndroidManifest.xml will contain all of the elements that should be shared across the
Android Auto and Automotive OS versions of the app, such as the CarAppService <service> element
-->
<application>
<service
android:name="com.example.places.carappservice.PlacesCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.POI" />
</intent-filter>
</service>
</application>
</manifest>
Có hai yếu tố quan trọng cần lưu ý ở đây:
- Phần tử
<action>
cho phép ứng dụng lưu trữ (và trình chạy) tìm được ứng dụng đó. - Phần tử
<category>
khai báo về danh mục của ứng dụng, xác định tiêu chí chất lượng mà ứng dụng đó sẽ phải đáp ứng (bạn sẽ tìm hiểu kỹ hơn về điều này sau). Có thể sử dụng các giá trịandroidx.car.app.category.NAVIGATION
vàandroidx.car.app.category.IOT
.
Tạo lớp PlacesSession
- Tạo tệp một
PlacesCarAppService.kt
rồi thêm đoạn mã sau:
PlacesCarAppService.kt
class PlacesSession : Session() {
override fun onCreateScreen(intent: Intent): Screen {
// MainScreen will be an unresolved reference until the next step
return MainScreen(carContext)
}
}
Đối với một ứng dụng đơn giản như ứng dụng này, bạn có thể quay lại màn hình chính ngay trong onCreateScreen
. Tuy nhiên, vì phương thức này lấy Intent
làm tham số, nên một ứng dụng nhiều tính năng hơn cũng có thể đọc từ đó và điền sẵn vào ngăn xếp lui của màn hình hoặc sử dụng một số logic điều kiện khác.
Tạo lớp MainScreen
Tiếp theo, hãy tạo một gói mới tên là screen.
- Nhấp phải vào gói
com.example.places.carappservice
rồi chọn New (Mới) > Package (Gói) (tên đầy đủ của gói này sẽ làcom.example.places.carappservice.screen
). Đây là nơi bạn sẽ đưa vào đó tất cả lớp conScreen
cho ứng dụng. - Trong gói
screen
, hãy tạo một tệp tên làMainScreen.kt
để chứa lớpMainScreen
(mở rộngScreen
). Hiện tại, ứng dụng sẽ cho thấy một thông điệp Hello, world! đơn giản bằng cách sử dụngPaneTemplate
.
MainScreen.kt
class MainScreen(carContext: CarContext) : Screen(carContext) {
override fun onGetTemplate(): Template {
val row = Row.Builder()
.setTitle("Hello, world!")
.build()
val pane = Pane.Builder()
.addRow(row)
.build()
return PaneTemplate.Builder(pane)
.setHeaderAction(Action.APP_ICON)
.build()
}
}
6. Thêm khả năng hỗ trợ Android Auto
Mặc dù hiện tại bạn đã triển khai tất cả logic cần thiết để thiết lập và chạy ứng dụng, nhưng bạn vẫn sẽ cần thiết lập 2 phần cấu hình nữa trước khi có thể chạy ứng dụng đó trên Android Auto.
Thêm phần phụ thuộc vào mô-đun car-app-service
Trong tệp build.gradle
của mô-đun :app
, hãy thêm đoạn mã sau:
build.gradle (Mô-đun :app)
dependencies {
...
implementation project(path: ':common:car-app-service')
...
}
Với thay đổi này, biểu đồ phần phụ thuộc cho các mô-đun riêng của ứng dụng sẽ như sau:
Thay đổi này sẽ gói đoạn mã bạn vừa viết trong mô-đun :common:car-app-service
cùng với các thành phần khác có trong Thư viện Ứng dụng cho Ô tô (ví dụ: hoạt động cấp quyền được cung cấp).
Khai báo siêu dữ liệu com.google.android.gms.car.application
- Nhấp chuột phải vào mô-đun
:common:car-app-service
, chọn New > Android Resource File (Mới > Tệp tài nguyên Android), rồi ghi đè các giá trị sau:
- Tên tệp:
automotive_app_desc.xml
- Loại tài nguyên:
XML
- Phần tử gốc:
automotiveApp
- Trong tệp đó, hãy thêm phần tử
<uses>
sau để khai báo rằng ứng dụng của bạn sẽ sử dụng các mẫu do Thư viện Ứng dụng cho Ô tô cung cấp.
automotive_app_desc.xml
<?xml version="1.0" encoding="utf-8"?>
<automotiveApp>
<uses name="template"/>
</automotiveApp>
- Trong tệp
AndroidManifest.xml
của mô-đun:app
, hãy thêm phần tử<meta-data>
sau (tham chiếu đến tệpautomotive_app_desc.xml
mà bạn vừa tạo).
AndroidManifest.xml (:app)
<application ...>
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
...
</application>
Android Auto sẽ đọc tệp này và được cho biết về những chức năng mà ứng dụng của bạn hỗ trợ (trong trường hợp này là ứng dụng sử dụng hệ thống tạo mẫu của Thư viện Ứng dụng cho Ô tô). Thông tin này sau đó được sẽ dùng để xử lý các hành vi như thêm ứng dụng vào trình chạy Android Auto và mở ứng dụng từ thông báo.
Không bắt buộc: Nghe những thay đổi về phép chiếu
Đôi khi, bạn muốn biết liệu thiết bị của người dùng có được kết nối với ô tô hay không. Bạn có thể thực hiện việc này bằng cách sử dụng CarConnection
API. API này cung cấp LiveData
cho phép bạn quan sát trạng thái kết nối.
- Để dùng
CarConnection
API, trước tiên hãy thêm phần phụ thuộc vào mô-đun:app
trên cấu phần phần mềmandroidx.car.app:app
.
build.gradle (Mô-đun :app)
dependencies {
...
implementation "androidx.car.app:app:$car_app_library_version"
...
}
- Để minh hoạ, bạn có thể tạo một Thành phần kết hợp (Composable) đơn giản như sau để cho thấy trạng thái kết nối hiện tại. Trong ứng dụng thực, trạng thái này có thể được ghi lại trong một số nhật ký, dùng để tắt một số chức năng trên màn hình điện thoại trong khi chiếu, hoặc cho mục đích khác.
MainActivity.kt
@Composable
fun ProjectionState(carConnectionType: Int, modifier: Modifier = Modifier) {
val text = when (carConnectionType) {
CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not projecting"
CarConnection.CONNECTION_TYPE_NATIVE -> "Running on Android Automotive OS"
CarConnection.CONNECTION_TYPE_PROJECTION -> "Projecting"
else -> "Unknown connection type"
}
Text(
text = text,
style = MaterialTheme.typography.bodyMedium,
modifier = modifier
)
}
- Hiện bạn đã có cách hiển thị dữ liệu, hãy đọc và truyền dữ liệu đó vào Thành phần kết hợp, như minh hoạ trong đoạn mã sau.
MainActivity.kt
setContent {
val carConnectionType by CarConnection(this).type.observeAsState(initial = -1)
PlacesTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column {
Text(
text = "Places",
style = MaterialTheme.typography.displayLarge,
modifier = Modifier.padding(8.dp)
)
ProjectionState(
carConnectionType = carConnectionType,
modifier = Modifier.padding(8.dp)
)
PlaceList(places = PlacesRepository().getPlaces())
}
}
}
}
- Nếu bạn chạy ứng dụng, ứng dụng sẽ thông báo Hiện không chiếu.
7. Kiểm thử bằng Đầu phát trung tâm máy tính (DHU)
Sau khi triển khai CarAppService
và chuẩn bị xong cấu hình Android Auto, đã đến lúc chạy ứng dụng và xem kết quả.
- Cài đặt ứng dụng trên điện thoại của bạn, rồi làm theo hướng dẫn cài đặt và chạy DHU.
Khi DHU được thiết lập và chạy, bạn sẽ thấy biểu tượng ứng dụng trong trình chạy (nếu không, hãy kiểm tra kỹ xem bạn đã làm theo tất cả bước trong phần trước chưa, sau đó thoát và khởi động lại DHU từ thiết bị đầu cuối).
Ôi, gặp sự cố rồi!
- Để biết lý do ứng dụng gặp sự cố, bạn có thể chuyển đổi biểu tượng gỡ lỗi ở góc trên cùng bên phải (chỉ xuất hiện khi chạy trên DHU) hoặc kiểm tra Logcat trong Android Studio.
Error: [type: null, cause: null, debug msg: java.lang.IllegalArgumentException: Min API level not declared in manifest (androidx.car.app.minCarApiLevel) at androidx.car.app.AppInfo.retrieveMinCarAppApiLevel(AppInfo.java:143) at androidx.car.app.AppInfo.create(AppInfo.java:91) at androidx.car.app.CarAppService.getAppInfo(CarAppService.java:380) at androidx.car.app.CarAppBinder.getAppInfo(CarAppBinder.java:255) at androidx.car.app.ICarApp$Stub.onTransact(ICarApp.java:182) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1244) ]
Trên nhật ký này, bạn có thể thấy rằng có một phần khai báo bị thiếu trong tệp kê khai về cấp độ API tối thiểu mà ứng dụng hỗ trợ. Trước khi thêm mục đó, tốt nhất bạn nên hiểu lý do khiến nó cần thiết.
Cũng như Android, Thư viện Ứng dụng cho Ô tô cũng có khái niệm về các cấp độ API, vì cần phải có quy định ràng buộc giữa ứng dụng lưu trữ và ứng dụng khách để chúng giao tiếp với nhau. Các ứng dụng lưu trữ hỗ trợ một cấp API nhất định cũng như các tính năng liên quan đến cấp API đó (và cả các tính năng từ các cấp trước đó để tương thích ngược). Ví dụ: SignInTemplate
có thể được sử dụng trên các ứng dụng lưu trữ ở API cấp 2 trở lên. Tuy nhiên, nếu bạn cố sử dụng nó trên ứng dụng lưu trữ chỉ hỗ trợ API cấp 1, thì ứng dụng lưu trữ đó sẽ không biết về loại mẫu và sẽ không thể thực hiện bất cứ tác vụ có ý nghĩa nào với loại mẫu đó.
Trong quá trình liên kết ứng dụng lưu trữ với ứng dụng khách, các cấp độ API được hỗ trợ phải có một mức độ trùng nhau nào đó để có thể liên kết thành công. Ví dụ: nếu ứng dụng lưu trữ chỉ hỗ trợ API cấp 1 nhưng ứng dụng khách không thể chạy nếu không có các tính năng của API cấp 2 (như trong phần khai báo của tệp kê khai này cho thấy), thì các ứng dụng này sẽ không kết nối được với nhau vì ứng dụng khách sẽ không thể chạy thành công trên ứng dụng lưu trữ. Do đó, yêu cầu về cấp độ API tối thiểu phải được ứng dụng khách khai báo trong tệp kê khai để đảm bảo rằng chỉ ứng dụng lưu trữ hỗ trợ được cấp độ API đó mới được liên kết.
- Để thiết lập cấp độ API tối thiểu được hỗ trợ, hãy thêm phần tử
<meta-data>
sau vào tệpAndroidManfiest.xml
của mô-đun:common:car-app-service
:
AndroidManifest.xml (:common:car-app-service)
<application>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1" />
<service android:name="com.example.places.carappservice.PlacesCarAppService" ...>
...
</service>
</application>
- Cài đặt lại ứng dụng rồi khởi chạy ứng dụng đó trên DHU, bạn sẽ thấy như sau:
Để hoàn thiện, bạn cũng có thể thử đặt minCarApiLevel
thành một giá trị lớn (ví dụ: 100) để xem điều gì xảy ra khi cố khởi động ứng dụng nếu ứng dụng lưu trữ và ứng dụng khách không tương thích (gợi ý: sẽ gặp sự cố, tương tự như khi không có giá trị nào được thiết lập).
Điều quan trọng cần lưu ý là: cũng như Android, bạn có thể sử dụng các tính năng của API cao hơn API tối thiểu được khai báo nếu bạn xác minh được trong thời gian chạy rằng ứng dụng lưu trữ hỗ trợ cấp độ API cần thiết.
Không bắt buộc: Nghe những thay đổi về phép chiếu
- Nếu đã thêm trình nghe
CarConnection
ở bước trước, bạn sẽ thấy trạng thái đã cập nhật trên điện thoại của mình khi DHU đang chạy, như minh hoạ dưới đây:
8. Thêm khả năng hỗ trợ Android Automotive OS
Nay bạn đã thiết lập và chạy Android Auto, đã đến lúc mở rộng hơn nữa để hỗ trợ cả Android Automotive OS.
Tạo mô-đun :automotive
- Để tạo một mô-đun chứa đoạn mã dành riêng cho phiên bản ứng dụng Android Automotive OS, hãy mở File > New > New Module… (Tệp > Mới > Mô-đun mới…) trong Android Studio, chọn Automotive trong danh sách loại mẫu ở bên trái, sau đó sử dụng các giá trị sau:
- Tên ứng dụng/thư viện:
Places
(giống như ứng dụng chính, nhưng bạn cũng có thể chọn tên khác nếu muốn) - Tên mô-đun:
automotive
- Tên gói:
com.example.places.automotive
- Ngôn ngữ:
Kotlin
- SDK tối thiểu:
API 29: Android 10.0 (Q)
— như đề cập trước đó khi tạo mô-đun:common:car-app-service
, tất cả xe Android Automotive OS có hỗ trợ ứng dụng tạo bằng Thư viện Ứng dụng cho Ô tô đều chạy ở cấp độ API tối thiểu là 29.
- Nhấp vào Next (Tiếp theo), rồi chọn No Activity (Không có hoạt động) trên màn hình tiếp theo, sau cùng nhấp vào Finish (Hoàn tất).
Thêm phần phụ thuộc
Cũng như Android Auto, bạn cần khai báo phần phụ thuộc trên mô-đun :common:car-app-service
. Nhờ vậy, bạn có thể chia sẻ phương thức triển khai của mình trên cả hai nền tảng!
Ngoài ra, bạn cần thêm phần phụ thuộc vào cấu phần phần mềm androidx.car.app:app-automotive
. Không giống như cấu phần phần mềm androidx.car.app:app-projected
(không bắt buộc đối với Android Auto), phần phụ thuộc này là bắt buộc trên Android Automotive OS vì chứa CarAppActivity
dùng để chạy ứng dụng của bạn.
- Để thêm phần phụ thuộc, hãy mở tệp
build.gradle
, rồi chèn đoạn mã sau:
build.gradle (Mô-đun :automotive)
dependencies {
...
implementation project(':common:car-app-service')
implementation "androidx.car.app:app-automotive:$car_app_library_version"
...
}
Với thay đổi này, biểu đồ phần phụ thuộc cho các mô-đun riêng của ứng dụng sẽ như sau:
Thiết lập tệp kê khai
- Trước tiên, bạn cần khai báo hai tính năng (
android.hardware.type.automotive
vàandroid.software.car.templates_host
) bắt buộc.
android.hardware.type.automotive
là một tính năng hệ thống cho biết thiết bị là một chiếc xe (xem FEATURE_AUTOMOTIVE
để biết thêm chi tiết). Chỉ những ứng dụng đánh dấu tính năng này là bắt buộc mới có thể được gửi tới kênh Automotive OS trên Play Console (và những ứng dụng được gửi đến các kênh khác sẽ không thể đòi hỏi tính năng này). android.software.car.templates_host
là một tính năng hệ thống chỉ có trên những xe có ứng dụng lưu trữ mẫu bắt buộc để chạy các ứng dụng mẫu.
AndroidManifest.xml (:automotive)
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature
android:name="android.hardware.type.automotive"
android:required="true" />
<uses-feature
android:name="android.software.car.templates_host"
android:required="true" />
...
</manifest>
- Tiếp theo, bạn cần khai báo một số tính năng là không bắt buộc.
Điều này nhằm đảm bảo rằng ứng dụng của bạn tương thích với nhiều loại phần cứng có trên ô tô được cài sẵn Google. Ví dụ: nếu ứng dụng của bạn cần đến tính năng android.hardware.screen.portrait
thì ứng dụng đó sẽ không tương thích với những xe có màn hình ngang vì hầu hết màn hình xe đều có hướng cố định. Đây là lý do tại sao thuộc tính android:required
được thiết lập thành false
cho các tính năng này.
AndroidManifest.xml (:automotive)
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<uses-feature
android:name="android.hardware.wifi"
android:required="false" />
<uses-feature
android:name="android.hardware.screen.portrait"
android:required="false" />
<uses-feature
android:name="android.hardware.screen.landscape"
android:required="false" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
...
</manifest>
- Tiếp theo, bạn cần thêm tham chiếu đến tệp
automotive_app_desc.xml
như đã thực hiện với Android Auto.
Hãy lưu ý rằng lần này thuộc tính android:name
khác với trước đây (là com.android.automotive
thay vì com.google.android.gms.car.application
). Theo như trước đây, thuộc tính này tham chiếu đến tệp automotive_app_desc.xml
trong mô-đun :common:car-app-service
, tức là cùng một tài nguyên được sử dụng trên cả Android Auto và Android Automotive OS. Hãy lưu ý rằng phần tử <meta-data>
nằm trong phần tử <application>
(vì vậy bạn phải thay đổi thẻ application
để không tự đóng)!
AndroidManifest.xml (:automotive)
<application>
...
<meta-data android:name="com.android.automotive"
android:resource="@xml/automotive_app_desc"/>
...
</application>
- Sau cùng, bạn cần thêm phần tử
<activity>
choCarAppActivity
có trong thư viện.
AndroidManifest.xml (:automotive)
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<application ...>
...
<activity
android:name="androidx.car.app.activity.CarAppActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="distractionOptimized"
android:value="true" />
</activity>
</application>
</manifest>
Và sau đây là tác dụng của tất cả những điều đó:
android:name
liệt kê tên lớp đủ điều kiện của lớpCarAppActivity
từ góiapp-automotive
.android:exported
được thiết lập thànhtrue
do đóActivity
phải có thể được khởi chạy bởi một ứng dụng thay vì tự khởi chạy (trình chạy).android:launchMode
được thiết lập thànhsingleTask
, do đó chỉ có duy nhất một thực thểCarAppActivity
tại một thời điểm.android:theme
được thiết lập thành@android:style/Theme.DeviceDefault.NoActionBar
để ứng dụng chiếm toàn bộ không gian màn hình có thể sử dụng.- Bộ lọc ý định cho biết đây là trình chạy
Activity
cho ứng dụng. - Có một phần tử
<meta-data>
cho hệ thống biết rằng ứng dụng có thể được sử dụng khi áp dụng các quy tắc hạn chế về trải nghiệm người dùng, chẳng hạn như khi xe đang di chuyển.
Không bắt buộc: sao chép các biểu tượng trình khởi chạy từ mô-đun :app
Vì bạn vừa tạo mô-đun :automotive
nên mô-đun đó có biểu trưng Android màu xanh lục mặc định.
- Nếu muốn, hãy sao chép và dán thư mục tài nguyên
mipmap
từ mô-đun:app
vào mô-đun:automotive
để sử dụng các biểu tượng trình khởi chạy giống như ứng dụng di động!
9. Kiểm thử bằng trình mô phỏng Android Automotive OS
Cài đặt Automotive bằng hình ảnh Hệ thống Cửa hàng Play
- Trước tiên, hãy mở Trình quản lý SDK trong Android Studio rồi chọn thẻ SDK Platforms (Nền tảng SDK) nếu chưa chọn. Ở góc dưới bên phải của cửa sổ Trình quản lý SDK, hãy đảm bảo rằng hộp Show package details (Hiện thông tin về gói) được chọn.
- Cài đặt một hoặc nhiều hình ảnh hệ thống sau đây dành cho trình mô phỏng. Các hình ảnh hệ thống chỉ chạy được trên máy có cùng kiến trúc (x86/ARM) với chính chúng.
- Android 12L > Hình ảnh hệ thống Automotive có Cửa hàng Play dành cho Intel x86 Atom_64
- Android 12L > Hình ảnh hệ thống Automotive có Cửa hàng Play dành cho ARM 64 v8a
- Android 11 > Hình ảnh hệ thống Automotive có Cửa hàng Play dành cho Intel x86 Atom_64
- Android 10 > Hình ảnh hệ thống Automotive có Cửa hàng Play dành cho Intel x86 Atom_64
Tạo thiết bị Android ảo Android Automotive OS
- Sau khi mở Device Manager (Trình quản lý thiết bị), hãy chọn Automotive trong cột Category (Danh mục) ở bên trái cửa sổ. Sau đó, chọn định nghĩa thiết bị Automotive (1024p landscape) (Automotive (hướng ngang 1024p)) trong danh sách rồi nhấp vào Next (Tiếp theo).
- Trên trang tiếp theo, hãy chọn hình ảnh hệ thống từ bước trước (nếu bạn chọn hình ảnh Android 11/API 30, thì có thể hình ảnh đó nằm trong thẻ x86 Images (Hình ảnh x86) chứ không phải thẻ Recommended (Đề xuất) mặc định). Nhấp vào Next (Tiếp theo) rồi chọn mọi lựa chọn nâng cao mà bạn muốn trước khi tạo AVD bằng cách nhấp vào Finish (Hoàn tất).
Chạy ứng dụng
- Chạy ứng dụng trên trình mô phỏng bạn vừa tạo bằng cấu hình chạy
automotive
.
Trong lần đầu chạy ứng dụng, có thể bạn sẽ thấy một màn hình như sau:
Nếu trường hợp đó xảy ra, hãy nhấp vào nút Check for updates (Kiểm tra bản cập nhật). Nút này sẽ đưa bạn đến trang dành cho ứng dụng Google Automotive App Host trên Cửa hàng Play. Tại đó, bạn nên nhấp vào nút Cài đặt. Nếu chưa đăng nhập khi nhấp vào nút Check for updates (Kiểm tra bản cập nhật), bạn sẽ được chuyển sang quy trình đăng nhập. Sau khi đăng nhập, bạn có thể mở lại ứng dụng để nhấp vào nút và quay lại trang Cửa hàng Play.
- Sau cùng, khi ứng dụng lưu trữ đã được cài đặt, hãy mở lại ứng dụng trên trình chạy (biểu tượng lưới 9 chấm ở hàng dưới cùng) và bạn sẽ thấy như sau:
Trong bước tiếp theo, bạn sẽ thực hiện các thay đổi trong mô-đun :common:car-app-service
để hiện danh sách địa điểm và cho phép người dùng bắt đầu đi theo chỉ dẫn đến vị trí đã chọn trong một ứng dụng khác.
10. Thêm bản đồ và màn hình chi tiết
Thêm bản đồ vào màn hình chính
- Để bắt đầu, hãy thay thế đoạn mã trong phương thức
onGetTemplate
của lớpMainScreen
bằng đoạn mã sau:
MainScreen.kt
override fun onGetTemplate(): Template {
val placesRepository = PlacesRepository()
val itemListBuilder = ItemList.Builder()
.setNoItemsMessage("No places to show")
placesRepository.getPlaces()
.forEach {
itemListBuilder.addItem(
Row.Builder()
.setTitle(it.name)
// Each item in the list *must* have a DistanceSpan applied to either the title
// or one of the its lines of text (to help drivers make decisions)
.addText(SpannableString(" ").apply {
setSpan(
DistanceSpan.create(
Distance.create(Math.random() * 100, Distance.UNIT_KILOMETERS)
), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE
)
})
.setOnClickListener { TODO() }
// Setting Metadata is optional, but is required to automatically show the
// item's location on the provided map
.setMetadata(
Metadata.Builder()
.setPlace(Place.Builder(CarLocation.create(it.latitude, it.longitude))
// Using the default PlaceMarker indicates that the host should
// decide how to style the pins it shows on the map/in the list
.setMarker(PlaceMarker.Builder().build())
.build())
.build()
).build()
)
}
return PlaceListMapTemplate.Builder()
.setTitle("Places")
.setItemList(itemListBuilder.build())
.build()
}
Đoạn mã này sẽ đọc danh sách thực thể Place
từ PlacesRepository
và sau đó chuyển đổi từng thực thể đó thành một Row
để thêm vào ItemList
do PlaceListMapTemplate
hiển thị.
- Chạy lại ứng dụng (trên một hoặc cả hai nền tảng) để xem kết quả!
Android Auto | Android Automotive OS |
Ồ, lại một lỗi nữa – có vẻ như là thiếu quyền.
java.lang.SecurityException: The car app does not have a required permission: androidx.car.app.MAP_TEMPLATES at android.os.Parcel.createExceptionOrNull(Parcel.java:2373) at android.os.Parcel.createException(Parcel.java:2357) at android.os.Parcel.readException(Parcel.java:2340) at android.os.Parcel.readException(Parcel.java:2282) ...
- Để sửa lỗi, hãy thêm phần tử
<uses-permission>
sau đây vào tệp kê khai của mô-đun:common:car-app-service
.
Mọi ứng dụng sử dụng PlaceListMapTemplate
đều phải khai báo quyền này, nếu không ứng dụng sẽ gặp sự cố như vừa minh hoạ. Xin lưu ý rằng chỉ những ứng dụng khai báo danh mục là androidx.car.app.category.POI
mới có thể sử dụng mẫu này, tương ứng với quyền này.
AndroidManifest.xml (:common:car-app-service)
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="androidx.car.app.MAP_TEMPLATES" />
...
</manifest>
Nếu bạn chạy ứng dụng sau khi thêm quyền, kết quả sẽ giống như sau trên từng nền tảng:
Android Auto | Android Automotive OS |
Việc kết xuất bản đồ được ứng dụng lưu trữ xử lý cho bạn khi bạn cung cấp Metadata
cần thiết!
Thêm màn hình chi tiết
Tiếp theo, đã đến lúc thêm màn hình chi tiết để cho phép người dùng xem thêm thông tin về một vị trí cụ thể và chọn đi theo chỉ dẫn đến vị trí đó bằng ứng dụng đi theo chỉ dẫn mà họ ưu tiên dùng, hoặc quay lại danh sách địa điểm khác. Bạn có thể thực hiện điều này có thể được bằng cách sử dụng PaneTemplate
(cho phép bạn hiển thị tối đa 4 hàng thông tin bên cạnh các nút hành động không bắt buộc).
- Trước tiên, hãy nhấp chuột phải vào thư mục
res
trong mô-đun:common:car-app-service
, nhấp vào New > Vector Asset (Mới > Thành phần vectơ), rồi tạo biểu tượng đi theo chỉ dẫn bằng cách sử dụng cấu hình sau:
- Loại thành phần:
Clip art
- Hình mẫu:
navigation
- Tên:
baseline_navigation_24
- Kích thước:
24
dp x24
dp - Màu:
#000000
- Độ mờ:
100%
- Sau đó, trong gói
screen
, hãy tạo một tệp có tênDetailScreen.kt
(bên cạnh tệpMainScreen.kt
hiện tại) và thêm đoạn mã sau:
DetailScreen.kt
class DetailScreen(carContext: CarContext, private val placeId: Int) : Screen(carContext) {
override fun onGetTemplate(): Template {
val place = PlacesRepository().getPlace(placeId)
?: return MessageTemplate.Builder("Place not found")
.setHeaderAction(Action.BACK)
.build()
val navigateAction = Action.Builder()
.setTitle("Navigate")
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
carContext,
R.drawable.baseline_navigation_24
)
).build()
)
// Only certain intent actions are supported by `startCarApp`. Check its documentation
// for all of the details. To open another app that can handle navigating to a location
// you must use the CarContext.ACTION_NAVIGATE action and not Intent.ACTION_VIEW like
// you might on a phone.
.setOnClickListener { carContext.startCarApp(place.toIntent(CarContext.ACTION_NAVIGATE)) }
.build()
return PaneTemplate.Builder(
Pane.Builder()
.addAction(navigateAction)
.addRow(
Row.Builder()
.setTitle("Coordinates")
.addText("${place.latitude}, ${place.longitude}")
.build()
).addRow(
Row.Builder()
.setTitle("Description")
.addText(place.description)
.build()
).build()
)
.setTitle(place.name)
.setHeaderAction(Action.BACK)
.build()
}
}
Hãy đặc biệt chú ý đến cách tạo navigateAction
— lệnh gọi đến startCarApp
trong OnClickListener
của nó là yếu tố chính để tương tác với các ứng dụng khác trên Android Auto và Android Automotive OS.
Di chuyển giữa các màn hình
Bây giờ đã có hai loại màn hình, đã đến lúc thêm chức năng đi theo chỉ dẫn giữa chúng! Chức năng đi theo chỉ dẫn trong Thư viện Ứng dụng cho Ô tô sẽ sử dụng mô hình ngăn xếp với các lệnh thêm (push) và đóng (pop), lý tưởng cho các luồng tác vụ đơn giản phù hợp để hoàn tất trong khi lái xe.
- Để điều hướng từ một trong các mục danh sách trên
MainScreen
đếnDetailScreen
cho mục đó, hãy thêm đoạn mã sau:
MainScreen.kt
Row.Builder()
...
.setOnClickListener { screenManager.push(DetailScreen(carContext, it.id)) }
...
Việc điều hướng ngược lại từ DetailScreen
về MainScreen
đã được xử lý vì setHeaderAction(Action.BACK)
được gọi khi tạo PaneTemplate
hiển thị trên DetailScreen
. Khi người dùng nhấp vào hành động trên tiêu đề, ứng dụng lưu trữ sẽ xử lý việc xoá màn hình hiện tại ra khỏi ngăn xếp cho bạn, nhưng ứng dụng của bạn có thể ghi đè hành vi này nếu muốn.
- Hãy chạy ứng dụng để xem
DetailScreen
và chức năng đi theo chỉ dẫn trong ứng dụng hoạt động như thế nào!
11. Cập nhật nội dung trên màn hình
Thường thì bạn muốn cho phép người dùng tương tác với màn hình và thay đổi trạng thái của các thành phần trên màn hình đó. Để minh hoạ cách thực hiện điều này, bạn sẽ tạo chức năng cho phép người dùng chuyển đổi qua lại giữa yêu thích và bỏ yêu thích cho một địa điểm trên DetailScreen
.
- Trước tiên, hãy thêm một biến cục bộ
isFavorite
chứa trạng thái. Trong ứng dụng thực, dữ liệu này phải được lưu trữ dưới dạng một phần của lớp dữ liệu, nhưng một biến cục bộ là đủ cho mục đích minh hoạ.
DetailScreen.kt
class DetailScreen(carContext: CarContext, private val placeId: Int) : Screen(carContext) {
private var isFavorite = false
...
}
- Tiếp theo, hãy nhấp chuột phải vào thư mục
res
trong mô-đun:common:car-app-service
, nhấp vào New > Vector Asset (Mới > Thành phần vectơ), rồi tạo biểu tượng yêu thích bằng cách sử dụng cấu hình sau:
- Loại thành phần:
Clip art
- Tên:
baseline_favorite_24
- Hình mẫu:
favorite
- Kích thước:
24
dp x24
dp - Màu:
#000000
- Độ mờ:
100%
- Sau đó, trong
DetailsScreen.kt
, hãy tạo mộtActionStrip
choPaneTemplate
.
Các thành phần giao diện người dùng ActionStrip
được đặt ở hàng tiêu đề đối diện với tiêu đề và là lý tưởng để sử dụng cho các hành động cấp hai và cấp ba. Vì đi theo chỉ dẫn là hành động chính được thực hiện trên DetailScreen
, nên việc đặt Action
là yêu thích hoặc bỏ yêu thích trong ActionStrip
là một cách hiệu quả để tạo kết cấu cho màn hình.
DetailScreen.kt
val navigateAction = ...
val actionStrip = ActionStrip.Builder()
.addAction(
Action.Builder()
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
carContext,
R.drawable.baseline_favorite_24
)
).setTint(
if (isFavorite) CarColor.RED else CarColor.createCustom(
Color.LTGRAY,
Color.DKGRAY
)
).build()
)
.setOnClickListener {
isFavorite = !isFavorite
}.build()
)
.build()
...
Có hai phần cần quan tâm ở đây:
CarIcon
được tô màu tuỳ theo trạng thái của mục.setOnClickListener
dùng để phản ứng với hoạt động đầu vào từ người dùng và chuyển đổi trạng thái yêu thích.
- Đừng quên gọi hàm
setActionStrip
trênPaneTemplate.Builder
để sử dụng!
DetailScreen.kt
return PaneTemplate.Builder(...)
...
.setActionStrip(actionStrip)
.build()
- Bây giờ, hãy chạy ứng dụng và xem điều gì xảy ra:
Thật thú vị... có vẻ như giao diện người dùng không cập nhật mặc dù các lượt nhấp đang diễn ra.
Điều này là do Thư viện Ứng dụng cho Ô tô có khái niệm làm mới (refresh). Để hạn chế sự phân tâm của người lái xe, việc làm mới nội dung trên màn hình có một số hạn chế nhất định (tuỳ theo mẫu được hiển thị) và mỗi lần làm mới phải được mã nguồn của chính bạn yêu cầu rõ ràng bằng cách gọi phương thức invalidate
của lớp Screen
. Việc chỉ cập nhật một số trạng thái được tham chiếu trong onGetTemplate
là không đủ để cập nhật giao diện người dùng.
- Để khắc phục vấn đề này, hãy cập nhật
OnClickListener
như sau:
DetailScreen.kt
.setOnClickListener {
isFavorite = !isFavorite
// Request that `onGetTemplate` be called again so that updates to the
// screen's state can be picked up
invalidate()
}
- Chạy lại ứng dụng để xem màu của biểu tượng trái tim được cập nhật sau mỗi lượt nhấp!
Và thế là bạn đã có một ứng dụng cơ bản được tích hợp tốt với cả Android Auto và Android Automotive OS!
12. Xin chúc mừng
Bạn đã tạo thành công ứng dụng đầu tiên của mình bằng Thư viện Ứng dụng cho Ô tô. Bây giờ là lúc áp dụng kiến thức đã học vào ứng dụng của riêng bạn!
Như đề cập trước đó, hiện tại thì chỉ một số ứng dụng nhất định thuộc danh mục ứng dụng được tạo bằng Thư viện Ứng dụng cho Ô tô mới có thể được gửi tới Cửa hàng Play. Nếu ứng dụng của bạn là ứng dụng đi theo chỉ dẫn, ứng dụng địa điểm yêu thích (POI) (như ứng dụng mà bạn xử lý trong lớp học lập trình này) hoặc ứng dụng Internet của vạn vật (IOT), thì bạn có thể bắt đầu xây dựng ứng dụng ngay hôm nay để xuất bản chính thức ứng dụng trên cả hai nền tảng.
Mỗi năm chúng tôi đều bổ sung danh mục ứng dụng mới. Do đó, kể cả khi bạn chưa áp dụng ngay được những gì vừa học, thì sau này cũng đừng quên kiểm tra lại, vì có thể đến thời điểm mở rộng ứng dụng của bạn sang cho ô tô!
Những điều nên thử
- Cài đặt trình mô phỏng của nhà sản xuất thiết bị gốc (ví dụ: trình mô phỏng Polestar 2) và xem cách mà những chế độ tuỳ chỉnh của nhà sản xuất thiết bị gốc có thể thay đổi giao diện của ứng dụng Thư viện Ứng dụng cho Ô tô trên Android Automotive OS. Hãy lưu ý rằng không phải trình mô phỏng nào của nhà sản xuất thiết bị gốc cũng hỗ trợ ứng dụng sử dụng Thư viện Ứng dụng cho Ô tô.
- Tham khảo ứng dụng mẫu Showcase minh hoạ đầy đủ chức năng của Thư viện Ứng dụng cho Ô tô.
Tài liệu đọc thêm
- Sử dụng Thư viện Ứng dụng Android cho Ô tô để áp dụng nội dung trong lớp học lập trình này cùng nhiều nội dung khác!
- Nguyên tắc thiết kế dành cho Thư viện Ứng dụng Android dành cho Ô tô cung cấp nội dung mô tả chi tiết về tất cả mẫu cũng như các phương pháp hay nhất cần tuân theo khi bạn tạo ứng dụng.
- Trang Chất lượng ứng dụng Android dành cho ô tô mô tả những tiêu chí mà ứng dụng của bạn phải đáp ứng để tạo ra trải nghiệm người dùng chất lượng cao và vượt qua quy trình xem xét trên Cửa hàng Play.