Đưa dữ liệu vào chức năng

Các ứng dụng nhà cung cấp dữ liệu hiển thị thông tin cho chức năng của mặt đồng hồ, cung cấp các trường chứa văn bản, chuỗi, hình ảnh và số.

Dịch vụ của ứng dụng nhà cung cấp dữ liệu mở rộng ComplicationProviderService để cung cấp thông tin hữu ích trực tiếp trên mặt đồng hồ.

Tạo dự án cho ứng dụng cung cấp dữ liệu

Để tạo dự án trong Android Studio cho ứng dụng nhà cung cấp dữ liệu, hãy hoàn tất các bước sau:

  1. Nhấp vào File > New > New project (Tệp > Mới > Dự án mới).
  2. Trong cửa sổ Project Template (Mẫu dự án), hãy nhấp vào thẻ Wear OS, chọn No Activity (Không có hoạt động) rồi nhấp vào Next (Tiếp theo).
  3. Trong cửa sổ Configure Your Project (Định cấu hình dự án của bạn), hãy điền thông tin dự án chuẩn và nhấp vào Finish (Hoàn tất).
  4. Android Studio tạo dự án bằng một mô-đun ứng dụng dành cho ứng dụng nhà cung cấp dữ liệu của bạn. Để biết thêm thông tin về các dự án trong Android Studio, hãy xem phần Tạo dự án.
  5. Bắt đầu ứng dụng nhà cung cấp dữ liệu bằng việc tạo một lớp mới mở rộng BroadcastReceiver. Mục đích của lớp đó là theo dõi các yêu cầu cập nhật chức năng qua hệ thống Wear OS. Ngoài ra, hãy tạo một lớp mới mở rộng ComplicationProviderService để cung cấp dữ liệu theo yêu cầu của các chức năng phù hợp. Để biết thêm thông tin chi tiết, hãy xem phần dưới đây:

    Lưu ý: Bạn không bắt buộc phải thêm hoạt động cho ứng dụng cung cấp dữ liệu của mình. Ví dụ: có thể bạn muốn một hoạt động chỉ chạy khi người dùng nhấn vào một chức năng.

Triển khai một phương thức cho các yêu cầu cập nhật

Khi cần dữ liệu chức năng, hệ thống Wear OS sẽ gửi yêu cầu cập nhật đến ứng dụng nhà cung cấp dữ liệu của bạn. BroadcastReceiver của bạn sẽ nhận được các yêu cầu. Để phản hồi các yêu cầu cập nhật, ứng dụng cung cấp dữ liệu phải triển khai phương thức onComplicationUpdate() của lớp ComplicationProviderService.

Hệ thống Wear OS gọi onComplicationUpdate() khi cần dữ liệu của ứng dụng cung cấp, chẳng hạn như khi một chức năng cần sử dụng dữ liệu của ứng dụng cung cấp dữ liệu để có thể hoạt động hoặc khi một khoảng thời gian cố định trôi qua. Phương thức này truyền một đối tượng ComplicationManager dưới dạng tham số đến onComplicationUpdate, được dùng để gửi dữ liệu về hệ thống.

Lưu ý: Khi ứng dụng nhà cung cấp dữ liệu của bạn cung cấp dữ liệu, mặt đồng hồ sẽ nhận được giá trị thô mà bạn gửi để có thể vẽ thông tin.

Đoạn mã sau đây cho thấy cách triển khai mẫu của phương thức onComplicationUpdate:

Kotlin

override fun onComplicationUpdate(
    complicationId: Int, dataType: Int, complicationManager: ComplicationManager) {

    Log.d(TAG, "onComplicationUpdate() id: $complicationId")

    // Used to create a unique key to use with SharedPreferences for this complication.
    val thisProvider = ComponentName(this, javaClass)

    // Retrieves your data; in this case, grabs an incrementing number from SharedPrefs.
    val preferences = getSharedPreferences(ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0)

    val number = preferences.getInt(
            ComplicationTapBroadcastReceiver.getPreferenceKey(
                    thisProvider, complicationId),
                    0)
    val numberText = String.format(Locale.getDefault(), "%d!", number)

    var complicationData: ComplicationData? = null

    when (dataType) {
        ComplicationData.TYPE_SHORT_TEXT -> complicationData = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                .setShortText(ComplicationText.plainText(numberText))
                .build()
        else -> if (Log.isLoggable(TAG, Log.WARN)) {
                    Log.w(TAG, "Unexpected complication type $dataType")
                }
    }

    if (complicationData != null) {
        complicationManager.updateComplicationData(complicationId, complicationData)
    } else {
        // If no data is sent, we still need to inform the ComplicationManager, so
        // the update job can finish and the wake lock isn't held any longer.
        complicationManager.noUpdateRequired(complicationId)
    }
}

Java

@Override
public void onComplicationUpdate(
       int complicationId, int dataType, ComplicationManager complicationManager) {

   Log.d(TAG, "onComplicationUpdate() id: " + complicationId);

   // Used to create a unique key to use with SharedPreferences for this complication.
   ComponentName thisProvider = new ComponentName(this, getClass());

   // Retrieves your data; in this case, grabs an incrementing number from SharedPrefs.
   SharedPreferences preferences =
     getSharedPreferences( ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);

   int number =
           preferences.getInt(
                   ComplicationTapBroadcastReceiver.getPreferenceKey(
                           thisProvider, complicationId),
                   0);
   String numberText = String.format(Locale.getDefault(), "%d!", number);

   ComplicationData complicationData = null;

   switch (dataType) {
       case ComplicationData.TYPE_SHORT_TEXT:
           complicationData =
                   new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                           .setShortText(ComplicationText.plainText(numberText))
                           .build();
           break;
       default:
           if (Log.isLoggable(TAG, Log.WARN)) {
               Log.w(TAG, "Unexpected complication type " + dataType);
           }
   }

   if (complicationData != null) {
       complicationManager.updateComplicationData(complicationId, complicationData);

   } else {
       // If no data is sent, we still need to inform the ComplicationManager, so
       // the update job can finish and the wake lock isn't held any longer.
       complicationManager.noUpdateRequired(complicationId);
   }
}

Quyền và nội dung khai báo trong tệp kê khai

Ứng dụng nhà cung cấp dữ liệu phải bao gồm các nội dung khai báo cụ thể trong tệp kê khai ứng dụng để được hệ thống Android coi là một ứng dụng nhà cung cấp dữ liệu. Phần này giải thích các chế độ cài đặt bắt buộc cho ứng dụng nhà cung cấp dữ liệu.

Trong tệp kê khai của ứng dụng, hãy khai báo dịch vụ và thêm bộ lọc ý định hành động yêu cầu cập nhật. Tệp kê khai cũng phải bảo vệ dịch vụ bằng cách thêm quyền BIND_COMPLICATION_PROVIDER để đảm bảo chỉ hệ thống Wear OS mới có thể liên kết với các dịch vụ của ứng dụng nhà cung cấp dữ liệu.

Ngoài ra, hãy đưa thuộc tính android:icon vào phần tử service cung cấp biểu tượng màu trắng đơn sắc. Bạn nên sử dụng các vectơ vẽ được cho các biểu tượng. Biểu tượng này đại diện cho ứng dụng nhà cung cấp và được hiển thị trong trình chọn ứng dụng nhà cung cấp.

Ví dụ:

<service
    android:name=".provider.IncrementingNumberComplicationProviderService"
    android:icon="@drawable/icn_complications"
    android:label="@string/complications_provider_incrementing_number"
    android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
    <intent-filter>
        <action
         android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
    </intent-filter>
</service>

Chỉ định các phần tử siêu dữ liệu

Trong tệp kê khai, hãy thêm siêu dữ liệu để chỉ định các loại được hỗ trợ, khoảng thời gian cập nhật và thao tác với cấu hình, như trong ví dụ sau đây:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT" />

<meta-data
    android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
    android:value="300" />

Khi ứng dụng cung cấp dữ liệu bổ sung của bạn hoạt động, UPDATE_PERIOD_SECONDS sẽ chỉ định 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. Nếu thông tin hiện trong chức năng không cần cập nhật theo lịch định kỳ, chẳng hạn như khi bạn sử dụng bản cập nhật dạng đẩy, hãy đặt giá trị này thành 0.

Nếu không đặt UPDATE_PERIOD_SECONDS thành 0 thì bạn phải sử dụng giá trị tối thiểu là 300 (5 phút). Đây là thời gian cập nhật tối thiểu mà hệ thống thực thi để duy trì tuổi thọ pin của thiết bị. Ngoài ra, hãy lưu ý rằng yêu cầu cập nhật có thể ít thường xuyên hơn khi thiết bị ở chế độ môi trường xung quanh hoặc đang không được đeo.

Để biết thêm thông tin chi tiết về việc gửi bản cập nhật, hãy xem các khoá được liệt kê cho lớp ComplicationProviderService trong Tài liệu tham khảo API về Wear OS.

Thêm hoạt động cấu hình

Nếu cần, ứng dụng nhà cung cấp có thể đưa vào hoạt động cấu hình được hiện cho người dùng khi người dùng chọn nhà cung cấp dữ liệu. Để đưa hoạt động cấu hình vào, hãy đưa một mục siêu dữ liệu vào phần khai báo dịch vụ của ứng dụng nhà cung cấp trong tệp kê khai kèm theo khoá sau:

<meta-data
    android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
    android:value="PROVIDER_CONFIG_ACTION"/>

Giá trị này có thể là bất kỳ hành động nào.

Sau đó, hãy tạo hoạt động cấu hình bằng bộ lọc ý định cho thao tác đó. Hoạt động định cấu hình phải nằm trong cùng một gói với ứng dụng nhà cung cấp. Hoạt động cấu hình phải trả về RESULT_OK hoặc RESULT_CANCELED để cho hệ thống biết có nên đặt ứng dụng nhà cung cấp hay không.

Mặt đồng hồ an toàn do ứng dụng cung cấp chỉ định

Ứng dụng nhà cung cấp có thể chỉ định một số mặt đồng hồ là "an toàn" để nhận được dữ liệu. Chế độ này chỉ được sử dụng khi mặt đồng hồ cố gắng sử dụng ứng dụng cung cấp làm mặc định và ứng dụng cung cấp tin tưởng ứng dụng mặt đồng hồ.

Để khai báo mặt đồng hồ là an toàn, ứng dụng cung cấp thêm siêu dữ liệu bằng khoá android.support.wearable.complications.SAFE_WATCH_FACES. Giá trị siêu dữ liệu là một danh sách được phân tách bằng dấu phẩy gồm các tên thành phần WatchFaceService (được cung cấp như thể ComponentName.flattenToString() được gọi) hoặc tên gói ứng dụng. Trong trường hợp đó, mọi mặt đồng hồ trong một ứng dụng cụ thể đều được coi là an toàn. Hệ thống sẽ bỏ qua khoảng trắng trong danh sách giá trị. Ví dụ:

<meta-data
       android:name="android.support.wearable.complications.SAFE_WATCH_FACES"
       android:value="
          com.app.watchface/com.app.watchface.MyWatchFaceService,
          com.anotherapp.anotherwatchface/com.something.WatchFaceService,
          com.something.text"/>

Cung cấp hình ảnh được bảo vệ chống lỗi lưu ảnh (do các pixel không đồng đều).

Trên những màn hình dễ xảy ra hiện tượng lưu ảnh, bạn nên tránh sử dụng các khối màu đồng nhất ở chế độ môi trường xung quanh. Nếu biểu tượng hoặc hình ảnh của bạn có chứa các khối màu đồng nhất, hãy cung cấp một phiên bản an toàn chống lỗi lưu ảnh.

Khi bạn cung cấp biểu tượng bằng ComplicationData.Builder#setIcon, hãy đưa vào một phiên bản không có hiện tượng lưu ảnh bằng cách sử dụng ComplicationData.Builder#setBurnInProtectionIcon.

Khi bạn cung cấp hình ảnh bằng ComplicationData.Builder#setSmallImage, hãy bao gồm một phiên bản an toàn chống lỗi lưu ảnh bằng cách sử dụng ComplicationData.Builder#setBurnInProtectionSmallImage.

Sử dụng các bản cập nhật đẩy

Thay vì chỉ định khoảng thời gian giữa những lần cập nhật bằng một hằng số khác 0 cho một chức năng trong tệp kê khai của ứng dụng, bạn có thể sử dụng một thực thể của ComplicationDataSourceUpdateRequester để yêu cầu các bản cập nhật một cách linh hoạt. Để yêu cầu cập nhật nội dung mà người dùng thấy của chức năng, hãy gọi requestUpdate().

Thận trọng: Để duy trì thời lượng pin của thiết bị, đừng gọi requestUpdate() qua thực thể của ComplicationDataSourceUpdateRequester thường xuyên hơn trung bình 5 phút một lần.

Cung cấp các giá trị linh động

Kể từ Wear OS 4, một số chức năng có thể cho thấy các giá trị có tần suất làm mới nhanh hơn dựa trên các giá trị có sẵn trực tiếp đến nền tảng. Để cung cấp tính năng này trong các chức năng, hãy sử dụng các trường ComplicationData chấp nhận giá trị động. Nền tảng thường xuyên đánh giá và cập nhật các giá trị này mà không yêu cầu trình cung cấp chức năng phải chạy.

Các trường ví dụ bao gồm trường giá trị động của GoalProgressComplicationData DynamicComplicationText có thể được dùng trong bất kỳ trường ComplicationText nào. Các giá trị động này dựa trên thư viện androidx.wear.protolayout.expression.

Trong một số trường hợp nhất định, nền tảng không thể đánh giá các giá trị động:

Cung cấp các giá trị phụ thuộc vào thời gian

Một số chức năng cần hiển thị một giá trị liên quan đến thời gian hiện tại. Ví dụ bao gồm ngày hiện tại, thời gian diễn ra cuộc họp tiếp theo hoặc thời gian ở một múi giờ khác.

Đừng cập nhật một chức năng từng giây hoặc phút để duy trì cập nhật các giá trị đó. Thay vào đó, hãy chỉ định các giá trị tương ứng với ngày hoặc giờ hiện tại bằng cách sử dụng giá trị phụ thuộc vào thời gian. Bạn có thể sử dụng trình tạo trong lớp ComplicationText để tạo các giá trị phụ thuộc vào thời gian này.

Tốc độ cập nhật chức năng

Có thể bạn muốn cập nhật các chức năng ở tốc độ nhanh. Tuy nhiên, điều này có thể ảnh hưởng đến thời lượng pin của thiết bị. Bạn có thể chọn sử dụng một API yêu cầu chức năng để cho phép các chức năng cụ thể cập nhật thường xuyên hơn. Tuy nhiên, việc sử dụng API này phải được nhà sản xuất đồng hồ cho phép. Mỗi nhà sản xuất đồng hồ sẽ quyết định chức năng nào có thể cập nhật với tốc độ nhanh hơn mức cho phép bình thường.