1. Trước khi bắt đầu
Kiến thức bạn sẽ học được
- Trải nghiệm người dùng độc đáo mà Android XR có thể mang đến.
- Cách tối ưu hoá một ứng dụng cho kính Android XR bằng thư viện Jetpack Compose XR.
- Cách sử dụng các phần tử trên giao diện người dùng trong thư viện Jetpack Compose XR.
- Tại đây, bạn sẽ tìm hiểu thêm về cách tạo ứng dụng cho Android XR.
Không bao gồm
- Hướng dẫn tạo ứng dụng Android XR mà không cần sử dụng Compose. Hãy xem bài viết Phát triển giao diện người dùng cho các ứng dụng Android dựa trên Khung hiển thị.
- Hướng dẫn tạo ứng dụng Unity hoặc OpenXR cho Android XR. Hãy xem bài viết Phát triển với Unity cho Android XR và Phát triển với OpenXR.
Bạn cần có
- Bản xem trước Android Studio mới nhất.
- Một máy tính có thể chạy trình mô phỏng Android XR.
- Trải nghiệm với Kotlin và Jetpack Compose, chẳng hạn bằng cách hoàn tất khoá học Kiến thức cơ bản về cách tạo ứng dụng Android bằng Compose.
- Trải nghiệm việc tạo các thiết bị Android ảo và chạy ứng dụng trên những thiết bị đó.
- Trải nghiệm các chế độ và bảng điều khiển không gian của Android XR, chẳng hạn như bằng cách hoàn tất lớp học lập trình Tìm hiểu kiến thức cơ bản về Android XR: Phần 1 – Chế độ và Bảng điều khiển không gian.
Sản phẩm bạn sẽ tạo ra
Trong lớp học lập trình này, bạn sẽ tối ưu hoá thêm một ứng dụng bằng một số tính năng XR hiện có bằng cách thêm các phần tử trên giao diện người dùng nổi và tuỳ chỉnh môi trường ảo bao quanh người dùng trong khi dùng ứng dụng.
Điểm xuất phát | Kết quả cuối cùng |
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
xr-fundamentals
trong kho lưu trữ GitHubxr-codelabs
. Để sao chép kho lưu trữ, hãy chạy lệnh sau đây:
git clone https://github.com/android/xr-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 khởi động Android Studio, hãy nhập thư mục
xr-fundamentals/part1
. Thư mụcxr-fundamentals/part2
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.
- Nếu bạn chưa tham gia lớp học lập trình đầu tiên hoặc chưa sử dụng trình mô phỏng Android XR, hãy làm theo các bước trong phần Chạy ứng dụng trong trình mô phỏng Android XR để chạy ứng dụng.
3. Tìm hiểu các khái niệm về XR: Orbiter
Orbiter là các phần tử trên giao diện người dùng nổi có trong chế độ Toàn không gian, thường được dùng để kiểm soát nội dung trong bảng điều khiển không gian hoặc các thực thể khác mà orbit được liên kết. Việc điều khiển nội dung bằng orbiter sẽ tạo thêm không gian cho nội dung, nghĩa là người dùng có thể nhanh chóng truy cập vào các tính năng có trong orbiter trong khi nội dung chính vẫn hiển thị. Nhờ orbiter, bạn có thể linh hoạt tích hợp các thành phần hiện có trên giao diện người dùng (chẳng hạn như thanh điều hướng) hoặc tạo ra các thành phần mới.
Ngoài ra, với API Orbiter, bạn có thể hiển thị nội dung của một orbiter ở chế độ bình thường khi chạy trong chế độ Không gian chính hoặc trên một thiết bị không phải là XR và tự động tách nội dung đó vào một orbiter khi chạy ở chế độ Toàn không gian.
Ở chế độ Không gian chính, dải điều hướng này sẽ hiển thị trong bảng điều khiển ứng dụng chính. | Ở chế độ Toàn không gian, dải điều hướng này được chia thành một orbiter gắn với bảng điều khiển chính. |
Tại thời điểm này, ứng dụng sẽ có một nút trong thanh ứng dụng ở trên cùng để chuyển đổi giữa chế độ Không gian chính và chế độ Toàn không gian. Nút này là ví dụ điển hình về một thành phần điều khiển có thể nằm trong một orbiter khi chạy ở chế độ Toàn không gian, vì việc di chuyển thành phần điều khiển để quay quanh bảng điều khiển chính sẽ giúp thành phần điều khiển đó trở nên nổi bật, đồng thời chỉ ra theo cách trực quan rằng thành phần điều khiển sẽ thu gọn nội dung của ứng dụng vào bảng điều khiển đó khi được nhấp vào.
Trạng thái hiện tại | Nội dung bạn sẽ triển khai |
Để tìm hiểu thêm về các điểm cần cân nhắc khi thiết kế cho orbiter, hãy xem bài viết Giao diện người dùng không gian.
4. Thêm một orbiter
Gói nút bật tắt chế độ không gian
Để chuyển nút bật tắt chế độ không gian thành một orbiter, hãy gói thành phần kết hợp ToggleSpaceModeButton
trong thành phần kết hợp Orbiter
.
ui/component/XRFundamentalsTopAppBar .kt
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.EdgeOffset
import androidx.xr.compose.spatial.Orbiter
import androidx.xr.compose.spatial.OrbiterEdge
import androidx.xr.compose.subspace.layout.SpatialRoundedCornerShape
...
Orbiter(
position = OrbiterEdge.Top,
alignment = Alignment.End,
offset = EdgeOffset.inner(16.dp),
shape = SpatialRoundedCornerShape(
CornerSize(percent = 100)
)
) {
ToggleSpaceModeButton()
}
Bây giờ, hãy chạy ứng dụng: Khi chạy ở chế độ Không gian chính, bạn sẽ nhận thấy không có gì thay đổi. Tuy nhiên, khi nhấp vào nút bật tắt và ứng dụng chuyển sang chế độ Toàn không gian, bạn sẽ thấy nút này không còn nằm trong thanh ứng dụng ở trên cùng mà nằm ở cạnh trên cùng bên phải của bảng điều khiển không gian chính.
Orbiter được liên kết với bảng điều khiển không gian chính vì đó là thực thể không gian mẹ gần nhất trong cây giao diện người dùng. Vị trí chính xác của orbiter so với bảng điều khiển không gian chính được xác định bằng các tham số position
, alignment
và offset
. Hãy thử sửa đổi các tham số này để xem chúng hỗ trợ khoảng hành vi nào.
Chế độ Không gian chính | Chế độ Toàn không gian |
5. Tìm hiểu các khái niệm về XR: Môi trường không gian
Việc dùng Orbiter
để tuỳ chỉnh vị trí trong không gian 3D của các phần tử trên giao diện người dùng là một cách hiệu quả để cải thiện trải nghiệm người dùng trên các thiết bị XR. Bạn có thể cải thiện trải nghiệm hơn nữa bằng cách tuỳ chỉnh môi trường không gian mà người dùng nhìn thấy khi dùng ứng dụng của bạn.
Môi trường không gian có thể kết hợp chiều sâu, hoạ tiết và thành phần hình học 3D để tạo ra trải nghiệm hình ảnh phong phú, sống động. Điều này đạt được là nhờ việc sử dụng hình ảnh skybox hình cầu (ở định dạng EXR) để tạo ra một nền toàn cảnh và/hoặc thành phần hình học ở xa (định dạng glTF) nhằm cung cấp các thành phần nền trước và nền giữa có thể phù hợp với skybox. Ví dụ: ứng dụng phát trực tuyến video có thể sử dụng skybox ban đêm với glTF của một rạp chiếu phim ngoài trời có màn hình chiếu và ô tô. Khi tạo các thành phần để thiết lập môi trường không gian cho người dùng, hãy đảm bảo rằng các thành phần có độ phân giải chất lượng cao mà vẫn duy trì kích thước tệp hợp lý. Hãy xem phần Tối ưu hoá thành phần môi trường để biết thêm thông tin.
Ngoài ra, bạn có thể kiểm soát độ mờ của môi trường không gian. Nhờ đó, luồng video thực tế sẽ ở dạng nhìn xuyên qua và hoà lẫn vào môi trường ảo, giúp người dùng không bị mất phương hướng
Trong bước tiếp theo, bạn sẽ thêm một thành phần hình học vào ứng dụng và tạo một trình đơn để người dùng có thể chọn môi trường của họ.
Để biết toàn bộ thông tin chi tiết về việc thiết kế và triển khai môi trường không gian, hãy xem bài viết Môi trường không gian và Thêm môi trường không gian vào ứng dụng.
6. Cho phép người dùng thay đổi môi trường không gian
Cách ứng dụng kiểm soát môi trường không gian
Trước khi bắt đầu, bạn nên tìm hiểu chính xác cách ứng dụng có thể kiểm soát môi trường không gian.
Không giống như nội dung trong bảng điều khiển, ứng dụng không trực tiếp kiểm soát môi trường. Thay vào đó, các ứng dụng có thể tương tác với phiên SceneCore để cung cấp lựa chọn ưu tiên cho môi trường mà ứng dụng muốn hệ thống sử dụng. Lựa chọn ưu tiên này được biểu thị bằng SpatialEnvironmentPreference
, bao gồm một hình ảnh skybox EXR và/hoặc gLTF hình học. Điều sẽ xảy ra khi ứng dụng của bạn cung cấp một lựa chọn ưu tiên phụ thuộc vào các chức năng của ứng dụng tại thời điểm ứng dụng đó đặt lựa chọn ưu tiên. Nếu ứng dụng của bạn có khả năng thay đổi môi trường, thì hệ thống sẽ dùng ngay ứng dụng đó. Nếu không, lựa chọn ưu tiên sẽ được áp dụng khi ứng dụng của bạn có được khả năng đó.
Ví dụ: các ứng dụng thường không có khả năng thay đổi môi trường khi chạy ở chế độ Không gian chính, nhưng lại có thể thay đổi khi chạy ở chế độ Toàn không gian. Vì vậy, nếu bạn cho phép người dùng đặt lựa chọn ưu tiên về môi trường trong chế độ Không gian chính, lựa chọn ưu tiên đó thường sẽ không có hiệu lực cho đến khi ứng dụng của bạn chạy ở chế độ Toàn không gian.
Thêm một phần phụ thuộc vào thư viện XR SceneCore
Để bắt đầu sửa đổi môi trường không gian, hãy thêm một phần phụ thuộc vào thư viện XR SceneCore. Bạn sẽ sử dụng thư viện này để tải các thành phần môi trường và đặt lựa chọn ưu tiên về môi trường. Bạn cũng cần thêm một phần phụ thuộc vào cấu phần phần mềm kotlinx-coroutines-guava
, vì một số API dùng để tải các thành phần sẽ sử dụng loại dữ liệu ListenableFuture
.
libs.version.toml
[versions]
...
xrSceneCore = "1.0.0-alpha04"
kotlinxCoroutinesGuava = "1.10.2"
[libraries]
...
androidx-xr-scenecore = { group = "androidx.xr.scenecore", name = "scenecore", version.ref = "xrSceneCore"}
jetbrains-kotlinx-coroutines-guava = {group = "org.jetbrains.kotlinx", name="kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesGuava"}
app/build.gradle.kts
dependencies {
...
implementation(libs.androidx.xr.scenecore)
implementation(libs.jetbrains.kotlinx.coroutines.guava)
...
}
Thêm một thành phần môi trường vào dự án
Để chỉ định lựa chọn ưu tiên riêng biệt về môi trường, bạn cần một skybox và/hoặc một thành phần hình học. Trong lớp học lập trình này, bạn sẽ chỉ sử dụng thành phần hình học green_hills_ktx2_mipmap.glb
. Bạn có thể tìm thấy thành phần này trong thư mục part2
chứa mã giải pháp hoặc trên GitHub.
- Nhấp chuột phải vào mô-đun ứng dụng trong cửa sổ Project (Dự án) trong Android Studio. Sau đó, chọn New > Folder > Assets Folder (Mới > Thư viện > Thư viện thành phần), sau đó nhấp vào Finish (Hoàn tất) để tạo thư mục.
- Thêm tệp GLB vào thư mục
app/src/main/assets
mà bạn vừa tạo.
Mô hình hoá các lựa chọn về môi trường
Để đơn giản hoá hoạt động tương tác giữa mã giao diện người dùng và API hệ thống, bạn có thể tạo một lớp dữ liệu Kotlin để mô hình hoá từng lựa chọn về môi trường.
- Nhấp chuột phải vào gói
com.example.android.xrfundamentals
trong cửa sổ Project (Dự án) rồi chọn New > Package (Mới > Gói). Nhậpcom.example.android.xrfundamentals.environment
làm tên gói. - Nhấp chuột phải vào gói đó rồi chọn New > Kotlin Class/File (Mới > Lớp/Tệp Kotlin). Nhập
EnvironmentOption
làm tên rồi nhấp vào loại Data class (Lớp dữ liệu). - Thêm mã sau vào tệp bạn vừa tạo:
EnvironmentOption.kt
data class EnvironmentOption(val name: String, val skyboxPath: String?, val geometryPath: String?)
val DEFAULT_ENVIRONMENT = EnvironmentOption("Default", null, null)
val ENVIRONMENT_OPTIONS = listOf(
DEFAULT_ENVIRONMENT,
EnvironmentOption("Green Hills", null, "green_hills_ktx2_mipmap.glb")
)
Thêm một trình trợ giúp để tạo thành phần tải và trả về SpatialEnvironmentPreference
Tiếp theo, bạn có thể thêm một phương thức trợ giúp vào lớp dữ liệu để dễ dàng chuyển đổi EnvironmentOption
thành SpatialEnvrionmentPreference
tương ứng.
EnvironmentOption.kt
import androidx.xr.runtime.Session
import androidx.xr.scenecore.ExrImage
import androidx.xr.scenecore.GltfModel
import androidx.xr.scenecore.SpatialEnvironment
import kotlinx.coroutines.guava.await
...
data class EnvironmentOption(val name: String, val skyboxPath: String?, val geometryPath: String?) {
suspend fun toSpatialEnvironmentPreference(session: Session): SpatialEnvironmentPreference? {
if (skyboxPath == null && geometryPath == null) {
return null
} else {
val skybox = skyboxPath?.let {
ExrImage.create(session, it).await()
}
val geometry = geometryPath?.let {
GltfModel.create(session, it).await()
}
return SpatialEnvironmentPreference(skybox, geometry)
}
}
}
Sau đây là một số điều cần lưu ý:
- Nếu cả skybox và thành phần hình học đều rỗng, giá trị rỗng được trả về để chỉ ra rằng cần sử dụng lựa chọn ưu tiên mặc định về môi trường hệ thống. Hãy xem
setSpatialEnvironmentPreference
để biết thêm thông tin. - Các tài nguyên
skybox
vàgeometry
được tạo không đồng bộ vì những thành phần này có thể thường khá lớn và mất thời gian để đọc vào bộ nhớ. Trong ứng dụng phát hành chính thức, bạn nên cân nhắc lưu những thành phần này vào bộ nhớ đệm nếu thường xuyên chuyển đổi môi trường.
Triển khai giao diện người dùng chọn môi trường
Để triển khai giao diện người dùng, bạn sẽ thêm một orbiter thứ hai xoay qua các lựa chọn về môi trường khi được nhấp vào.
Thêm orbiter
- Nhấp chuột phải vào mô-đun
app
trong cửa sổ Project (Dự án) rồi chọn New > Vector Asset (Mới > Thành phần vectơ). Nhấp vào trường Clip art (Hình mẫu) rồi tìm kiếm và chọn thành phầnlandscape
(từ nhóm biểu tượng Filled (Đã điền)), sau đó nhấp vào OK rồi nhấp vào Next (Tiếp theo) để tạo thành phần. - Nhấp chuột phải vào gói
com.example.android.xrfundamentals.ui.component
rồi chọn New > Kotlin Class/File (Mới > Lớp/Tệp Kotlin). NhậpEnvironmentSelectionOrbiter
làm tên và nhấp vào loại File (Tệp). - Trong tệp bạn vừa tạo, hãy thêm cách triển khai sau đây cho thành phần kết hợp
EnvironmentSelectionOrbiter
EnvironmentSelectionOrbiter.kt
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.EdgeOffset
import androidx.xr.compose.spatial.Orbiter
import androidx.xr.compose.spatial.OrbiterEdge
import androidx.xr.compose.subspace.layout.SpatialRoundedCornerShape
import com.example.android.xrfundamentals.R
@Composable
fun EnvironmentSelectionOrbiter(
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
) {
Orbiter(
position = OrbiterEdge.Top,
alignment = Alignment.Start,
offset = EdgeOffset.inner(16.dp),
shape = SpatialRoundedCornerShape(
CornerSize(100)
)
) {
FilledTonalIconButton(
modifier = modifier,
onClick = onClick,
) {
Icon(painterResource(R.drawable.baseline_landscape_24), "Show environment selection dialog")
}
}
}
- Cuối cùng, hãy thêm
EnvironmentSelectionOrbiter
trong bảng điều khiển không gian chính
XRFundamentalsApp.kt
import androidx.xr.compose.platform.LocalSpatialCapabilities
import com.example.android.xrfundamentals.ui.component.EnvironmentSelectionOrbiter
...
SpatialPanel(...) {
// Only show the environment selection orbiter if the app is actually able to
// change the environment
if (LocalSpatialCapabilities.current.isAppEnvironmentEnabled) {
EnvironmentSelectionOrbiter(
onClick = { TODO() }
)
}
...
}
Thay đổi môi trường khi orbiter được nhấp vào
Để mọi thứ hoạt động, bạn cần thực hiện một bước cuối cùng là gọi setSpatialEnvironmentPreference
trong trình xử lý lượt nhấp EnvironmentSelectionOrbiter
.
- Thiết lập một biến để theo dõi lựa chọn hiện tại về môi trường (bên ngoài
Subspace
để duy trì trạng thái khi chuyển đổi giữa chế độ Không gian chính và chế độ Toàn không gian). Ngoài ra, hãy tạo các biến cho phiên XR hiện tại và phạm vi coroutine để gọi trình trợ giúptoSpatialEnvironmentPreference
XRFundamentalsApp.kt
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.xr.compose.platform.LocalSession
...
var currentEnvironmentOptionIndex by remember { mutableStateOf(0) }
Subspace {
val session = checkNotNull(LocalSession.current)
val scope = rememberCoroutineScope()
...
}
- Triển khai lệnh gọi lại
onClick
để xoay qua các lựa chọn về môi trường.
XRFundamentalsApp.kt
EnvironmentSelectionOrbiter(
onClick = {
scope.launch {
currentEnvironmentOptionIndex =
(currentEnvironmentOptionIndex + 1) % ENVIRONMENT_OPTIONS.size
session.scene.spatialEnvironment.setSpatialEnvironmentPreference(
ENVIRONMENT_OPTIONS[currentEnvironmentOptionIndex].toSpatialEnvironmentPreference(
session
)
)
}
}
)
Chạy ứng dụng một lần nữa và bạn sẽ thấy rằng có thể chuyển đổi giữa Green Hills và môi trường mặc định!
7. Xin chúc mừng
Để tiếp tục tìm hiểu về cách khai thác tối đa XR, hãy tham khảo các tài nguyên và bài tập sau đây:
Tài liệu đọc thêm
- Thiết kế cho XR bao gồm các nguyên tắc thiết kế và phương pháp hay nhất để sử dụng khi tạo ứng dụng cho Android XR.
- Phát triển với SDK Jetpack XR chứa hướng dẫn kỹ thuật về API và các công cụ mà bạn có thể dùng trong quá trình xây dựng trải nghiệm Android.
- Trang Nguyên tắc về chất lượng cho ứng dụng Android XR mô tả các tiêu chí để xây dựng trải nghiệm tuyệt vời cho người dùng.
- Khám phá Mẫu xin chào trong Android XR
Thử thách
- Tìm hoặc tạo thêm các thành phần môi trường rồi thêm các thành phần đó dưới dạng lựa chọn.
- Sửa đổi trình điều khiển môi trường và giao diện người dùng để cho phép người dùng đặt lựa chọn ưu tiên nhìn xuyên qua bằng API
setPassthroughOpacityPreference
. Xin lưu ý rằng việc kiểm soát tính năng nhìn xuyên qua được kiểm soát bằng một chức năng khác so với việc thay đổi các thành phần môi trường.