Hướng dẫn

Đưa Androidify lên XR bằng Jetpack XR SDK

Đọc trong 9 phút
Dereck Bridie
Kỹ sư Quan hệ với nhà phát triển

Samsung Galaxy XR đã ra mắt, chạy trên Android XR! Bài đăng này trên blog nằm trong Tuần lễ giới thiệu Android XR. Trong tuần lễ này, chúng tôi cung cấp các tài nguyên (bài đăng trên blog, video, mã mẫu và nhiều tài nguyên khác) nhằm giúp bạn tìm hiểu, xây dựng và chuẩn bị ứng dụng cho Android XR.

Với việc ra mắt Samsung Galaxy XR , thiết bị đầu tiên chạy Android XR đã chính thức xuất hiện. Giờ đây, mọi người có thể thưởng thức nhiều ứng dụng yêu thích của mình trên Cửa hàng Play ở một khía cạnh hoàn toàn mới: không gian ba chiều!

Chiều thứ ba là một chiều không gian rộng rãi, có nhiều chỗ cho các ứng dụng của bạn. Hãy bắt đầu ngay hôm nay bằng cách sử dụng bất kỳ công cụ nào phù hợp với ứng dụng của bạn. Ví dụ: bạn có thể dùng SDK Jetpack XR để tạo trải nghiệm XR sống động bằng các công cụ phát triển Android hiện đại như Kotlin và Compose.

Trong bài đăng này trên blog, chúng tôi sẽ kể cho bạn nghe về hành trình của chính mình khi đưa sự độc đáo của ứng dụng Androidify mà chúng tôi yêu thích lên XR, đồng thời trình bày những kiến thức cơ bản cần thiết để đưa ứng dụng của bạn lên XR.

Khám phá Androidify

Androidify là một ứng dụng nguồn mở cho phép bạn tạo các bot Android bằng một số công nghệ mới nhất như Gemini, CameraX, Navigation 3 và tất nhiên là Jetpack Compose. Ban đầu, Androidify được thiết kế để có giao diện bắt mắt trên điện thoại, thiết bị có thể gập lại và máy tính bảng bằng cách tạo bố cục thích ứng.

customize.png

Androidify trông rất đẹp trên nhiều kiểu dáng

Một trụ cột chính của bố cục thích ứng là các thành phần kết hợp có thể sử dụng lại. Jetpack Compose giúp bạn tạo các thành phần giao diện người dùng có kích thước nhỏ có thể được bố trí theo nhiều cách để tạo trải nghiệm người dùng trực quan, bất kể người dùng đang sử dụng loại thiết bị nào. Trên thực tế, Androidify tương thích với Android XR mà không cần sửa đổi ứng dụng!

customize_2.png

Androidify thích ứng với XR bằng cách sử dụng bố cục đáp ứng màn hình lớn mà không cần thay đổi mã

Các ứng dụng không có chế độ xử lý đặc biệt cho Android XR có thể thực hiện nhiều việc cùng lúc trong một cửa sổ có kích thước phù hợp và hoạt động giống như trên màn hình lớn. Do đó, Androidify đã có đầy đủ tính năng trên Android XR mà không cần làm gì thêm! Tuy nhiên, chúng tôi không muốn dừng lại ở đó, nên đã quyết định nỗ lực hơn nữa và tạo ra một ứng dụng có sự khác biệt về XR để mang đến trải nghiệm thú vị cho người dùng XR.

Định hướng bản thân trong XR

Hãy cùng tìm hiểu các khái niệm cơ bản chính cho Android XR, bắt đầu bằng 2 chế độ mà ứng dụng có thể chạy: Không gian chính và Toàn bộ không gian.

homespace.png
Các ứng dụng trong Không gian chính
homespace2.png
Ứng dụng ở chế độ Toàn bộ không gian

Trong Không gian chính, nhiều ứng dụng có thể chạy song song để người dùng có thể làm nhiều việc trên nhiều cửa sổ. Theo nghĩa đó, chế độ này giống như chế độ cửa sổ kiểu máy tính trên một thiết bị Android có màn hình lớn, nhưng ở không gian ảo!

Ở chế độ Toàn bộ không gian, ứng dụng không bị giới hạn về không gian và có thể tận dụng toàn bộ các tính năng không gian của Android XR, chẳng hạn như giao diện người dùng không gian và khả năng kiểm soát môi trường ảo.

Mặc dù có thể bạn muốn ứng dụng của mình chỉ chạy ở chế độ Toàn bộ không gian, nhưng người dùng có thể muốn làm nhiều việc cùng lúc với ứng dụng của bạn, vì vậy, việc hỗ trợ cả hai chế độ sẽ mang lại trải nghiệm tốt hơn cho người dùng.

Thiết kế cho chiều hướng mới của Androidify

Một ứng dụng thú vị bắt đầu từ một thiết kế tuyệt vời. Ivy Knight, Chuyên gia tư vấn cấp cao về thiết kế tại nhóm Android DevRel, đã đảm nhận nhiệm vụ lấy các thiết kế hiện có cho Androidify và đưa ra một thiết kế mới cho XR. Mời Ivy!

Thiết kế cho XR đòi hỏi một phương pháp độc đáo, nhưng thực tế vẫn có nhiều điểm chung với thiết kế cho thiết bị di động. Chúng tôi bắt đầu bằng cách nghĩ về việc tạo vách ngăn: cách sắp xếp và nhóm các phần tử giao diện người dùng trong không gian con, bằng cách thể hiện rõ ràng ranh giới hoặc ngụ ý một cách tinh tế. Chúng tôi cũng học được cách sử dụng tất cả các kích thước khác nhau của các phần tử giao diện người dùng không gian. Các phần tử này được thiết kế để điều chỉnh và di chuyển theo phản ứng của người dùng. Như chúng ta đã làm với Androidify, hãy xây dựng bằng bố cục thích ứng để bạn có thể chia bố cục thành nhiều phần cho giao diện người dùng không gian.

Bắt đầu thiết kế bằng Không gian chính

May mắn thay, Android XR cho phép bạn bắt đầu với ứng dụng hiện tại cho Không gian chính, vì vậy, chúng ta có thể chuyển sang các thiết kế XR mở rộng bằng cách chỉ cần thêm một thanh công cụ cửa sổ và nút chuyển đổi Toàn bộ không gian.

Chúng tôi cũng xem xét các tính năng phần cứng có thể có và cách người dùng tương tác với các tính năng đó. Bố cục trên thiết bị di động của Androidify thích ứng với nhiều tư thế, kích thước lớp và số lượng camera để mang đến nhiều lựa chọn chụp ảnh hơn. Theo mô hình này, chúng tôi cũng phải điều chỉnh bố cục camera cho các thiết bị tai nghe. Chúng tôi cũng cần điều chỉnh để văn bản hoạt động nhằm tính đến khoảng cách giữa giao diện người dùng và người dùng.

Thiết kế cho sự thay đổi lớn hơn đối với chế độ Toàn bộ không gian

Toàn bộ không gian là thay đổi lớn nhất, nhưng lại mang đến cho chúng tôi không gian sáng tạo nhất để điều chỉnh thiết kế. 

tablet_to_xr.webp
Từ máy tính bảng đến XR

Androidify sử dụng vùng chứa trực quan (hoặc ngăn) để nhóm các tính năng có nền và đường viền, chẳng hạn như ngăn "Chụp hoặc chọn ảnh". Chúng tôi cũng sử dụng các thành phần như thanh ứng dụng trên cùng để tạo vùng chứa tự nhiên bằng cách đóng khung các ngăn khác. Cuối cùng, tính năng ngăn chặn nội tại được đề xuất bằng cách đặt một số phần tử gần với các phần tử khác, chẳng hạn như nút dưới cùng "Bắt đầu biến đổi" nằm gần ngăn "Chọn màu cho bot của tôi".

Bảng điều khiển không gian được thiết kế để dễ dàng tách biệt. Để quyết định cách điều chỉnh thiết kế cho thiết bị di động cho các bảng điều khiển không gian, hãy thử xoá các bề mặt bắt đầu từ bề mặt ở xa nhất rồi di chuyển về phía trước. Xem bạn có thể xoá bao nhiêu nền và những gì còn lại. Sau khi chúng tôi thực hiện bài tập này cho Androidify, hình nguệch ngoạc màu xanh lục lớn của Android là thứ còn lại. Đường ngoằn ngoèo không chỉ đóng vai trò là khoảnh khắc xây dựng thương hiệu và nền mà còn là điểm neo cho nội dung trong không gian 3D.

Việc thiết lập điểm neo này giúp chúng tôi dễ dàng hình dung cách các phần tử có thể di chuyển xung quanh điểm neo đó, cũng như cách chúng tôi có thể sử dụng khoảng cách để tách biệt và chuyển đổi phần còn lại của trải nghiệm người dùng.

Các mẹo thiết kế khác giúp ứng dụng của bạn có không gian

  • Để mọi thứ không bị gò bó: Tách các thành phần và tạo cho chúng một không gian thực (không gian). Đã đến lúc tạo khoảng trống cho các phần tử trên giao diện người dùng đó.
  • Xoá bề mặt: Ẩn nền để xem điều gì sẽ xảy ra với thiết kế của bạn.
  • Tạo động lực bằng chuyển động: Bạn đang sử dụng hiệu ứng chuyển đổi như thế nào trong ứng dụng của mình? Hãy dùng nhân vật đó để tưởng tượng ứng dụng của bạn sẽ xuất hiện trong thực tế ảo.
  • Chọn một điểm neo: Đừng để người dùng bị lạc trong không gian. Có một phần tử giúp thu thập hoặc đặt nền tảng cho giao diện người dùng.

Để biết thêm về các mẫu thiết kế giao diện người dùng XR, hãy xem bài viết Thiết kế cho Android XR trên trang Android Developers.

Kiến thức cơ bản về giao diện người dùng không gian

Giờ đây, khi chúng ta đã tìm hiểu về trải nghiệm của Ivy trong việc điều chỉnh tư duy khi thiết kế Androidify cho XR, hãy cùng thảo luận về việc phát triển giao diện người dùng không gian. Việc phát triển giao diện người dùng không gian bằng Jetpack XR SDK sẽ quen thuộc nếu bạn đã quen làm việc với các công cụ và thư viện Android hiện đại. Bạn sẽ thấy những khái niệm mà mình đã quen thuộc, chẳng hạn như tạo bố cục bằng Compose. Trên thực tế, bố cục không gian rất giống với bố cục 2D khi dùng hàng, cột và khoảng trống:

spatialrows.png

Các phần tử này được sắp xếp theo SpatialRows và SpatialColumns

Các phần tử không gian xuất hiện ở đây là thành phần kết hợp SpatialPanel. Thành phần này cho phép bạn hiển thị nội dung 2D như văn bản, nút và video.

  Subspace {
    SpatialPanel(
        SubspaceModifier
            .height(824.dp)
            .width(1400.dp)
    ) {
        Text("I'm a panel!")
    }
}

SpatialPanel là một thành phần kết hợp không gian con. Các thành phần kết hợp không gian con phải nằm trong một Không gian con và được sửa đổi bằng các đối tượng SubspaceModifier. Bạn có thể đặt không gian phụ ở bất kỳ vị trí nào trong hệ phân cấp giao diện người dùng của ứng dụng và chỉ có thể chứa các thành phần kết hợp Không gian phụ. Các đối tượng SubspaceModifier cũng rất giống với các đối tượng Modifier: chúng kiểm soát các tham số như kích thước và vị trí.

Bạn có thể đính kèm Orbiter  vào SpatialPanel và di chuyển cùng với nội dung mà nó được đính kèm. Các chú thích này thường được dùng để cung cấp chế độ kiểm soát theo bối cảnh về nội dung mà chúng được đính kèm, giúp nội dung trở thành trọng tâm chính. Bạn có thể đặt các đường viền này ở bất kỳ vị trí nào trong số 4 cạnh của nội dung, ở một khoảng cách có thể định cấu hình.

orbiter.png
Orbiter được gắn vào cuối SpatialPanel

Có nhiều phần tử giao diện người dùng không gian khác, nhưng đây là những phần tử chính mà chúng tôi dùng để tạo bố cục không gian cho Androidify.

Bắt đầu phát triển XR

Hãy bắt đầu với việc thiết lập dự án. Chúng tôi đã thêm phần phụ thuộc Jetpack XR Compose. Bạn có thể tìm thấy phần phụ thuộc này trên trang Phần phụ thuộc Jetpack XR.

Chúng tôi đã thêm mã cho một nút chuyển người dùng sang chế độ Toàn bộ không gian, bắt đầu bằng việc phát hiện khả năng thực hiện việc này:

  @Composable
fun couldRequestFullSpace(): Boolean =
   LocalSpatialConfiguration.current.hasXrSpatialFeature && 
   !LocalSpatialCapabilities.current.isSpatialUiEnabled
}

Sau đó, chúng tôi tạo một thành phần nút mới sử dụng biểu tượng Mở rộng nội dung cho các bố cục hiện có và đặt hành vi onClick cho nút này:

  @Composable

fun RequestFullSpaceIconButton() {
   if (!couldRequestFullSpace()) return
   val session = LocalSession.current ?: return

   IconButton(
       onClick = {
           session.scene.requestFullSpaceMode()
       },
   ) {
       Icon(
           imageVector =  
               vectorResource(R.drawable.expand_content_24px),
           contentDescription = 
               stringResource("To Full Space"),
       )
   }
}

Giờ đây, khi bạn nhấp vào nút đó, bố cục Trung bình sẽ xuất hiện ở chế độ Toàn bộ không gian. Chúng ta có thể kiểm tra các chức năng không gian và xác định xem có thể hiển thị giao diện người dùng không gian hay không. Trong trường hợp đó, chúng ta sẽ hiển thị bố cục không gian mới:

  @Composable

fun HomeScreenContents(layoutType: HomeScreenLayoutType) {
   val layoutType = when {
      LocalSpatialCapabilities.current.isSpatialUiEnabled -> 
          HomeScreenLayoutType.Spatial
      isAtLeastMedium() -> HomeScreenLayoutType.Medium
      else -> HomeScreenLayoutType.Compact
   }

   when (layoutType) {
      HomeScreenLayoutType.Compact ->
          HomeScreenCompactPager(...)

      HomeScreenLayoutType.Medium ->
          HomeScreenMediumContents(...)

      HomeScreenLayoutType.Spatial ->
          HomeScreenContentsSpatial(...)
   }
}

Triển khai thiết kế cho Màn hình chính

Hãy quay lại thiết kế không gian cho Màn hình chính ở chế độ Toàn bộ không gian để tìm hiểu cách triển khai thiết kế này.

customize_3.png

Chúng ta xác định được 2 phần tử SpatialPanel ở đây: một bảng điều khiển chứa thẻ video ở bên phải và một bảng điều khiển chứa giao diện người dùng chính. Cuối cùng, có một Orbiter được gắn ở trên cùng. Hãy bắt đầu với bảng điều khiển trình phát video:

  @Composable
fun HomeScreenContentsSpatial(...) {
   Subspace {
      SpatialPanel(SubspaceModifier
                   .fillMaxWidth(0.2f)
                   .fillMaxHeight(0.8f)
                   .aspectRatio(0.77f)
                   .rotate(0f, 0f, 5f),
      ) {
          VideoPlayer(videoLink)
      }
   }
}

Chúng tôi chỉ cần dùng lại thành phần VideoPlayer 2D từ bố cục thông thường vào một SpatialPanel mà không cần thay đổi gì thêm! Đây là hình ảnh minh hoạ khi nút này xuất hiện độc lập:

bluetiel.png

Ngăn nội dung chính cũng có câu chuyện tương tự: chúng tôi đã sử dụng lại nội dung ngăn trung bình trong một SpatialPanel.

  SpatialPanel(SubspaceModifier.fillMaxSize(),
             resizePolicy = ResizePolicy(
                 shouldMaintainAspectRatio = true
             ),
             dragPolicy = MovePolicy()
) {
    Box {
        FillBackground(R.drawable.squiggle_full)
        HomeScreenSpatialMainContent(...)
    }
}

Chúng ta đã cung cấp cho bảng điều khiển này một ResizePolicy (Chính sách đổi kích thước), giúp bảng điều khiển có một số ô điều khiển gần các cạnh để người dùng có thể đổi kích thước bảng điều khiển. Thanh này cũng có một MovePolicy, cho phép người dùng kéo thanh này xung quanh.

customize_4.png

Việc đặt chúng vào cùng một Subspace sẽ khiến chúng độc lập với nhau, vì vậy, chúng ta sẽ đặt bảng VideoPlayer làm bảng con của bảng nội dung chính. Điều này khiến bảng VideoPlayer di chuyển khi bảng nội dung chính được kéo thông qua mối quan hệ mẹ con.

  @Composable
fun HomeScreenContentsSpatial(...) {
   Subspace {
       SpatialPanel(SubspaceModifier..., resizePolicy, dragPolicy) {
           Box {
               FillBackground(R.drawable.squiggle_full)
               HomeScreenSpatialMainContent(...)
           }
           Subspace {
              SpatialPanel(SubspaceModifier...) {
                  VideoPlayer(videoLink)
              }
           }
       }
   }
}

Đó là cách chúng tôi tạo màn hình đầu tiên!

Chuyển sang các màn hình khác

Tôi cũng sẽ trình bày ngắn gọn về một số màn hình khác, đồng thời nêu bật những điểm cần cân nhắc cụ thể cho từng màn hình.

fullspace.png
Màn hình sáng tạo ở chế độ Toàn bộ không gian

Ở đây, chúng ta đã dùng các thành phần kết hợp SpatialRow và SpatialColumn để tạo bố cục phù hợp với không gian xem được đề xuất, đồng thời sử dụng lại các thành phần trong bố cục Medium.

fullspace_2.png

Màn hình kết quả ở chế độ toàn màn hình: Một bot được tạo bằng câu lệnh: mũ bóng chày màu đỏ, kính râm phi công, áo phông màu xanh dương nhạt, quần soóc kẻ ô màu đỏ và trắng, dép xỏ ngón màu xanh lục và đang cầm vợt quần vợt.


Màn hình kết quả cho thấy các câu trích dẫn bổ sung bằng hiệu ứng làm mờ, cho phép các câu trích dẫn này mờ dần ở gần các cạnh của màn hình. Ứng dụng này cũng sử dụng hiệu ứng chuyển đổi 3D thực tế khi xem thông tin đầu vào đã dùng, lật hình ảnh trong không gian.

Phát hành lên Cửa hàng Google Play

Giờ đây, ứng dụng đã sẵn sàng cho XR với bố cục không gian, chúng tôi tiếp tục phát hành ứng dụng này lên Cửa hàng Play. Có một thay đổi quan trọng cuối cùng mà chúng tôi đã thực hiện đối với tệp AndroidManifest.xml của ứng dụng:

  <!-- Androidify can use XR features if they're available; they're not required. -->
<uses-feature android:name="android.software.xr.api.spatial" 
              android:required="false" />

Nhờ đó, Cửa hàng Play sẽ biết rằng ứng dụng này có các tính năng dành riêng cho XR, đồng thời hiển thị một huy hiệu cho người dùng biết rằng ứng dụng được tạo ra có tính đến XR:

androidify2.png
Androidify xuất hiện trong Cửa hàng Google Play trên Android XR


Khi tải bản phát hành lên, chúng ta không cần thực hiện bất kỳ bước đặc biệt nào để phát hành cho XR: ứng dụng đó được phân phối bình thường cho người dùng trên kênh di động cũng như người dùng trên thiết bị XR! Tuy nhiên, bạn có thể chọn thêm ảnh chụp màn hình dành riêng cho XR của ứng dụng, hoặc thậm chí tải bản xem trước sống động của ứng dụng lên bằng cách sử dụng một thành phần video không gian. Trên thiết bị Android XR, Cửa hàng Play sẽ tự động hiển thị nội dung này dưới dạng bản xem trước 3D sống động, cho phép người dùng trải nghiệm độ sâu và quy mô của nội dung trước khi cài đặt ứng dụng.

Bắt đầu xây dựng trải nghiệm của riêng bạn ngay hôm nay

Androidify là một ví dụ điển hình về cách chuyển đổi một ứng dụng 2D Jetpack Compose hiện có sang không gian 3D. Hôm nay, chúng tôi đã trình bày toàn bộ quy trình phát triển giao diện người dùng không gian cho Androidify, từ thiết kế đến mã và xuất bản. Chúng tôi đã sửa đổi các thiết kế hiện có để hoạt động với các mô hình không gian, sử dụng các thành phần kết hợp SpatialPanel và Orbiter để tạo bố cục không gian xuất hiện khi người dùng chuyển sang chế độ Toàn bộ không gian, và cuối cùng, chúng tôi đã phát hành phiên bản mới của ứng dụng trên Cửa hàng Play.

Chúng tôi hy vọng bài đăng này trên blog đã giúp bạn hiểu cách đưa ứng dụng của riêng mình vào Android XR! Sau đây là một số đường liên kết khác có thể giúp bạn:

Tác giả:

Tiếp tục đọc