Các thiết bị Wear OS thường được dùng cho những trải nghiệm kéo dài, chẳng hạn như theo dõi một buổi tập luyện. Điều này gây ra một thách thức về trải nghiệm người dùng: nếu người dùng bắt đầu một tác vụ rồi chuyển hướng đến mặt đồng hồ, thì làm cách nào để họ quay lại? Việc quay lại ứng dụng bằng trình chạy có thể gây khó khăn, đặc biệt là khi đang di chuyển, tạo ra những trở ngại không cần thiết.
Giải pháp là ghép nối một thông báo hiển thị liên tục với một OngoingActivity
.
Nhờ đó, thiết bị có thể hiển thị thông tin về hoạt động chạy trong thời gian dài trên giao diện người dùng, cho phép các tính năng như biểu tượng nhấn vào được ở cuối mặt đồng hồ. Điều này giúp người dùng biết về tác vụ ở chế độ nền và cung cấp cách thức chỉ cần một lần nhấn để quay lại ứng dụng.
Ví dụ: trong ứng dụng tập thể dục này, thông tin có thể xuất hiện trên mặt đồng hồ của người dùng dưới dạng biểu tượng đang chạy có thể nhấn vào:
Hình 1. Chỉ báo hoạt động
Thông báo đang diễn ra cũng hiển thị thông tin trong phần Recents (Gần đây) của trình chạy ứng dụng chung. Nhờ đó, người dùng có thêm một nơi thuận tiện để xem trạng thái của nhiệm vụ và tương tác lại với ứng dụng:
Hình 2. Global launcher (Trình chạy chung)
Sau đây là các tình huống phù hợp để sử dụng một thông báo hiển thị liên tục gắn liền với hoạt động đang diễn ra:
Hình 3. Bộ hẹn giờ: Chủ động đếm ngược thời gian và kết thúc khi bộ hẹn giờ tạm dừng hoặc dừng.
Hình 4. Chỉ đường từng chặng: Thông báo chỉ đường đến một điểm đến. Kết thúc khi người dùng đến điểm đến hoặc ngừng điều hướng.
Hình 5. Nội dung nghe nhìn: Phát nhạc trong một phiên. Kết thúc ngay sau khi người dùng tạm dừng phiên.
Wear tự động tạo các hoạt động đang diễn ra cho ứng dụng đa phương tiện.
Hãy xem lớp học lập trình về Hoạt động đang diễn ra để tìm hiểu ví dụ chuyên sâu về cách tạo hoạt động đang diễn ra cho các loại ứng dụng khác.
Thiết lập
Để bắt đầu sử dụng Ongoing Activity API (API Hoạt động đang diễn ra) trong ứng dụng, hãy thêm các phần phụ thuộc sau vào tệp build.gradle
của ứng dụng:
dependencies {
implementation "androidx.wear:wear-ongoing:1.1.0"
implementation "androidx.core:core:1.17.0"
}
Tạo một hoạt động đang diễn ra
Quy trình này bao gồm 3 bước:
- Tạo một
NotificationCompat.Builder
tiêu chuẩn và định cấu hìnhNotificationCompat.Builder
đó ở trạng thái đang diễn ra. - Tạo và định cấu hình một đối tượng
OngoingActivity
, truyền trình tạo thông báo đến đối tượng đó. - Áp dụng hoạt động đang diễn ra cho trình tạo thông báo và đăng thông báo kết quả.
Tạo và định cấu hình thông báo
Hãy bắt đầu bằng cách tạo một NotificationCompat.Builder
. Bước quan trọng là gọi setOngoing(true)
để đánh dấu thông báo đó là thông báo liên tục. Bạn cũng có thể đặt các thuộc tính thông báo khác ở giai đoạn này, chẳng hạn như biểu tượng nhỏ và danh mục.
// Create a PendingIntent to pass to the notification builder val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Always On Service") .setContentText("Service is running in background") .setSmallIcon(R.drawable.animated_walk) // Category helps the system prioritize the ongoing activity .setCategory(NotificationCompat.CATEGORY_WORKOUT) .setContentIntent(pendingIntent) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true) // Important!
Tạo OngoingActivity
Tiếp theo, hãy tạo một thực thể của OngoingActivity
bằng trình tạo tương ứng. OngoingActivity.Builder
yêu cầu Context
, mã thông báo và NotificationCompat.Builder
mà bạn đã tạo ở bước trước.
Định cấu hình các thuộc tính chính sẽ xuất hiện trên giao diện người dùng mới:
- Biểu tượng động và tĩnh: Cung cấp các biểu tượng xuất hiện trên mặt đồng hồ ở chế độ đang hoạt động và chế độ môi trường xung quanh.
- Ý định nhấn: Một
PendingIntent
đưa người dùng trở lại ứng dụng của bạn khi họ nhấn vào biểu tượng hoạt động đang diễn ra. Bạn có thể sử dụng lạipendingIndent
được tạo ở bước trước.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // Sets the icon that appears on the watch face in active mode. .setAnimatedIcon(R.drawable.animated_walk) // Sets the icon that appears on the watch face in ambient mode. .setStaticIcon(R.drawable.ic_walk) // Sets the tap target to bring the user back to the app. .setTouchIntent(pendingIntent) .build()
Áp dụng cho thông báo và bài đăng
Bước cuối cùng là liên kết OngoingActivity
với thông báo rồi đăng thông báo đó. Phương thức ongoingActivity.apply()
sửa đổi trình tạo thông báo ban đầu, thêm dữ liệu cần thiết để hệ thống có thể hiển thị thông báo đó trên các nền tảng bổ sung. Sau khi áp dụng, bạn có thể tạo và đăng thông báo như bình thường.
// This call modifies notificationBuilder to include the ongoing activity data. ongoingActivity.apply(applicationContext) // Post the notification. startForeground(NOTIFICATION_ID, notificationBuilder.build())
Thêm văn bản trạng thái động vào trình chạy
Đoạn mã trên sẽ thêm biểu tượng có thể nhấn vào mặt đồng hồ. Để cung cấp thông tin cập nhật theo thời gian thực, phong phú hơn nữa trong mục Gần đây của trình chạy, hãy tạo một đối tượng Status
và đính kèm đối tượng đó vào OngoingActivity
. Nếu bạn không cung cấp Status
tuỳ chỉnh, hệ thống sẽ mặc định sử dụng văn bản nội dung của thông báo (được đặt bằng setContentText()
).
Để hiển thị văn bản động, hãy sử dụng Status.Builder
. Bạn có thể xác định một chuỗi mẫu bằng phần giữ chỗ và cung cấp các đối tượng Status.Part
để điền vào các phần giữ chỗ đó. Status.Part
có thể là một giá trị động, chẳng hạn như đồng hồ bấm giờ hoặc bộ hẹn giờ .
Ví dụ sau đây minh hoạ cách tạo một trạng thái hiển thị "Chạy trong [một bộ hẹn giờ bấm giờ]":
// Define a template with placeholders for the activity type and the timer. val statusTemplate = "#type# for #time#" // Set the start time for a stopwatch. // Use SystemClock.elapsedRealtime() for time-based parts. val runStartTime = SystemClock.elapsedRealtime() val ongoingActivityStatus = Status.Builder() // Sets the template string. .addTemplate(statusTemplate) // Fills the #type# placeholder with a static text part. .addPart("type", Status.TextPart("Run")) // Fills the #time# placeholder with a stopwatch part. .addPart("time", Status.StopwatchPart(runStartTime)) .build()
Cuối cùng, hãy liên kết Status
này với OngoingActivity
bằng cách gọi setStatus()
trên OngoingActivity.Builder
.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // Add the status to the OngoingActivity. .setStatus(ongoingActivityStatus) .build()
Chế độ tuỳ chỉnh khác
Ngoài Status
, bạn có thể tuỳ chỉnh hoạt động đang diễn ra hoặc thông báo hiển thị liên tục theo những cách sau. Tuy nhiên, các cách tuỳ chỉnh này có thể không được sử dụng dựa trên cách triển khai của OEM.
Thông báo hiển thị liên tục
- Tập hợp danh mục xác định mức độ ưu tiên của hoạt động đang diễn ra.
CATEGORY_CALL
: cuộc gọi thoại, cuộc gọi video đến hoặc yêu cầu giao tiếp đồng bộ tương tựCATEGORY_NAVIGATION
: bản đồ hoặc tính năng chỉ đường từng chặng.CATEGORY_TRANSPORT
: trình điều khiển truyền tải nội dung nghe nhìn để phát lạiCATEGORY_ALARM
: chuông báo hoặc đồng hồ hẹn giờCATEGORY_WORKOUT
: một bài tập thể dụcCATEGORY_LOCATION_SHARING
: chia sẻ vị trí tạm thời (danh mục mới)CATEGORY_STOPWATCH
: đồng hồ bấm giờ
Hoạt động đang diễn ra
Animated icon (Biểu tượng động): vectơ màu đen trắng, tốt nhất là có nền trong suốt. Hiện trên mặt đồng hồ ở chế độ đang hoạt động. Nếu bạn không cung cấp biểu tượng động thì biểu tượng thông báo mặc định sẽ được sử dụng. Biểu tượng thông báo mặc định của mỗi ứng dụng sẽ khác nhau.
Static icon (Biểu tượng tĩnh): biểu tượng vectơ có nền trong suốt. Hiện trên mặt đồng hồ ở chế độ môi trường xung quanh. Nếu bạn không đặt biểu tượng động thì biểu tượng tĩnh sẽ được dùng trên mặt đồng hồ cho chế độ đang hoạt động. Nếu bạn không đặt biểu tượng này thì hệ thống sẽ sử dụng biểu tượng thông báo. Nếu bạn không đặt biểu tượng nào thì hệ thống sẽ gửi một trường hợp ngoại lệ. (Trình chạy ứng dụng vẫn sử dụng biểu tượng ứng dụng.)
OngoingActivityStatus: văn bản thuần tuý hoặc
Chronometer
. Hiện trong mục Recents(Gần đây) của trình chạy ứng dụng. Hệ thống sẽ sử dụng thông báo bằng "văn bản theo ngữ cảnh" nếu trạng thái không được cung cấp.Touch Intent (Ý định nhấn): một
PendingIntent
dùng để chuyển trở lại ứng dụng nếu người dùng nhấn vào biểu tượng hoạt động đang diễn ra. Hiện trên mặt đồng hồ hoặc trên mục trình chạy. Ý định này có thể khác với ý định ban đầu dùng để chạy ứng dụng. Nếu không được cung cấp, hệ thống sẽ sử dụng ý định nội dung của thông báo. Nếu bạn không đặt biểu tượng nào thì hệ thống sẽ gửi một trường hợp ngoại lệ.LocusId
: Mã nhận dạng chỉ định lối tắt của trình chạy tương ứng với hoạt động đang diễn ra. Hiện trên trình chạy ở mục Recents (Gần đây) trong khi hoạt động đang diễn ra. Nếu mã không được cung cấp, trình chạy sẽ ẩn toàn bộ mục của ứng dụng trong mục Recents (Gần đây) khỏi gói chung và chỉ hiện hoạt động đang diễn ra.Ongoing Activity ID (Mã nhận dạng hoạt động đang diễn ra): Mã được dùng để phân biệt các lệnh gọi tới
fromExistingOngoingActivity()
khi một ứng dụng có nhiều hoạt động đang diễn ra.
Cập nhật một hoạt động đang diễn ra
Trong hầu hết các trường hợp, nhà phát triển sẽ tạo một thông báo mới hiển thị liên tục và một hoạt động mới đang diễn ra khi họ cần cập nhật dữ liệu trên màn hình. Tuy nhiên, Ongoing Activity API (API Hoạt động đang diễn ra) cũng cung cấp các phương thức trợ giúp để cập nhật OngoingActivity
nếu bạn muốn giữ lại một thực thể thay vì tạo lại thực thể đó.
Nếu đang chạy ở chế độ nền thì ứng dụng có thể gửi các bản cập nhật cho Ongoing Activity API (API Hoạt động đang diễn ra). Tuy nhiên, đừng thực hiện thao tác này quá thường xuyên vì phương thức cập nhật sẽ bỏ qua các lệnh gọi quá gần nhau. Mỗi phút một vài bản cập nhật là hợp lý.
Để cập nhật hoạt động đang diễn ra và thông báo đã được đăng, hãy sử dụng đối tượng mà bạn đã tạo trước đó rồi gọi update()
như ví dụ sau:
ongoingActivity.update(context, newStatus)
Để thuận tiện, bạn có thể dùng phương thức tĩnh tạo hoạt động đang diễn ra.
OngoingActivity.recoverOngoingActivity(context)
.update(context, newStatus)
Dừng một hoạt động đang diễn ra
Khi hoàn tất quá trình chạy dưới dạng một hoạt động đang diễn ra, ứng dụng chỉ cần huỷ thông báo hiển thị liên tục.
Bạn cũng có thể chọn huỷ thông báo hiển thị liên tục hoặc hoạt động đang diễn ra khi chạy trên nền trước, sau đó tạo lại các thông báo hoặc hoạt động này khi quay lại chế độ nền nhưng điều này là không bắt buộc.
Tạm dừng một hoạt động đang diễn ra
Nếu ứng dụng của bạn dừng một cách rõ ràng, hãy tiếp tục hoạt động đang diễn ra sau khi ứng dụng chạy trở lại. Đối với ứng dụng không dừng một cách rõ ràng, hãy kết thúc hoạt động đó khi ứng dụng bị tạm dừng.
Các phương pháp hay nhất
Hãy nhớ những điều sau khi làm việc với Ongoing Activity API (API Hoạt động đang diễn ra):
Đặt biểu tượng tĩnh cho Hoạt động đang diễn ra của bạn một cách rõ ràng hoặc đặt dưới dạng trường hợp dự phòng bằng cách sử dụng thông báo. Nếu không, bạn sẽ nhận được một
IllegalArgumentException
.Sử dụng biểu tượng vectơ đen trắng có nền trong suốt.
Đặt ý định nhấn cho hoạt động đang diễn ra của bạn một cách rõ ràng hoặc dưới dạng trường hợp dự phòng bằng cách sử dụng thông báo. Nếu không, bạn sẽ nhận được một
IllegalArgumentException
.Nếu ứng dụng của bạn có nhiều hoạt động
MAIN LAUNCHER
được khai báo trong tệp kê khai, hãy xuất bản một lối tắt động và liên kết lối tắt này với hoạt động đang diễn ra bằng cách sử dụngLocusId
.
Xuất bản thông báo về nội dung nghe nhìn khi phát nội dung nghe nhìn trên thiết bị Wear OS
Nếu nội dung nghe nhìn đang phát trên một thiết bị Wear OS, hãy xuất bản một thông báo về nội dung nghe nhìn. Điều này giúp hệ thống tạo hoạt động đang diễn ra tương ứng.
Nếu bạn đang dùng Media3, thông báo sẽ được xuất bản tự động. Nếu bạn tạo thông báo theo cách thủ công, thông báo đó sẽ sử dụng MediaStyleNotificationHelper.MediaStyle
và MediaSession
tương ứng phải điền sẵn hoạt động trong phiên.
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Tạo thông báo {:#notification}
- Thu hút người dùng Wear OS theo những cách mới thông qua Ongoing Activity API
- Tạo một thông báo có thể mở rộng {:#expandable-notification}