Narażenie danych na widżety

Aplikacje dostawców danych ujawniają informacje widżetom tarczy zegarka, udostępniając pola zawierające tekst, ciągi znaków, obrazy i liczby.

Dostawca danych wykracza poza ComplicationProviderService, aby dostarczać przydatne informacje bezpośrednio na tarczę zegarka.

Tworzenie projektu dostawcy danych

Aby utworzyć w Android Studio projekt dla aplikacji dostawcy danych, wykonaj te czynności:

  1. Kliknij File (Plik) > New (Nowy) > New project (Nowy projekt).
  2. W oknie Szablon projektu kliknij kartę Wear OS, wybierz Brak aktywności i kliknij Dalej.
  3. W oknie Skonfiguruj projekt wpisz nazwę projektu, wpisz standardowe informacje o projekcie i kliknij Zakończ.
  4. Android Studio utworzy projekt z modułem aplikacji dla Twojego dostawcy danych. Więcej informacji o projektach w Android Studio znajdziesz w artykule o tworzeniu projektu.
  5. Zacznij aplikację dostawcy danych od utworzenia nowej klasy o rozszerzeniu BroadcastReceiver. Ta klasa służy do wychwytywania żądań aktualizacji widżetów z systemu Wear OS. Dodatkowo utwórz nową klasę, która rozszerzy zakres ComplicationProviderService, aby udostępniać dane wymagane przez odpowiednie widżety. Więcej informacji:

    Uwaga: dodanie aktywności dla Twojego dostawcy danych jest opcjonalne. Możesz na przykład chcieć, aby działanie było uruchamiane tylko wtedy, gdy użytkownik kliknie widżet.

Wdrażanie metody obsługi żądań aktualizacji

Gdy potrzebne są dane widżetów, system Wear OS wysyła żądania aktualizacji do dostawcy danych. Żądania są przesyłane przez BroadcastReceiver. Aby odpowiadać na żądania aktualizacji, Twój dostawca danych musi wdrożyć metodę onComplicationUpdate() klasy ComplicationProviderService.

System Wear OS wywołuje onComplicationUpdate(), gdy potrzebuje danych od dostawcy, np. gdy aktywny widżet korzystający z usług dostawcy lub gdy minie ustalony czas. Przekazuje do onComplicationUpdate obiekt ComplicationManager jako parametr, który służy do wysyłania danych z powrotem do systemu.

Uwaga: gdy aplikacja dostawcy danych dostarcza dane, tarcza zegarka otrzymuje nieprzetworzone wartości, które przesyłasz, aby mogła je pobrać.

Ten fragment kodu zawiera przykładową implementację metody 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);
   }
}

Deklaracje i uprawnienia w pliku manifestu

Aplikacje dostawców danych muszą zawierać określone deklaracje w pliku manifestu, aby system Android był traktowany jako dostawca danych. W tej sekcji opisano wymagane ustawienia dla aplikacji dostawców danych.

W pliku manifestu aplikacji zadeklaruj usługę i dodaj filtr intencji działania żądania aktualizacji. Plik manifestu musi też chronić usługę, dodając uprawnienie BIND_COMPLICATION_PROVIDER, aby mieć pewność, że tylko system Wear OS może tworzyć powiązania z usługami dostawców.

Dodaj też atrybut android:icon w elemencie service, który tworzy jednokolorową białą ikonę. Zalecamy korzystanie z elementów rysowalnych w formie wektorowej. Ikona ta reprezentuje dostawcę i jest widoczna w selektorze dostawcy.

Oto przykład:

<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>

Określ elementy metadanych

W pliku manifestu uwzględnij metadane, aby określić obsługiwane typy, okres aktualizacji i działanie konfiguracji, jak pokazano w tym przykładzie:

<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" />

Gdy dostawca danych widżetu jest aktywny, UPDATE_PERIOD_SECONDS określa, jak często system ma sprawdzać dostępność aktualizacji danych. Jeśli informacje widoczne w widżecie nie muszą być aktualizowane zgodnie ze stałym harmonogramem, np. gdy używasz aktualizacji push, ustaw tę wartość na 0.

Jeśli nie ustawisz UPDATE_PERIOD_SECONDS na 0, musisz użyć wartości co najmniej 300 (5 minut), co jest minimalnym okresem aktualizacji wymuszanym przez system, aby oszczędzać baterię urządzenia. Dodatkowo pamiętaj, że żądania aktualizacji przychodzą rzadziej, gdy urządzenie działa w trybie nieaktywnym lub nie jest używane.

Więcej informacji o wysyłaniu aktualizacji znajdziesz w opisie kluczy dla klasy ComplicationProviderService w dokumentacji interfejsu Wear OS API.

Dodaj działanie konfiguracji

W razie potrzeby dostawca może dołączyć aktywność związaną z konfiguracją, która jest wyświetlana użytkownikowi, gdy użytkownik wybiera dostawcę danych. Aby uwzględnić działanie konfiguracji, w deklaracji usługi dostawcy w pliku manifestu umieść element metadanych z tym kluczem:

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

Wartością może być dowolne działanie.

Następnie utwórz działanie konfiguracji z filtrem intencji dla tego działania. Działanie konfiguracji musi znajdować się w tym samym pakiecie co dostawca. Działanie konfiguracji musi zwracać wartość RESULT_OK lub RESULT_CANCELED, która informuje system, czy należy ustawić dostawcę.

Bezpieczne tarcze zegarka określone przez dostawcę

Dostawcy mogą określić niektóre tarcze zegarka jako „bezpieczne” i mogą odbierać dane. Jest używane tylko wtedy, gdy tarcza zegarka próbuje ustawić dostawcę jako dostawcę domyślnego i traktuje ją jako zaufaną aplikację.

Aby zadeklarować tarcze zegarka jako bezpieczne, dostawca dodaje metadane z kluczem android.support.wearable.complications.SAFE_WATCH_FACES. Wartość metadanych to rozdzielana przecinkami lista nazw komponentów WatchFaceService (jakby wywoływana była funkcja ComponentName.flattenToString()) lub nazwy pakietów aplikacji, w których przypadku każda tarcza zegarka w określonej aplikacji jest uznawana za bezpieczną. Odstępy na liście wartości są ignorowane. Na przykład:

<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"/>

Dodawanie obrazów bezpiecznych do wykrywania wypalania

W trybie nieaktywnym na ekranach narażonych na wypalenie należy unikać stosowania jednolitych bloków kolorów. Jeśli ikony lub obrazy zawierają jednolite bloki koloru, zapewnij też bezpieczną wersję do wypalenia.

Dodając ikonę, korzystając z ComplicationData.Builder#setIcon, dodaj bezpieczną wersję wypaloną za pomocą ComplicationData.Builder#setBurnInProtectionIcon.

Przy dostarczaniu obrazu za pomocą ComplicationData.Builder#setSmallImage dodaj bezpieczną wersję wypalania za pomocą ComplicationData.Builder#setBurnInProtectionSmallImage.

Korzystanie z aktualizacji push

Zamiast określać stały, niezerowy interwał aktualizacji dla widżetu w pliku manifestu aplikacji możesz użyć wystąpienia ComplicationDataSourceUpdateRequester, aby dynamicznie żądać aktualizacji. Aby poprosić o aktualizację treści widocznej dla użytkowników widżetu, wywołaj requestUpdate().

Uwaga: aby oszczędzać baterię urządzenia, nie wywołuj funkcji requestUpdate() z instancji ComplicationDataSourceUpdateRequester częściej niż średnio co 5 minut.

Podaj wartości dynamiczne

Począwszy od Wear OS 4 niektóre widżety mogą wyświetlać wartości, które są odświeżane częściej na podstawie wartości dostępnych bezpośrednio na platformie. Aby udostępnić tę funkcję w swoich widżetach, użyj pól ComplicationData, które akceptują wartości dynamiczne. Platforma często ocenia i aktualizuje te wartości, nie wymagając działania dostawcy widżetu.

Przykładowe pola to dynamiczne pole wartości parametru GoalProgressComplicationData i DynamicComplicationText, których można użyć w dowolnym polu ComplicationText. Te wartości dynamiczne opierają się na bibliotece androidx.wear.protolayout.expression.

W niektórych sytuacjach platforma nie może ocenić wartości dynamicznych:

Podaj wartości zależne od czasu

Niektóre widżety muszą wyświetlać wartość związaną z bieżącą godziną. Może to być na przykład bieżąca data, godzina do następnego spotkania lub godzina w innej strefie czasowej.

Nie aktualizuj widżetów co sekundę ani minutę, aby te wartości były aktualne. Zamiast tego podaj wartości w odniesieniu do bieżącej daty lub godziny, korzystając z tekstu zależnego od czasu. Aby utworzyć te wartości zależne od czasu, możesz użyć monterów w klasie ComplicationText.

Częstotliwość aktualizacji widżetów

Możesz szybko aktualizować widżety. Może to jednak wpłynąć na żywotność baterii urządzenia. Możesz korzystać z uprzywilejowanego interfejsu API żądania widżetu, który umożliwia częstsze aktualizowanie określonych widżetów. Korzystanie z tego interfejsu API musi jednak być dopuszczone przez producenta zegarka. Każdy producent zegarka decyduje, które widżety mogą aktualizować się szybciej niż jest to dozwolone.