1. Hiện dữ liệu của bạn cho các chức năng
Lớp học lập trình này sẽ hướng dẫn bạn cách tạo nguồn dữ liệu cho chức năng.
Ý tưởng và thiết lập
Sau khi kết thúc lớp học lập trình, bạn sẽ biết cách cung cấp dữ liệu cho các chức năng mặt đồng hồ trên Wear OS.
Khái niệm
Chức năng (complication) là một tính năng của mặt đồng hồ ngoài giờ và phút. Ví dụ: mặt đồng hồ trên hình ảnh dưới đây có bốn chức năng.
API Chức năng dành cho cả ứng dụng mặt đồng hồ và ứng dụng nguồn dữ liệu:
- Nguồn dữ liệu chức năng cung cấp dữ liệu, chẳng hạn như mức pin, thời tiết, số bước, v.v.
- Nhà phát triển mặt đồng hồ có thể hiển thị dữ liệu đó trong một chức năng trên mặt đồng hồ của họ
- Người dùng chọn nguồn dữ liệu họ muốn cho các chức năng của mình
Trong lớp học lập trình này, chúng tôi đề cập đến việc tạo nguồn dữ liệu chức năng. Nếu bạn cũng muốn thêm các chức năng vào mặt đồng hồ, hãy xem mẫu mặt đồng hồ.
Hãy bắt đầu!
Nhân bản kho lưu trữ dự án ban đầu
Để giúp bạn nhanh chóng bắt đầu, chúng tôi đã chuẩn bị một dự án để bạn dựa vào đó mà xây dựng ứng dụng. Dự án này chứa một số mã cơ bản và các tuỳ chọn cài đặt ứng dụng cần thiết cho lớp học lập trình này.
Nếu bạn đã cài đặt Git, hãy chạy lệnh dưới đây. (Bạn có thể kiểm tra xem Git đã cài đặt chưa bằng cách nhập git --version
vào Terminal/dòng lệnh và xác minh lệnh đó thực thi đúng cách):
git clone https://github.com/android/codelab-complications-data-source.git
Nếu không có Git, bạn có thể tải dự án xuống dưới dạng tệp zip:
Nhập dự án
Khởi động Android Studio rồi chọn "Open an existing Android Studio project" (Mở dự án Android Studio hiện có) từ màn hình Chào mừng. Mở thư mục dự án và nhấp đúp vào tệp build.gradle
trong thư mục complications-data-source.
Ở góc trên bên trái cửa sổ dự án, nếu đang ở chế độ xem Android, bạn sẽ thấy một tập hợp các biểu tượng thư mục tương tự các biểu tượng trong ảnh chụp màn hình bên dưới. (Nếu bạn đang ở chế độ xem Project (Dự án), hãy mở rộng dự án complications-data-source để xem tập hợp các biểu tượng trong thư mục.)
Có hai biểu tượng thư mục. Cả hai đều đại diện cho một mô-đun. Hãy lưu ý Android Studio có thể mất vài giây để biên dịch dự án ở chế độ nền trong lần đầu tiên. Trong khoảng thời gian này, bạn sẽ thấy một vòng quay trong thanh trạng thái ở phía dưới Android Studio:
Chờ cho đến khi các quy trình kết thúc trước khi thực hiện thay đổi mã, để cho phép Android Studio lấy tất cả các thành phần cần thiết.
Tìm hiểu về dự án ban đầu
Bạn đã thiết lập và sẵn sàng bắt đầu tiết lộ dữ liệu cho các chức năng. Chúng ta sẽ bắt đầu từ mô-đun base
. Bạn phải thêm mã từ mỗi bước vào base
.
Bạn có thể sử dụng mô-đun complete
trong lớp học lập trình làm điểm tham chiếu để kiểm tra công việc của mình (hoặc làm tham chiếu nếu gặp vấn đề).
Tổng quan về các thành phần khoá cho nguồn dữ liệu
ComplicationTapBroadcastReceiver
– Lớp được dùng để cập nhật dữ liệu về chức năng thông quaPendingIntent
.CustomComplicationDataSourceService
– Lớp được dùng để tiết lộ dữ liệu của chúng ta cho các chức năng. Tệp được đặt trong thư mụcbase/java/com/example/android/wearable/complicationsdatasource
. Trong Android Studio, tính năng này nằm trongbase/java/com.example.android.wearable.complicationsdatasource
. Ở lớp học này, chúng ta sẽ chủ yếu xử lý theo 4 phương pháp:onComplicationActivated
– Được gọi khi một chức năng được kích hoạt cùng dữ liệu của bạn.getPreviewData
– Xem trước dữ liệu cho chức năng được sử dụng trong giao diện người dùng trình chỉnh sửa (thường chỉ là nội dung tĩnh).onComplicationRequest
– Phần lớn hoạt động của chúng ta đều được thực hiện theo phương thức này. Phương thức này được gọi bất kỳ khi nào một chức năng đang hoạt động cần cập nhật dữ liệu từ nguồn.onComplicationDeactivated
– Được gọi khi chức năng đã được kích hoạt.
Thiết lập trình mô phỏng
Nếu bạn cần trợ giúp thiết lập trình mô phỏng Wear OS, vui lòng tham khảo phần "Launch the emulator and run your Wear app" (Chạy trình mô phỏng và chạy ứng dụng Wear) trên trang "Tạo và chạy ứng dụng cho thiết bị đeo".
Chạy dự án khởi đầu
Hãy chạy ứng dụng trên đồng hồ.
- Kết nối thiết bị Wear OS hoặc khởi động trình mô phỏng.
- Trên thanh công cụ, hãy chọn cấu hình "base" (cơ sở) từ bộ chọn thả xuống và nhấp vào nút hình tam giác xanh lục (Run (Chạy)) bên cạnh:
- Nếu gặp lỗi như lỗi bên dưới (Lỗi khi khởi chạy hoạt động), hãy thay đổi khởi chạy mặc định
Activity
(hướng dẫn bên dưới).
Ngược lại, nếu được nhắc Activity
sử dụng khi khởi chạy ứng dụng, hãy chọn "Do not launch Activity" (Không chạy Hoạt động).
- Để thay đổi khởi chạy mặc định
Activity
(nếu cần, từ bước trước đó), nhấp vào bộ chọn thả xuống ở bên trái mũi tên xanh lục và nhấp vào "edit configurations" (chỉnh sửa cấu hình).
Chọn "base" (cơ sở) và bạn sẽ thấy một cửa sổ tương tự như cửa sổ bên dưới. Chọn "Nothing" (Không có gì) trong phần Launch Options (Tuỳ chọn khởi chạy) và nhấp vào Run (Chạy). Sau này khi muốn thử phát hành mô-đun khác, bạn cũng phải thao tác như vậy.
- Chọn thiết bị Android hoặc trình mô phỏng rồi nhấp vào OK. Thao tác này sẽ cài đặt dịch vụ trên thiết bị Wear OS hoặc trình mô phỏng.
- Sau vài giây, dịch vụ của bạn đã được xây dựng và sẵn sàng để triển khai. Bạn sẽ thấy một vòng quay trên thanh trạng thái ở cuối Android Studio.
- Nếu thẻ này chưa có trên thẻ "Build" (Tạo) ở dưới cùng bên trái Android Studio, hãy chọn thẻ đó để bạn có thể xem tiến trình cài đặt. Khi kết thúc quá trình cài đặt, bạn sẽ thấy thông báo "Build: completed successfully" (Tạo: hoàn tất thành công).
- Hãy chọn mặt đồng hồ cho phép bạn chọn một chức năng. Trong trường hợp này, chúng ta đã chọn Elements Digital (Phần tử số) nhưng phần tử này có thể không có trên đồng hồ của bạn.
Lưu ý vì đây là lần đầu chạy mặt đồng hồ này, bạn sẽ cần chọn mặt đồng hồ đó trong mục "Add more watch faces" (Thêm mặt đồng hồ khác). Sau khi được chọn, mặt đồng hồ này sẽ xuất hiện trong danh sách mặt đồng hồ để bạn chọn.
- Giờ đây, mặt đồng hồ đã chọn sẽ ở chính giữa trình đơn Favorite (Mục yêu thích) (xem hình ảnh bên dưới). Nhấp vào biểu tượng bánh răng ở dưới cùng.
- Đối với mặt đồng hồ này, bạn nên chọn Data (Dữ liệu). Đối với mặt đồng hồ tuỳ chỉnh mà bạn đang sử dụng, giao diện người dùng có thể khác đi.
- Chọn bất kỳ vị trí nào, tức là bất kỳ "+" (chức năng) nào.
- Cuối cùng, cuộn xuống rồi chọn dịch vụ Complications Data Source Codelab (Lớp học lập trình về nguồn dữ liệu chức năng). (Sau khi chọn, bạn phải vuốt sang trái vài lần hoặc đặt cả bàn tay lên thiết bị để thoát.)
- Ở đầu ra, bạn sẽ thấy cả thông báo nhật ký "
onComplicationActivated()
" và "onComplicationRequest
()
" (mặc dù sẽ không có thông báo nào hiển thị ở vị trí chức năng). - Nếu bạn không thấy thông báo nhật ký, hãy thử triển khai lại mặt đồng hồ bằng cách nhấn nút tam giác xanh lục trên thanh công cụ.
- Nếu bạn chưa hiểu rõ cách xem dữ liệu
Log
, nhấp vào thẻ ở cuối Android Studio có nhãn "6: Logcat". Đặt trình đơn thả xuống thành tên thiết bị/trình mô phỏng và góicom.example.android.wearable.complicationsdatasource
(bên dưới là ảnh chụp màn hình).
"Nhưng chờ đã! Không có gì hiển thị trong vùng dữ liệu đã chọn!" Đừng lo, chúng tôi chưa cung cấp bất kỳ dữ liệu nào. Chúng tôi sẽ bổ sung thông tin này trong bước tiếp theo.
Trên một số đồng hồ, Mặt đồng hồ phần tử có các chức năng đã bật, do đó bạn có thể thấy chức năng đã điền sẵn hiển thị trên đồng hồ. Ngoài ra, đừng lo lắng nếu trình mô phỏng của bạn có đám mây bị gạch ngang thay vì biểu tượng máy bay. Chúng ta không cần kết nối với điện thoại hoặc Internet cho ứng dụng của lớp học lập trình này.
Tóm tắt
Trong bước này, bạn đã tìm hiểu về:
- Wear OS và các khái niệm đằng sau việc tiết lộ dữ liệu cho các chức năng
- Kiến thức cơ bản về điểm xuất phát của chúng tôi (mô-đun cơ sở)
- Triển khai và chạy mặt đồng hồ
Tiếp theo
Hãy bắt đầu tiết lộ một vài dữ liệu.
2. Hiện dữ liệu văn bản ngắn
Bước mã 2
Trong bước này, chúng ta sẽ bắt đầu tiết lộ dữ liệu. Các chức năng chấp nhận một số loại dữ liệu. Ở bước này, chúng ta sẽ trả về loại dữ liệu Văn bản ngắn.
Nếu bạn thấy khó hiểu về các khái niệm được thảo luận tại đây, vui lòng tham khảo mô-đun complete
và xem các bước này có thể được triển khai như thế nào.
Chỉ định loại dữ liệu mà nguồn của bạn hỗ trợ
Mở lại tệp AndroidManifest.xml
và xem dịch vụ CustomComplicationDataSourceService
. Lưu ý đến bộ lọc ý định:
<action android:name=
"android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
Điều này cho hệ thống biết rằng dịch vụ của bạn mở rộng ComplicationDataSourceService
hoặc SuspendingComplicationDataSourceService
(biến thể hỗ trợ Kotlin Coroutine) và có thể gửi dữ liệu cho các chức năng.
Tiếp theo là phần tử meta-data
chỉ định(các) loại dữ liệu mà chúng ta hỗ trợ. Trong trường hợp này, chúng ta hỗ trợ SMALL_IMAGE, nhưng đối với bước này, hãy thay đổi tuỳ chọn đó thành SHORT_TEXT. Hãy thay đổi thành phần meta-data
đầu tiên của bạn thành các thành phần sau:
<meta-data
android:name="android.support.wearable.complications.SUPPORTED_TYPES"
android:value="SHORT_TEXT"/>
Tiết lộ dữ liệu của bạn
Như đã nêu ở trên, onComplicationActivated()
được gọi khi nguồn dữ liệu được kích hoạt. Đây là vị trí/thời gian thích hợp để thực hiện các thiết lập cơ bản cần được thực hiện một lần mỗi khi kích hoạt. Chúng ta sẽ không thực hiện thao tác đó ở lớp học lập trình này vì mẫu của chúng ta tương đối đơn giản.
Lệnh gọi onComplicationRequest()
là khi các yêu cầu chức năng hoạt động cập nhật dữ liệu.
Phương thức onComplicationRequest()
được kích hoạt vì nhiều lý do:
- Chức năng hoạt động trên mặt đồng hồ được thay đổi để sử dụng nguồn này
- Chức năng sử dụng nguồn này sẽ hoạt động trở lại
- Bạn đã kích hoạt bản cập nhật từ lớp của chính mình qua
ComplicationDataSourceUpdateRequester.requestUpdate()
hoặcComplicationDataSourceUpdateRequester.requestUpdateAll()
. - Khoảng thời gian bạn đã chỉ định trong tệp kê khai đã trôi qua
Mở CustomComplicationDataSourceService
.kt
và di chuyển con trỏ xuống phương thức onComplicationRequest()
. Xoá dòng "return null
", sau đó sao chép và dán mã bên dưới trong lệnh gọi Log.d()
ban đầu:
// Retrieves your data, in this case, we grab an incrementing number from Datastore.
val number: Int = applicationContext.dataStore.data
.map { preferences ->
preferences[TAP_COUNTER_PREF_KEY] ?: 0
}
.first()
val numberText = String.format(Locale.getDefault(), "%d!", number)
Trong trường hợp này, chúng ta sẽ truy xuất một int
được lưu trữ từ DataStore
đại diện cho dữ liệu của chúng ta. Đây dễ trở thành một lệnh gọi đến cơ sở dữ liệu của bạn.
Để tương tác với DataStore
, bạn phải sử dụng coroutine để thu thập Flow
mà nó tạo ra. Bạn có thể nhận thấy onComplicationRequest()
là một hàm suspend
, vì vậy chúng ta có thể thu thập dữ liệu thông qua Flow
mà không kích hoạt cụ thể một coroutine.
Sau khi truy xuất giá trị số nguyên, chúng ta sẽ chuyển đổi nó thành chuỗi đơn giản để chuẩn bị chuyển đổi nó sang đối tượng ComplicationData
, tức là loại dữ liệu mà chức năng (compilation) có thể hiểu được.
Tiếp theo, sao chép và dán mã bên dưới mã bạn vừa thêm..
return when (request.complicationType) {
ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = numberText).build(),
contentDescription = PlainComplicationText
.Builder(text = "Short Text version of Number.").build()
)
.build()
else -> {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unexpected complication type ${request.complicationType}")
}
null
}
}
Trong mã này, chúng ta trả về một đối tượng ComplicationData
dựa trên loại chức năng, tức là chúng ta sẽ trả về một ShortTextComplicationData
(một lớp con của ComplicationData
) cho loại dữ liệu SHORT_TEXT
.
Một loại dữ liệu nhất định có thể bao gồm nhiều trường. Ví dụ: SHORT_TEXT
có thể chỉ là đoạn văn bản hoặc tiêu đề và văn bản, hoặc hình ảnh và văn bản đơn sắc (tất cả phải bao gồm nội dung mô tả để cho biết khả năng tiếp cận).
Ở đây, chúng ta chỉ đặt trường bắt buộc và không đặt các trường không bắt buộc. Để tìm hiểu thêm về các loại và trường này, xem tài liệu của chúng ta.
Bạn có thể hỏi lý do chúng ta sử dụng câu lệnh thời gian để tạo dữ liệu. Sau này, chúng ta sẽ hỗ trợ nhiều dạng dữ liệu dựa trên loại dữ liệu mà hệ thống yêu cầu. Bằng cách sử dụng câu lệnh thời gian, chúng ta có thể dễ dàng thêm các loại dữ liệu mới (LONG_TEXT
, RANGED_VALUE
, v.v.) sau này.
Cuối cùng, chúng ta sẽ trả về giá trị rỗng nếu không hỗ trợ loại dữ liệu này.
Phương pháp cuối cùng của bạn sẽ có dạng như sau:
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
Log.d(TAG, "onComplicationRequest() id: ${request.complicationInstanceId}")
// Retrieves your data, in this case, we grab an incrementing number from Datastore.
val number: Int = applicationContext.dataStore.data
.map { preferences ->
preferences[TAP_COUNTER_PREF_KEY] ?: 0
}
.first()
val numberText = String.format(Locale.getDefault(), "%d!", number)
return when (request.complicationType) {
ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = numberText).build(),
contentDescription = PlainComplicationText
.Builder(text = "Short Text version of Number.").build()
)
.build()
else -> {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unexpected complication type ${request.complicationType}")
}
null
}
}
}
Chạy lại ứng dụng
Trong bước đầu tiên, bạn đã tìm hiểu cách cài đặt dịch vụ dữ liệu chức năng trên thiết bị hoặc trình mô phỏng của mình. Bây giờ, hãy làm lại điều đó! Cài đặt ứng dụng rồi chọn lại chức năng (compilation), tức là vuốt mặt đồng hồ, chọn bánh răng, chuyển đến cùng chức năng và chọn Lớp học lập trình về Nguồn dữ liệu cho chức năng. Bạn sẽ thấy như sau:
Tóm tắt
Trong bước này, bạn đã tìm hiểu về:
- Cách chỉ định loại dữ liệu mà nguồn của bạn có thể hỗ trợ
- Dữ liệu của bạn nên được yêu cầu ở tần suất như thế nào khi một chức năng hoạt động đang sử dụng dữ liệu đó
- Nơi hiển thị dữ liệu của bạn trên Wear OS
Tiếp theo
Hãy thử hỗ trợ một loại dữ liệu khác.
3. Kích hoạt bản cập nhật dữ liệu chức năng
Bước mã 3
Ở bước này, chúng ta sẽ kích hoạt các bản cập nhật trong dữ liệu khi người dùng nhấn vào chức năng của chúng ta.
Nếu bạn thấy khó hiểu về các khái niệm được thảo luận tại đây, vui lòng tham khảo mô-đun complete
và xem các bước này có thể được triển khai như thế nào.
Chỉ định tần suất chức năng (complication) nên làm mới dữ liệu
Mở tệp AndroidManifest.xml
và xem lại dịch vụ CustomComplicationDataSourceService
.
Hãy lưu ý trường UPDATE_PERIOD_SECONDS trong phần tử meta-data
. Thông tin này cho biết tần suất bạn muốn hệ thống kiểm tra các bản cập nhật dữ liệu khi nguồn dữ liệu của bạn đang hoạt động.
Hiện tại, nó được đặt thành 600 giây (10 phút). Vì muốn cập nhật chức năng của mình để phản hồi một hành động của người dùng nên chúng ta sẽ cập nhật thường xuyên hơn. Mặc dù có thể giảm thời gian này nhưng hệ thống có thể không kích hoạt bản cập nhật trong khoảng thời gian ngắn hơn vài phút.
Cách hiệu quả hơn là "kiểu đẩy" trong đó chúng ta yêu cầu hệ thống cập nhật chính xác khi dữ liệu thay đổi.
Thay đổi tần suất cập nhật từ 600 thành 0, điều này có nghĩa là chúng ta sẽ trực tiếp ping hệ thống khi dữ liệu thay đổi thay vì dựa vào cập nhật định kỳ. Lưu ý đối với siêu dữ liệu, đây là yêu cầu bắt buộc.
<meta-data
android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
android:value="0"/>
Thông báo cho hệ thống về dữ liệu chức năng mới có sẵn
Mở ComplicationTapBroadcastReceiver.kt
. Lớp BroadcastReceiver
này sẽ cập nhật dữ liệu về chức năng của chúng ta khi nó được kích hoạt. (Đừng quên chúng ta chỉ lưu dữ liệu vào DataStore
.)
Lớp này cũng cung cấp phương thức trợ giúp để tạo PendingIntent
(kích hoạt nó dưới dạng BroadcastReceiver
).
Hiện tại, phương thức onReceive()
, trích xuất nguồn dữ liệu và mã (id) chức năng (compilation) từ ý định, đồng thời cập nhật số nguyên trong DataStore
. Chúng ta cần cho chức năng biết dữ liệu đã được cập nhật.
Di chuyển xuống cuối phương thức onReceive()
. Trên khối cuối cùng, bạn sẽ thấy nhận xét "Request an update for the…" (Yêu cầu cập nhật cho…) Sao chép và dán mã bên dưới nhận xét đó.
// Request an update for the complication that has just been tapped, that is,
// the system call onComplicationUpdate on the specified complication data
// source.
val complicationDataSourceUpdateRequester =
ComplicationDataSourceUpdateRequester.create(
context = context,
complicationDataSourceComponent = dataSource
)
complicationDataSourceUpdateRequester.requestUpdate(complicationId)
Thao tác này giúp Wear OS biết dữ liệu của chức năng đã được cập nhật. Chúng ta cần ba phần dữ liệu để làm việc này:
- context (ngữ cảnh) -
Context
có sẵn dưới dạng một đối số cho phương thức này:onReceive()
. - complicationDataSourceComponent –
DataSource
của chức năng được chuyển vào nhưExtra
từPendingIntent
để kích hoạtBroadcastReceiver
này. - complicationId: Số nguyên độc nhất được mặt đồng hồ gán cho vị trí hiển thị chức năng.
int
được chuyển vào dưới dạngExtra
từPendingIntent
sẽ kích hoạtBroadcastReceiver
này.
Chúng ta đã hoàn tất bước này và phương pháp cuối cùng của bạn sẽ có dạng như sau:
override fun onReceive(context: Context, intent: Intent) {
// Retrieve complication values from Intent's extras.
val extras = intent.extras ?: return
val dataSource = extras.getParcelable<ComponentName>(EXTRA_DATA_SOURCE_COMPONENT) ?: return
val complicationId = extras.getInt(EXTRA_COMPLICATION_ID)
// Required when using async code in onReceive().
val result = goAsync()
// Launches coroutine to update the DataStore counter value.
scope.launch {
try {
context.dataStore.edit { preferences ->
val currentValue = preferences[TAP_COUNTER_PREF_KEY] ?: 0
// Update data for complication.
val newValue = (currentValue + 1) % MAX_NUMBER
preferences[TAP_COUNTER_PREF_KEY] = newValue
}
// Request an update for the complication that has just been tapped, that is,
// the system call onComplicationUpdate on the specified complication data
// source.
val complicationDataSourceUpdateRequester =
ComplicationDataSourceUpdateRequester.create(
context = context,
complicationDataSourceComponent = dataSource
)
complicationDataSourceUpdateRequester.requestUpdate(complicationId)
} finally {
// Always call finish, even if cancelled
result.finish()
}
}
}
Thêm một thao tác nhấn vào chức năng
BroadcastReceiver
không chỉ cập nhật dữ liệu mà còn thông báo cho hệ thống rằng dữ liệu mới có sẵn (xem bước trước). Cần thêm một hành động nhấn vào chức năng để kích hoạt BroadcastReceiver
.
Mở CustomComplicationDataSourceService.kt
và chuyển xuống phương thức onComplicationRequest()
.
Bên dưới câu lệnh Log.d()
đầu tiên và ở trên vị trí số nguyên được truy xuất từ DataStore, sao chép/dán mã bên dưới:
// Create Tap Action so that the user can trigger an update by tapping the complication.
val thisDataSource = ComponentName(this, javaClass)
// We pass the complication id, so we can only update the specific complication tapped.
val complicationPendingIntent =
ComplicationTapBroadcastReceiver.getToggleIntent(
this,
thisDataSource,
request.complicationInstanceId
)
Ở bước trước, chúng ta đã biết cần cả hai phần dữ liệu này để BroadcastReceiver
hoạt động (nguồn dữ liệu và mã chức năng). Chúng ta chuyển cả hai thông tin này dưới dạng thông số bổ sung cho PendingIntent
.
Tiếp theo, chúng ta phải chỉ định PendingIntent
cho sự kiện nhấn của chức năng này.
Tìm câu lệnh thời gian cho ST và thêm dòng này lên trên lệnh gọi .build().
.setTapAction(complicationPendingIntent)
Khối mã bây giờ sẽ giống như thế này.
ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = numberText).build(),
contentDescription = PlainComplicationText
.Builder(text = "Short Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
Thao tác này chỉ thêm một dòng, phương thức .setTapAction()
để chỉ định PendingIntent
mới cho thao tác nhấn cho chức năng đó.
Chúng ta đã thực hiện xong bước này. Phương pháp cuối cùng của bạn sẽ có dạng như sau:
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
Log.d(TAG, "onComplicationRequest() id: ${request.complicationInstanceId}")
// Create Tap Action so that the user can trigger an update by tapping the complication.
val thisDataSource = ComponentName(this, javaClass)
// We pass the complication id, so we can only update the specific complication tapped.
val complicationPendingIntent =
ComplicationTapBroadcastReceiver.getToggleIntent(
this,
thisDataSource,
request.complicationInstanceId
)
// Retrieves your data, in this case, we grab an incrementing number from Datastore.
val number: Int = applicationContext.dataStore.data
.map { preferences ->
preferences[TAP_COUNTER_PREF_KEY] ?: 0
}
.first()
val numberText = String.format(Locale.getDefault(), "%d!", number)
return when (request.complicationType) {
ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = numberText).build(),
contentDescription = PlainComplicationText
.Builder(text = "Short Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
else -> {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unexpected complication type ${request.complicationType}")
}
null
}
}
}
Chạy lại ứng dụng
Cài đặt ứng dụng rồi chọn lại chức năng (compilation), tức là vuốt mặt đồng hồ, chọn bánh răng, chuyển đến cùng chức năng và chọn nguồn Complications Data Source Codelab (Lớp học lập trình về Nguồn dữ liệu cho chức năng). Bạn sẽ thấy nội dung như đã thấy trước đây. Tuy nhiên, giờ bạn có thể nhấn vào chức năng này và dữ liệu sẽ được cập nhật.
Tóm tắt
Trong bước này, bạn đã tìm hiểu về:
- Cách thông báo cho hệ thống biết dữ liệu chức năng của bạn đã được cập nhật
- Cách liên kết một
PendingIntent
vào một hành động nhấn trong chức năng
Tiếp theo
Hãy thử hỗ trợ một loại dữ liệu khác.
4. Hiện dữ liệu văn bản dài
Bước mã 4
Khi tiết lộ dữ liệu của mình cho các chức năng, bạn nên hỗ trợ nhiều loại dữ liệu hơn và xem các loại dữ liệu trông như thế nào trong các chức năng.
Chỉ định một loại dữ liệu được hỗ trợ khác
Mở lại tệp AndroidManifest.xml
và xem khai báo về dịch vụ CustomComplicationDataSourceService
.
Thay đổi phần tử meta-data
SUPPORTED_TYPES
từ SHORT_TEXT thành LONG_TEXT. Thay đổi của bạn sẽ giống như sau:
<meta-data
android:name="android.support.wearable.complications.SUPPORTED_TYPES"
android:value="LONG_TEXT"/>
Thêm hỗ trợ cho LONG TEXT
Mở CustomComplicationDataSourceService.kt
, di chuyển xuống câu lệnh when
trong phương thức onComplicationRequest()
và thêm mã sau bên dưới phần cuối của trường hợp TYPE_SHORT_TEXT
và phía trên trường hợp mặc định.
ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
contentDescription = PlainComplicationText
.Builder(text = "Long Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
Câu lệnh when
sẽ giống như sau:
return when (request.complicationType) {
ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = numberText).build(),
contentDescription = PlainComplicationText
.Builder(text = "Short Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
contentDescription = PlainComplicationText
.Builder(text = "Long Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
else -> {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unexpected complication type ${request.complicationType}")
}
null
}
}
Bạn hẳn đã thấy chúng ta chỉ đóng gói lại dữ liệu đó trong một định dạng mới. Hãy xem giao diện của nó.
Cách kiểm tra tiến trình và gỡ lỗi
Cài đặt dịch vụ của bạn, nhưng lần này hãy chọn chức năng vùng dưới cùng trước khi chọn nguồn dịch vụ chức năng của bạn:
Bạn sẽ thấy một hình ảnh như hình bên dưới. Lưu ý mỗi chức năng được lưu trữ trong một khoá riêng, vì vậy bạn có thể thấy các giá trị khác nhau nếu đã đặt chức năng ở nhiều vị trí:
Tóm tắt
Trong bước này, bạn đã tìm hiểu về:
- Thay đổi và hỗ trợ các loại dữ liệu chức năng khác nhau
Tiếp theo
Chúng ta muốn hỗ trợ thêm một loại dữ liệu trước khi gộp tất cả lại.
5. Hiện dữ liệu văn bản trong phạm vi
Bước mã 5
Mặc dù có thể tiết lộ dữ liệu của mình nhưng chúng ta hãy tiếp tục tìm hiểu cách hỗ trợ thêm nhiều loại dữ liệu.
Chỉ định một loại dữ liệu được hỗ trợ khác
Mở lại tệp AndroidManifest.xml
và xem dịch vụ CustomComplicationDataSourceService
.
Thay đổi phần tử meta-data
SUPPORTED_TYPES
thành RANGED_VALUE. Thay đổi của bạn sẽ có dạng như sau:
<meta-data
android:name="android.support.wearable.complications.SUPPORTED_TYPES"
android:value="RANGED_VALUE"/>
Thêm tuỳ chọn hỗ trợ cho RANGED VALUES
Giá trị theo phạm vi không chỉ hiện văn bản mà còn hiện cả hình ảnh cho biết giá trị của bạn đang nằm ở vị trí nào giữa giá trị tối thiểu và giá trị tối đa. Loại chức năng này cho biết mức pin còn lại trên thiết bị hoặc số bước còn lại để đáp ứng mục tiêu của bạn.
Mở CustomComplicationDataSourceService .kt
, di chuyển con trỏ xuống câu lệnh when
trong phương thức onComplicationRequest()
và thêm mã này trong trường hợp TYPE_LONG_TEXT
và phía trên trường hợp mặc định:
ComplicationType.RANGED_VALUE -> RangedValueComplicationData.Builder(
value = number.toFloat(),
min = 0f,
max = ComplicationTapBroadcastReceiver.MAX_NUMBER.toFloat(),
contentDescription = PlainComplicationText
.Builder(text = "Ranged Value version of Number.").build()
)
.setText(PlainComplicationText.Builder(text = numberText).build())
.setTapAction(complicationPendingIntent)
.build()
Câu lệnh thời gian nên có dạng như sau:
return when (request.complicationType) {
ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = numberText).build(),
contentDescription = PlainComplicationText
.Builder(text = "Short Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
contentDescription = PlainComplicationText
.Builder(text = "Long Text version of Number.").build()
)
.setTapAction(complicationPendingIntent)
.build()
ComplicationType.RANGED_VALUE -> RangedValueComplicationData.Builder(
value = number.toFloat(),
min = 0f,
max = ComplicationTapBroadcastReceiver.MAX_NUMBER.toFloat(),
contentDescription = PlainComplicationText
.Builder(text = "Ranged Value version of Number.").build()
)
.setText(PlainComplicationText.Builder(text = numberText).build())
.setTapAction(complicationPendingIntent)
.build()
else -> {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unexpected complication type ${request.complicationType}")
}
null
}
}
Vui lòng lưu ý một lần nữa, chúng tôi chỉ gói lại dữ liệu đó trong một định dạng mới. Hãy xem giao diện của nó.
Cách kiểm tra tiến trình và gỡ lỗi
Cài đặt dịch vụ và chọn một vị trí khác.
Bây giờ bạn sẽ thấy như sau:
Bạn có thể thấy một vòng tròn hướng tâm bao quanh số làm nổi bật số tương đương 3/20.
Tóm tắt
Trong bước này, bạn đã tìm hiểu về:
- Thay đổi và hỗ trợ các loại dữ liệu chức năng khác nhau
Tiếp theo
Chúng ta kết thúc lớp học lập trình này bằng việc bật tất cả các biến thể của loại dữ liệu.
6. Hiện cả 3 loại dữ liệu
Bước mã 6
Hiện tại, nguồn dữ liệu chức năng của chúng ta hỗ trợ ba biến thể dữ liệu (RANGED_VALUE, SHORT_TEXT, và LONG_TEXT).
Trong bước cuối cùng này, chúng ta sẽ cho hệ thống chúng ta hỗ trợ biết cả 3 biến thể này.
Chỉ định nhiều loại dữ liệu được hỗ trợ
Mở lại tệp AndroidManifest.xml
và xem dịch vụ CustomComplicationDataSourceService
.
Thay đổi phần tử meta-data
SUPPORTED_TYPES
thành RANGED_VALUE,SHORT_TEXT,LONG_TEXT
. Thay đổi của bạn bây giờ sẽ có dạng như sau:
<meta-data
android:name="android.support.wearable.complications.SUPPORTED_TYPES"
android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT"/>
Kiểm tra tiến trình
Cài đặt dịch vụ của bạn.
Trong trường hợp này, mặt đồng hồ ưu tiên loại dữ liệu theo phạm vi hơn là loại dữ liệu ngắn và dài. Tuy nhiên, nếu chức năng này chỉ hỗ trợ loại văn bản ngắn thì dữ liệu vẫn sẽ hiển thị vì mặt đồng hồ hỗ trợ cả 3 loại dữ liệu. Lưu ý bản thân mặt đồng hồ sẽ chỉ định loại dữ liệu mà chức năng hỗ trợ và thứ tự ưu tiên của các loại đó.
Tóm tắt
Trong bước này, bạn đã tìm hiểu về:
- Hỗ trợ nhiều loại dữ liệu chức năng
7. Bạn đã hoàn tất! Tiếp theo là gì?
Bạn có thể hỗ trợ nhiều loại dữ liệu khác trong các chức năng (bao gồm hình ảnh nhỏ, hình ảnh lớn và biểu tượng). Thử mở rộng lớp học lập trình này bằng cách tự triển khai một số loại đó.
Để biết thêm thông tin về cách phát triển các chức năng cho mặt đồng hồ và tạo nguồn dữ liệu cho chức năng, truy cập vào Watch Face Complications (Chức năng trên mặt đồng hồ)
Để biết thêm thông tin chi tiết về cách phát triển mặt đồng hồ Wear OS, truy cập vào https://developer.android.com/training/wearables/watch-faces/index.html