Nền tảng ứng dụng

Phát triển Thẻ thông tin thành Tiện ích cho Wear bằng Jetpack Glance và Remote Compose

Loa

  • François Deschênes

    Nhà quản lý sản phẩm

  • Yuri Schimke

    Kỹ sư phần mềm

Giới thiệu

Giới thiệu về bài thuyết trình

Trong phiên này, chúng ta sẽ tìm hiểu sâu về kỹ thuật trong quá trình phát triển từ Thẻ thông tin toàn màn hình đến Tiện ích Wear động, có chiều cao một phần.

Chúng ta sẽ khám phá các lợi ích kỹ thuật của Jetpack Glance API hợp nhất và công cụ Remote Compose mới, đồng thời tìm hiểu chi tiết cách các công cụ này kết hợp liền mạch với Quy trình phát triển Android hiện đại.

Cuối cùng, chúng tôi sẽ chia sẻ hướng dẫn mới nhất về trải nghiệm người dùng và hướng dẫn các chiến lược di chuyển thực tế để giúp bạn xây dựng giao diện người dùng dễ đọc thế hệ tiếp theo.

Tóm tắt

  • Wear OS đang phát triển Thẻ thông tin toàn màn hình thành Tiện ích Wear được xây dựng bằng Jetpack Glance và hoạt động dựa trên tính năng Compose từ xa.
  • Remote Compose dùng chung trình biên dịch và thời gian chạy với giao diện người dùng Jetpack Compose, đồng thời tách giao diện người dùng khỏi quy trình ứng dụng một cách an toàn.
  • Kích thước vùng chứa nhỏ và lớn phù hợp với định dạng lưới dành cho thiết bị di động, trong khi API Jetpack Glance Wear duy trì khả năng tương thích ngược với Wear 4.
  • Để di chuyển Thẻ thông tin hiện có sang tiện ích, bạn có thể sử dụng chiến lược dịch vụ kép được đề xuất hoặc một dịch vụ tương thích duy nhất.

Kỹ năng

Tài nguyên

Gemini Notebook

Chủ đề

  • wear-os
  • wear-widgets
  • jetpack-glance
  • remote-compose
  • tiles-migration
  • jetpack-compose

Bản chép lời

Giới thiệu

  • Chào mọi người.

  • Tôi là Frank, hiện đang phụ trách mảng trải nghiệm xem nhanh cho Wear OS.

  • Đồng hồ là người bạn đồng hành thiết yếu, luôn bên cạnh người dùng suốt cả ngày. Hôm nay, chúng tôi sẽ hướng dẫn bạn cách tận dụng trải nghiệm mới của Tiện ích Wear.

  • Chúng ta sẽ xem xét hai cách để cung cấp các tính năng quan trọng nhất ngay trên cổ tay của người dùng, và chúng ta sẽ làm như vậy bằng cách sử dụng các API mới nhất, những API được thiết kế để giúp các nhà phát triển Android như bạn cảm thấy quen thuộc và trực quan khi xây dựng cho Wear OS.

  • Tham gia cùng tôi trên sân khấu hôm nay để tìm hiểu chính xác cách chúng tôi thực hiện việc này là Yuri, người đồng nghiệp và người bạn cùng bàn tuyệt vời của tôi.

  • Xin chào, tôi là Yuri Schimke.

  • Tôi là kỹ sư trong nhóm Wear OS và công việc chính của tôi là phát triển Remote Compose API.

  • Hôm nay, tôi sẽ giới thiệu nhanh về Remote Compose và cũng nói về quy trình di chuyển từ Thẻ thông tin sang Tiện ích Wear.

  • Bây giờ, tôi xin nhường lời lại cho Frank.

Phát triển Thẻ thông tin thành Tiện ích cho Wear

  • Tuyệt vời.

  • Cảm ơn Yuri.

  • Chúng tôi chính thức đưa thiết bị đeo vào hệ sinh thái tiện ích Android hợp nhất bằng cách phát triển Thẻ thông tin toàn màn hình thành Tiện ích Wear.

  • Và vì những trải nghiệm này hiện được xây dựng bằng Jetpack Glance, nên bạn có thể thấy rằng đây chính là cơ sở hạ tầng cơ bản được dùng cho các tiện ích di động.

  • Bạn sẽ thấy rằng việc xây dựng cho Wear sẽ ngày càng trở nên quen thuộc hơn với bạn trong tương lai.

Tổng quan về Remote Compose

  • Để hỗ trợ những trải nghiệm này, chúng tôi đang phát triển ngăn xếp giao diện người dùng, tức là ngăn xếp giao diện người dùng cơ bản.

  • Tiện ích Wear hoạt động dựa trên Remote Compose, một khung Android mới cho giao diện người dùng từ xa.

  • Điều này có nghĩa là cuối cùng bạn có thể sử dụng một API khai báo phù hợp với Jetpack Compose để xây dựng trải nghiệm bên ngoài ứng dụng, chẳng hạn như tiện ích.

  • Remote Compose mang đến đồ hoạ hiện đại và bố cục thích ứng cho các tiện ích, đồng thời đảm bảo hiệu suất và mức sử dụng pin hiệu quả.

  • Và bằng cách tách giao diện người dùng khỏi quy trình ứng dụng, các tiện ích của bạn sẽ được chuyển đổi tuần tự một cách an toàn và dễ dàng hiển thị trên nhiều thiết bị Android.

  • Điều này có nghĩa là bạn có thể mang trải nghiệm phong phú này đến hầu hết các nền tảng từ xa được hỗ trợ mà không tốn nhiều công sức.

Kích thước bố cục và khả năng tương thích ngược

  • Để quá trình chuyển đổi từ Thẻ thông tin sang tiện ích diễn ra suôn sẻ nhất có thể, chúng tôi sẽ ra mắt hai kích thước vùng chứa tiêu chuẩn: nhỏ và lớn.

  • Các mẫu này được thiết kế để phù hợp với định dạng tiện ích dựa trên lưới 2x1 và 2x2 mà bạn đã quen thuộc khi tạo tiện ích trên thiết bị di động.

  • Kể từ Wear 7 trên một số nhà sản xuất phần cứng, Tiện ích Wear của bạn giờ đây sẽ nằm trong một khay cuộn dọc cùng với tiện ích của các ứng dụng khác.

  • Ví dụ: đây là giao diện của Tiện ích Wear trên Samsung Galaxy Watch.

  • Kiến trúc nền tảng được xây dựng để hỗ trợ khay cuộn dọc khi các nhà sản xuất phần cứng áp dụng mẫu này trong tương lai.

  • Và bạn không cần phải lo lắng về việc bỏ sót bất kỳ người dùng nào, kể cả người dùng hiện tại.

  • Các API Jetpack Glance Wear được thiết kế để hỗ trợ khả năng tương thích ngược xuống Wear 4.

  • Trên các thiết bị cũ hỗ trợ khay tiện ích hoặc Thẻ thông tin theo chiều ngang, hệ thống sẽ xử lý việc đó cho bạn.

  • Bạn chỉ cần nêu trong mã rằng bạn muốn hỗ trợ chế độ toàn màn hình, và hệ thống sẽ lấy tiện ích lớn của bạn rồi hiển thị tiện ích đó dưới dạng Thẻ thông tin truyền thống toàn màn hình trên các thiết bị này.

  • Bây giờ, Yuri sẽ hướng dẫn chúng ta xem mã để cho bạn biết chính xác cách di chuyển Thẻ thông tin hiện có sang Tiện ích cho Wear.

Chiến lược di chuyển cho các thẻ thông tin hiện có

  • Cảm ơn Frank.

  • Nếu bạn đang tạo một Tiện ích Wear mới từ đầu, thì việc này rất đơn giản.

  • Bạn chỉ cần xác định GlanceWearWidgetService và xây dựng giao diện người dùng bằng Remote Compose.

  • Tuy nhiên, nếu ứng dụng của bạn đã có Thẻ thông tin trong phiên bản chính thức, thì bạn cần di chuyển cả dịch vụ, giao diện người dùng và dữ liệu.

  • Để quá trình chuyển đổi này diễn ra suôn sẻ nhất có thể, chúng tôi đã cung cấp các lộ trình để đảm bảo trải nghiệm liền mạch cho người dùng hiện tại.

  • Đối với dịch vụ, bạn có thể chọn một trong hai chiến lược: dịch vụ kép hoặc dịch vụ đơn.

  • Với dịch vụ kép (phương án nên dùng), bạn sẽ giữ lại TileService hiện có cho các thiết bị Wear OS cũ và thêm một GlanceWearWidgetService mới cho Wear OS 7 trở lên.

  • Ngược lại, với dịch vụ đơn, bạn tạo một GlanceWearWidgetService mới, duy nhất xử lý cả hai giao thức, chạy ở chế độ tương thích để dịch tiện ích của bạn thành Thẻ thông tin trên các thiết bị cũ.

  • Dù bằng cách nào, bạn cũng sẽ tiếp tục tiếp cận được người dùng.

  • Việc này chỉ ảnh hưởng đến mã mà bạn duy trì trong tương lai.

  • Chúng tôi cũng vừa xuất bản tài liệu toàn diện trên trang web dành cho nhà phát triển Android, trong đó trình bày chi tiết về cách thức và thời điểm sử dụng cả hai mẫu này.

  • Hãy xem để tìm hiểu thêm về chiến lược phù hợp nhất với ứng dụng của bạn.

Xây dựng giao diện người dùng bằng Remote Compose

  • Bây giờ, hãy nói về lớp giao diện người dùng.

  • Khi di chuyển, mô hình tư duy của bạn sẽ thay đổi.

  • Trước đây, các thẻ thông tin sử dụng ProtoLayout, một thư viện được xây dựng riêng cho thẻ thông tin Wear.

  • Mặt khác, Tiện ích cho Wear OS được xây dựng dựa trên Remote Compose.

  • Remote Compose có cùng nền tảng với giao diện người dùng Jetpack Compose, sử dụng cùng một trình biên dịch và thời gian chạy cốt lõi.

  • Thư viện này được thiết kế để mang lại cảm giác quen thuộc, gần giống với các thư viện Giao diện người dùng Compose như Foundation và Material 3.

  • Nhưng thay vì hộp, cột hoặc văn bản, bạn chỉ cần hoán đổi chúng cho RemoteBox, RemoteColumn hoặc RemoteText.

  • Trong trường hợp này, bạn sẽ quen với việc viết "remote" (từ xa) rất nhiều.

  • Ngoài ra, để đẩy nhanh quy trình làm việc, chúng tôi đã cung cấp một bộ đầy đủ các thành phần Remote Compose sẵn sàng sử dụng, được thiết kế riêng cho tiện ích.

  • Điều này có nghĩa là bạn có thể dễ dàng điều chỉnh các thiết kế Wear Material 3 hiện có (bao gồm cả những thiết kế trong Figma) cho phù hợp với tiện ích, giúp cả kỹ sư và nhà thiết kế đều quen thuộc với tiện ích.

  • Để xem mức độ tương đồng giữa các khung này, hãy cùng xem một ví dụ cụ thể.

  • Chúng ta sẽ xây dựng thành phần ứng dụng của riêng mình dựa trên nút chuyển Material 3.

  • Ở bên trái, chúng ta có thành phần Wear Compose chuẩn mà bạn sẽ viết bên trong ứng dụng, còn ở bên phải là phiên bản Remote Compose.

    // Wear Compose
    @Composable
    fun HistoryEraserButton(
      onClick: () -> Unit,
      modifier: Modifier = Modifier,
      checked: Boolean = true,
      onCheckedChange: (Boolean) -> Unit = {},
    )
    // Wear RemoteCompose
    @RemoteComposable
    @Composable
    fun RemoteHistoryEraserButton(
      onClick: Action,
      modifier: RemoteModifier = RemoteModifier,
      checked: RemoteBoolean = true.rb,
      onCheckedChange: Action = Action.Empty,
    )
  • Hãy lưu ý sự tương đồng giữa các mẫu.

  • Tuy nhiên, khi viết mã Remote Compose, bạn sẽ sử dụng chú thích RemoteComposable.

  • Và khi bạn sử dụng các tham số quen thuộc như đối tượng sửa đổi và boolean, chúng sẽ có các loại Remote Compose tương đương như RemoteModifier và RemoteBoolean.

  • Và bạn sử dụng các hành động thay vì lambda.

  • Thay vì xác định mã cần thực thi bên trong lambda, bạn cần khai báo một hành động, chẳng hạn như khởi chạy ý định đang chờ xử lý, gọi dịch vụ hoặc cập nhật giá trị.

  • Hãy chuyển đến phần nội dung của thành phần.

  • Bạn sẽ nhận thấy ngay cả giao diện cũng được điều chỉnh cho phù hợp.

  • Bạn có thể áp dụng bảng phối màu Material 3 cho thành phần Remote Compose giống hệt như trong Compose tiêu chuẩn, giúp tiện ích của bạn khớp chính xác với thương hiệu của ứng dụng.

    // Wear Compose
      val colors = MaterialTheme.colorScheme
      SplitSwitchButton(
        checked = checked,
        onCheckedChange = onCheckedChange,
        toggleContentDescription = "Arm Eraser",
        onContainerClick = onClick,
        modifier = modifier.fillMaxWidth(),
        colors =
          SwitchButtonDefaults.splitSwitchButtonColors(
            checkedContainerColor = colors.errorContainer, …
          ),
        label = { Text("History Eraser") },
        secondaryLabel = { Text("Don't touch it!") },
      )
    // Wear RemoteCompose
      val colors = RemoteMaterialTheme.colorScheme
      RemoteSplitSwitchButton(
        checked = checked,
        onCheckedChange = onCheckedChange,
        toggleContentDescription = "Arm Eraser".rs,
        onContainerClick = onClick,
        modifier = modifier.fillMaxWidth(),
        colors =
          RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
            checkedContainerColor = colors.errorContainer, …
          ),
        label = { RemoteText("History Eraser".rs) },
        secondaryLabel = { RemoteText("Don't touch it!".rs) },
      )
  • Cuối cùng, hãy xem kết quả. Giao diện người dùng thu được chính xác là những gì bạn mong đợi, một nút bật tắt rõ ràng, thích ứng và có ảnh động.

Hỗ trợ bản xem trước trong Compose cho các tiện ích

  • Thật khó để nhận biết sự khác biệt.

  • Để giúp bạn thiết kế, lặp lại và xác minh bố cục tiện ích mà không cần phải luôn chạy trên thiết bị hoặc trình mô phỏng, chúng tôi đã thêm tính năng hỗ trợ xem trước Compose cho Tiện ích Wear.

  • Vì tiện ích phụ thuộc vào các quy tắc ràng buộc về vùng chứa dành riêng cho OEM (chẳng hạn như kích thước, hình dạng, khoảng đệm, bán kính góc), nên chúng tôi xây dựng dựa trên chú thích xem trước tiêu chuẩn, nhưng có thêm một trình cung cấp tham số để chèn các cấu hình này.

    @Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
    @Composable
    fun WeatherWidgetSquirclePreview(
        @PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
    ) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
    
    @Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
    @Composable
    fun WeatherWidgetRoundPreview(
        @PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
    ) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
  • Thư viện này cung cấp các phương thức triển khai nhà cung cấp PreviewParameter được định cấu hình sẵn, phù hợp với các thiết bị Wear OS thực tế.

  • Các chú thích xem trước này giúp bạn dễ dàng xác minh bố cục của mình trên nhiều hình dạng phần cứng khác nhau.

  • Ngoài việc kiểm thử bố cục, bạn có thể sử dụng các bản xem trước này để tạo hình ảnh tĩnh cần thiết cho bộ chọn tiện ích trên thiết bị.

    @Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
    @Composable
    fun WeatherWidgetRectangularPreview(
        @PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
    ) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
  • Thư viện này cung cấp một tham số cho hình dạng xem trước hình chữ nhật, mô phỏng vùng chứa hình chữ nhật đầy đủ chưa cắt.

Công cụ triển khai và di chuyển mẫu

  • Nếu bạn muốn xem chính xác cách hoạt động của API này trong thực tế, hãy xem ứng dụng mẫu Horologist Media mà chúng tôi đã làm mới để thêm một tiện ích mới minh hoạ API này.

  • Chúng tôi sẽ hướng dẫn cách thêm cả phiên bản nhỏ và lớn của tiện ích nội dung nghe nhìn.

  • Hãy xem trên GitHub để so sánh mã ProtoLayout cũ và cách triển khai Remote Compose mới.

  • Chúng tôi chắc chắn bạn sẽ thích.

  • Cuối cùng, đây sẽ không phải là một, bạn biết đấy, một bài nói chuyện mà không đề cập đến AI.

  • Để giúp bạn di chuyển nhanh hơn, chúng tôi đã phát hành một kỹ năng di chuyển từ thẻ thông tin sang tiện ích mới trên GitHub.

  • Bạn có thể sử dụng công cụ này với tác nhân mà bạn chọn hoặc có thể thêm trực tiếp vào Android Studio bằng Android CLI.

    android skills add wear-widgets
    android skills add --all
  • Bây giờ, tôi xin mời François trở lại để tổng kết.

Tóm tắt và kết thúc

  • Cảm ơn bạn.

  • Cảm ơn Yuri.

  • Như bạn có thể thấy, việc phát triển thẻ thông tin thành Tiện ích cho Wear là một quy trình rất đơn giản.

  • Tóm lại, bằng cách di chuyển sang Jetpack Glance Wear và Remote Compose, bạn không chỉ cập nhật giao diện người dùng mà còn tham gia vào một hệ sinh thái tiện ích Android hợp nhất hơn.

  • Giờ đây, bạn có thể tạo các tiện ích đẹp mắt, có khả năng tương thích ngược bằng một khung khai báo hiện đại, hoàn toàn phù hợp với Jetpack Compose.

  • Bạn có thể bắt đầu di chuyển thẻ ngay hôm nay bằng cách truy cập vào hướng dẫn bắt đầu sử dụng trên trang web dành cho Nhà phát triển Android để biết thêm thông tin chi tiết.

  • Chúng tôi rất mong được thấy tất cả những trải nghiệm giàu biểu cảm, dễ nắm bắt mà bạn xây dựng cho thiết bị đeo tay.

  • Cảm ơn các bạn rất nhiều vì đã tham gia cùng chúng tôi hôm nay, sáng nay và chúng tôi hy vọng các bạn sẽ thích phần còn lại của hội nghị.

  • Cảm ơn bạn.

Mã

Đoạn mã

Đoạn mã Kotlin ở phút 06:40 trong video "Xây dựng giao diện người dùng bằng Remote Compose"
// Wear Compose
@Composable
fun HistoryEraserButton(
  onClick: () -> Unit,
  modifier: Modifier = Modifier,
  checked: Boolean = true,
  onCheckedChange: (Boolean) -> Unit = {},
)
Đoạn mã Kotlin ở phút 06:40 trong video "Xây dựng giao diện người dùng bằng Remote Compose"
// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
  onClick: Action,
  modifier: RemoteModifier = RemoteModifier,
  checked: RemoteBoolean = true.rb,
  onCheckedChange: Action = Action.Empty,
)
Đoạn mã Kotlin ở phút 07:39 trong video "Xây dựng giao diện người dùng bằng Remote Compose"
// Wear Compose
  val colors = MaterialTheme.colorScheme
  SplitSwitchButton(
    checked = checked,
    onCheckedChange = onCheckedChange,
    toggleContentDescription = "Arm Eraser",
    onContainerClick = onClick,
    modifier = modifier.fillMaxWidth(),
    colors =
      SwitchButtonDefaults.splitSwitchButtonColors(
        checkedContainerColor = colors.errorContainer, …
      ),
    label = { Text("History Eraser") },
    secondaryLabel = { Text("Don't touch it!") },
  )
Đoạn mã Kotlin ở phút 07:39 trong video "Xây dựng giao diện người dùng bằng Remote Compose"
// Wear RemoteCompose
  val colors = RemoteMaterialTheme.colorScheme
  RemoteSplitSwitchButton(
    checked = checked,
    onCheckedChange = onCheckedChange,
    toggleContentDescription = "Arm Eraser".rs,
    onContainerClick = onClick,
    modifier = modifier.fillMaxWidth(),
    colors =
      RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
        checkedContainerColor = colors.errorContainer, …
      ),
    label = { RemoteText("History Eraser".rs) },
    secondaryLabel = { RemoteText("Don't touch it!".rs) },
  )
Đoạn mã Kotlin ở phút 08:20 trong video "Hỗ trợ xem trước tiện ích trong Compose"
@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
    @PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)

@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
    @PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
Đoạn mã Kotlin ở phút 08:58 trong video "Hỗ trợ xem trước Compose cho tiện ích"
@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
    @PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
Đoạn mã shell ở phút 09:58 trong phần "Công cụ di chuyển và triển khai mẫu"
android skills add wear-widgets
android skills add --all