Ứng dụng luôn bật và chế độ môi trường xung quanh của hệ thống

Hướng dẫn này giải thích cách làm cho ứng dụng của bạn luôn bật, cách phản ứng với các trạng thái chuyển đổi nguồn và cách quản lý hành vi của ứng dụng để mang lại trải nghiệm tốt cho người dùng trong khi tiết kiệm pin.

Việc cho phép một ứng dụng liên tục xuất hiện sẽ ảnh hưởng đáng kể đến thời lượng pin, vì vậy bạn hãy cân nhắc mức tiêu thụ điện năng khi thêm tính năng này.

Khái niệm chính

Khi một ứng dụng Wear OS xuất hiện ở chế độ toàn màn hình, ứng dụng đó sẽ ở một trong hai trạng thái nguồn sau:

  • Tương tác: Trạng thái công suất cao, trong đó màn hình ở độ sáng tối đa, cho phép người dùng tương tác đầy đủ.
  • Môi trường xung quanh: Trạng thái tiêu thụ ít điện năng, trong đó màn hình sẽ mờ đi để tiết kiệm pin. Ở trạng thái này, giao diện người dùng của ứng dụng vẫn chiếm toàn bộ màn hình, nhưng hệ thống có thể thay đổi giao diện bằng cách làm mờ hoặc hiển thị nội dung lớp phủ như thời gian. Đây còn được gọi là Chế độ môi trường xung quanh.

Hệ điều hành kiểm soát quá trình chuyển đổi giữa các trạng thái này.

Ứng dụng luôn bật là ứng dụng hiển thị nội dung ở cả trạng thái Tương tácMôi trường xung quanh.

Khi một ứng dụng luôn bật tiếp tục hiển thị giao diện người dùng của riêng ứng dụng đó trong khi thiết bị ở trạng thái Môi trường xung quanh có mức sử dụng điện năng thấp, ứng dụng đó được mô tả là đang ở chế độ ambiactive.

Chuyển đổi hệ thống và hành vi mặc định

Khi một ứng dụng chạy ở nền trước, hệ thống sẽ quản lý các quá trình chuyển đổi trạng thái nguồn dựa trên 2 khoảng thời gian chờ do người dùng không hoạt động kích hoạt.

  • Thời gian chờ 1: Trạng thái Tương tác sang trạng thái Môi trường xung quanh: Sau một khoảng thời gian không hoạt động, thiết bị sẽ chuyển sang trạng thái Môi trường xung quanh.
  • Thời gian chờ #2: Trở về mặt đồng hồ: Sau một khoảng thời gian không hoạt động nữa, hệ thống có thể ẩn ứng dụng hiện tại và hiển thị mặt đồng hồ.

Ngay sau khi hệ thống chuyển đổi lần đầu tiên sang trạng thái Môi trường xung quanh, hành vi mặc định sẽ phụ thuộc vào phiên bản Wear OS và cấu hình của ứng dụng:

  • Trên Wear OS 5 trở xuống, hệ thống sẽ hiển thị ảnh chụp màn hình bị mờ của ứng dụng đang tạm dừng, với thời gian được phủ lên trên. Trạng thái này được biểu thị bằng nút "AOD Lite" trong sơ đồ quy trình sau.
  • Trên Wear OS 6 trở lên, nếu một ứng dụng nhắm đến SDK 36 trở lên, thì ứng dụng đó sẽ được coi là luôn bật. Màn hình sẽ mờ đi nhưng ứng dụng vẫn tiếp tục chạy và hiển thị. (Thông tin cập nhật có thể không thường xuyên, chẳng hạn như chỉ một lần mỗi phút.) Trạng thái này được biểu thị bằng nút "Global AOD" trong sơ đồ quy trình sau.

Tuỳ chỉnh hành vi cho trạng thái Môi trường xung quanh

Bất kể hành vi mặc định của hệ thống là gì, trên tất cả các phiên bản Wear OS, bạn đều có thể tuỳ chỉnh giao diện hoặc hành vi của ứng dụng khi ở trạng thái Môi trường xung quanh bằng cách sử dụng LocalAmbientModeManager để quan sát các quá trình chuyển đổi trạng thái trong Jetpack Compose trên Wear OS. Trạng thái này được biểu thị bằng nút "Chế độ Ambiactive" trong sơ đồ quy trình sau.

Quan sát trạng thái môi trường xung quanh

Cách phản ứng với các sự kiện ở chế độ xung quanh trong Jetpack Compose trên Wear OS:

  1. Sử dụng LocalAmbientModeManager để theo dõi các thay đổi về trạng thái chế độ xung quanh của hệ thống, từ đó điều chỉnh các thành phần kết hợp cho phù hợp. Định cấu hình thành phần để điều chỉnh sang chế độ tiêu thụ ít điện năng hơn ở trạng thái AmbientMode.Ambient và khôi phục thành phần đó về chế độ hiển thị tương tác đầy đủ ở trạng thái AmbientMode.Interactive.

    // In a production application, the AmbientModeManager should be instantiated and provided at
    // the highest level of the Compose hierarchy (typically in the host Activity's setContent
    // block) using a CompositionLocalProvider. This ensures proper lifecycle management and
    // broad accessibility.
    
    // For this self-contained demo, AmbientModeManager is created and provided locally:
    val activityAmbientModeManager = rememberAmbientModeManager()
    CompositionLocalProvider(LocalAmbientModeManager provides activityAmbientModeManager) {
        val ambientModeManager = LocalAmbientModeManager.current
        val ambientMode = ambientModeManager?.currentAmbientMode
    
        if (ambientModeManager != null) {
            ambientModeManager.AmbientTickEffect {
                // While device is in ambient mode, update properties every minute or so
                // ...
            }
        }
    
        // ...
            val ambientModeName =
                when (ambientMode) {
                    is AmbientMode.Interactive -> "Interactive"
                    is AmbientMode.Ambient -> "Ambient"
                    else -> "Unknown"
                }
    
            Text(text = "$ambientModeName Mode")
            // ...
    }

Đối với những nhà phát triển sử dụng Jetpack Compose, hãy dùng LocalAmbientModeManager. Thao tác này sẽ đơn giản hoá việc triển khai mẫu này.

Lưu đồ hành vi xung quanh

Sơ đồ quy trình sau đây minh hoạ cách hệ thống xác định hành vi ở chế độ xung quanh dựa trên phiên bản Wear OS của thiết bị, targetSdkVersion của ứng dụng và việc ứng dụng có triển khai AmbientLifecycleCallback hay không.

Sơ đồ quy trình minh hoạ logic quyết định cho chế độ môi trường xung quanh của Wear OS. Ví dụ này cho thấy phiên bản hệ điều hành của thiết bị và cấu hình của ứng dụng xác định một trong 3 kết quả: lớp phủ bị mờ, AOD toàn cầu hoặc Chế độ Ambiactive do ứng dụng quản lý.
Hình 1.: Sơ đồ quy trình minh hoạ logic quyết định cho chế độ môi trường xung quanh trên Wear OS.

Kiểm soát thời lượng bật màn hình

Các phần sau đây mô tả cách quản lý thời gian ứng dụng của bạn xuất hiện trên màn hình.

Ngăn người dùng quay lại mặt đồng hồ bằng một Hoạt động đang diễn ra hoặc Thông tin cập nhật trực tiếp

Sau một khoảng thời gian ở trạng thái Môi trường xung quanh (Hết thời gian chờ 2), hệ thống thường sẽ quay lại mặt đồng hồ. Người dùng có thể định cấu hình khoảng thời gian chờ trong phần cài đặt hệ thống. Đối với một số trường hợp sử dụng, chẳng hạn như khi người dùng theo dõi một bài tập thể dục, ứng dụng có thể cần duy trì trạng thái hiển thị lâu hơn.

Trên Wear OS 5 trở lên, bạn có thể ngăn chặn điều này bằng cách triển khai một OngoingActivity. Nếu ứng dụng của bạn đang hiển thị thông tin về một tác vụ đang diễn ra của người dùng (chẳng hạn như một phiên tập thể dục), thì bạn có thể dùng Ongoing Activity API để giữ cho ứng dụng của bạn hiển thị cho đến khi tác vụ kết thúc. Nếu người dùng tự quay lại mặt đồng hồ, chỉ báo hoạt động đang diễn ra sẽ cung cấp một cách thức để họ quay lại ứng dụng của bạn chỉ bằng một lần nhấn.

Ngoài ra, trên Wear OS 7 trở lên, bạn có thể sử dụng Thông tin cập nhật trực tiếp thay cho Hoạt động đang diễn ra. Để có khả năng tương thích ngược, hãy tiếp tục hỗ trợ Hoạt động đang diễn ra trên các thiết bị chạy Wear OS 6 trở xuống.

Để triển khai việc này, ý định chạm của thông báo hiển thị liên tục phải trỏ đến hoạt động luôn bật của bạn, như minh hoạ trong đoạn mã sau:

val activityIntent =
    Intent(this, AlwaysOnActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
    }

val pendingIntent =
    PendingIntent.getActivity(
        this,
        0,
        activityIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
    )

val notificationBuilder =
    NotificationCompat.Builder(this, CHANNEL_ID)
        // ...
        // ...
        .setOngoing(true)

// ...

val ongoingActivity =
    OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder)
        // ...
        // ...
        .setTouchIntent(pendingIntent)
        .build()

ongoingActivity.apply(applicationContext)

val notification = notificationBuilder.build()

Giữ màn hình luôn bật và ngăn Chế độ hiển thị thông minh

Trong một số ít trường hợp, bạn có thể cần ngăn hoàn toàn thiết bị chuyển sang trạng thái Môi trường xung quanh. Tức là để tránh hết thời gian chờ số 1. Để làm việc này, bạn có thể sử dụng đối tượng sửa đổi keepScreenOn. Hàm này hoạt động như một khoá chế độ thức, giữ thiết bị ở trạng thái Interactive. Hãy sử dụng tính năng này một cách thận trọng vì nó ảnh hưởng nghiêm trọng đến thời lượng pin.

Đề xuất cho Chế độ môi trường xung quanh

Để mang lại trải nghiệm tốt nhất cho người dùng và tiết kiệm pin ở chế độ Môi trường xung quanh, hãy tuân thủ các nguyên tắc thiết kế này. Những đề xuất này ưu tiên trải nghiệm rõ ràng cho người dùng bằng cách ngăn chặn thông tin sai lệch và giảm bớt sự lộn xộn về hình ảnh, đồng thời tối ưu hoá sức mạnh hiển thị.

  • Giảm tình trạng rối mắt và mức tiêu thụ điện của màn hình. Giao diện người dùng tối giản, gọn gàng cho người dùng biết rằng ứng dụng đang ở trạng thái tiêu thụ ít năng lượng và tiết kiệm đáng kể pin bằng cách giới hạn các pixel sáng.
    • Giữ ít nhất 85% màn hình ở trạng thái màu đen.
    • Chỉ hiển thị thông tin quan trọng nhất, chuyển các thông tin chi tiết thứ cấp sang màn hình tương tác.
    • Sử dụng đường viền cho các biểu tượng hoặc nút lớn thay vì màu tô đồng nhất.
    • Tránh sử dụng các khối màu đồng nhất lớn và hình ảnh thương hiệu hoặc hình nền không có chức năng.
  • Xử lý dữ liệu động lỗi thời
    • Lệnh gọi lại AmbientTickEffect chỉ được gọi định kỳ (thường là một lần mỗi phút) để tiết kiệm pin. Do hạn chế này, mọi dữ liệu thay đổi thường xuyên (chẳng hạn như đồng hồ bấm giờ, tần số tim hoặc khoảng cách tập luyện) sẽ trở nên cũ giữa các lần cập nhật. Để tránh hiển thị thông tin sai lệch và không chính xác, hãy thay thế các giá trị trực tiếp này bằng nội dung tĩnh của phần giữ chỗ, chẳng hạn như --.
  • Duy trì bố cục nhất quán
    • Giữ các phần tử ở cùng một vị trí trong chế độ Tương tácMôi trường xung quanh để tạo hiệu ứng chuyển đổi mượt mà.
    • Luôn hiển thị thời gian.
  • Nắm bắt bối cảnh
    • Nếu người dùng đang ở trên màn hình cài đặt hoặc cấu hình khi thiết bị chuyển sang chế độ môi trường xung quanh, hãy cân nhắc việc hiển thị một màn hình phù hợp hơn trong ứng dụng của bạn thay vì chế độ xem cài đặt.
  • Xử lý các yêu cầu cụ thể theo thiết bị
    • Trong đối tượng AmbientMode được trả về từ currentAmbientMode:
      • Nếu isLowBitAmbientSupportedtrue, hãy tắt tính năng khử răng cưa khi có thể.
      • Nếu isBurnInProtectionRequiredtrue, hãy định kỳ di chuyển nhẹ các phần tử giao diện người dùng và tránh các vùng màu trắng đồng nhất để ngăn hiện tượng lưu ảnh trên màn hình.

Gỡ lỗi và thử nghiệm

Các lệnh adb này có thể hữu ích khi bạn phát triển hoặc kiểm thử cách ứng dụng hoạt động khi thiết bị ở chế độ xung quanh:

# put device in ambient mode if the always on display is enabled in settings
# (and not disabled by other settings, such as theatre mode)
$ adb shell input keyevent KEYCODE_SLEEP

# put device in interactive mode
$ adb shell input keyevent KEYCODE_WAKEUP

Ví dụ: Ứng dụng tập luyện

Hãy cân nhắc một ứng dụng tập thể dục cần hiển thị các chỉ số cho người dùng trong toàn bộ thời gian của phiên tập thể dục. Ứng dụng phải luôn hiển thị trong quá trình chuyển đổi trạng thái Môi trường xung quanh và tránh bị mặt đồng hồ thay thế.

Để đạt được điều này, nhà phát triển cần làm như sau:

  1. Sử dụng LocalAmbientModeManager để xử lý các thay đổi về giao diện người dùng giữa các trạng thái Tương tácMôi trường xung quanh, chẳng hạn như làm mờ màn hình và xoá dữ liệu không cần thiết.
  2. Tạo một bố cục mới có mức sử dụng điện năng thấp cho trạng thái Môi trường xung quanh theo các phương pháp hay nhất.
  3. Sử dụng Ongoing Activity API (hoặc Thông tin cập nhật trực tiếp trên Wear OS 7 trở lên) trong suốt thời gian tập luyện để ngăn hệ thống quay lại mặt đồng hồ.

Để xem cách triển khai đầy đủ, hãy xem Mẫu bài tập thể dục dựa trên Compose trên GitHub. Mẫu này cũng minh hoạ việc sử dụng thành phần kết hợp LocalAmbientModeManager để đơn giản hoá việc xử lý chế độ môi trường xung quanh trong Compose.