Источники данных для виджетов предоставляют информацию для виджетов циферблата часов, обеспечивая отображение текста, изображений и цифр.
Сервис источника данных расширяет SuspendingComplicationDataSourceService , позволяя передавать полезную информацию непосредственно на циферблат часов.
Начиная
Добавьте следующую зависимость в модуль вашего приложения:
dependencies { implementiation("androidx.wear.watchface:watchface-complications-data-source-ktx:1.2.1") }
Создайте службу источника данных.
Когда требуются данные о осложнениях, система Wear OS отправляет запросы на обновление вашему источнику данных. Для ответа на запросы на обновление ваш источник данных должен реализовывать метод onComplicationRequest() класса SuspendingComplicationDataSourceService .
Система Wear OS вызывает onComplicationRequest() , когда ей требуются данные из вашего источника — например, когда становится активным виджет, использующий ваш источник данных, или когда проходит фиксированный промежуток времени.
Примечание: Когда источник данных предоставляет информацию, циферблат часов получает исходные значения. Циферблат отвечает за форматирование данных для отображения.
Приведённый ниже фрагмент кода демонстрирует пример реализации:
class MyComplicationDataSourceService : SuspendingComplicationDataSourceService() { override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? { // Retrieve the latest info for inclusion in the data. val text = getLatestData() return shortTextComplicationData(text) } override fun getPreviewData(type: ComplicationType): ComplicationData? { return shortTextComplicationData("Event 1") } private fun shortTextComplicationData(text: String) = ShortTextComplicationData.Builder( text = PlainComplicationText.Builder(text).build(), contentDescription = PlainComplicationText.Builder(text).build() ) // Add further optional details here such as icon, tap action, and title. .build() // ... }
Манифестные декларации и разрешения
Для того чтобы система Android рассматривала источники данных как источники данных, они должны содержать специальные объявления в своем манифесте приложения. В этом разделе описаны необходимые настройки для источников данных.
В манифесте вашего приложения объявите службу и добавьте фильтр намерений для действия запроса обновления. Манифест также должен защищать службу, добавив разрешение BIND_COMPLICATION_PROVIDER , чтобы гарантировать, что только система Wear OS может подключаться к службам поставщика.
Кроме того, добавьте атрибут android:icon к элементу service , который предоставляет одноцветную белую иконку. Мы рекомендуем использовать векторные изображения для иконок. Иконка представляет собой источник данных и отображается в окне выбора элементов.
Вот пример:
<service android:name=".snippets.complication.MyComplicationDataSourceService" android:exported="true" android:label="@string/my_complication_service_label" android:icon="@drawable/complication_icon" 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> <!-- Supported types should be comma-separated, for example: "SHORT_TEXT,SMALL_IMAGE" --> <meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES" android:value="SHORT_TEXT" /> <meta-data android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS" android:value="300" /> <!-- Optionally, specify a configuration activity, where the user can configure your complication. --> <meta-data android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION" android:value="MY_CONFIG_ACTION" /> </service>
Элементы метаданных
В файле манифеста обратите внимание на следующие элементы метаданных:
-
android:name="android.support.wearable.complications.SUPPORTED_TYPES": Указывает типы данных осложнений, которые поддерживает источник данных. -
android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS": Указывает, как часто система должна проверять наличие обновлений данных.
Когда источник данных для виджета активен, UPDATE_PERIOD_SECONDS определяет, как часто система должна проверять наличие обновлений данных. Если информация, отображаемая в виджете, не требует регулярного обновления, например, при использовании push-уведомлений , установите это значение равным 0 .
Если вы не установите значение UPDATE_PERIOD_SECONDS равным 0 , необходимо использовать значение не менее 300 (5 минут), что является минимальным периодом обновления, установленным системой для экономии заряда батареи устройства. Кроме того, имейте в виду, что запросы на обновление поступают реже, когда устройство находится в фоновом режиме или не носится.
Добавить действие настройки
При необходимости источник данных может включать в себя действие настройки, которое отображается пользователю при выборе этого конкретного источника данных в окне выбора виджета. Например, источник данных «мировые часы» может иметь действие настройки, позволяющее пользователю выбрать город или часовой пояс для отображения.
В примере манифеста содержится элемент meta-data с ключом PROVIDER_CONFIG_ACTION . Значение этого элемента — действие, используемое для запуска процесса настройки.
Создайте действие конфигурации и добавьте в файл манифеста фильтр намерений, соответствующий действию для этого действия.
<intent-filter> <action android:name="MY_CONFIG_ACTION" /> <category android:name="android.support.wearable.complications.category.PROVIDER_CONFIG" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
Активность может получить подробную информацию о настраиваемом слоте для виджета из интента в методе onCreate() активности:
// Keys defined on ComplicationDataSourceService val id = intent.getIntExtra(EXTRA_CONFIG_COMPLICATION_ID, -1) val type = intent.getIntExtra(EXTRA_CONFIG_COMPLICATION_TYPE, -1) val source = intent.getStringExtra(EXTRA_CONFIG_DATA_SOURCE_COMPONENT)
Операция настройки должна находиться в том же пакете, что и поставщик. Операция настройки должна возвращать RESULT_OK или RESULT_CANCELED чтобы сообщить системе, следует ли устанавливать источник данных:
setResult(RESULT_OK) // Or RESULT_CANCELED to cancel configuration finish()
Используйте push-уведомления
В качестве альтернативы указанию интервала обновления в манифесте вашего приложения вы можете использовать экземпляр ComplicationDataSourceUpdateRequester для динамического инициирования обновлений. Чтобы запросить обновление, вызовите requestUpdate() .
Внимание: Чтобы продлить срок службы батареи устройства, не вызывайте requestUpdate() из экземпляра ComplicationDataSourceUpdateRequester чаще, чем каждые 5 минут в среднем.
Укажите значения, зависящие от времени.
Некоторые элементы интерфейса должны отображать значение, соответствующее текущему времени. Например, текущую дату, время до следующей встречи или время в другом часовом поясе.
Не обновляйте виджет каждую секунду или минуту, чтобы поддерживать актуальность значений. Вместо этого указывайте значения относительно текущей даты или времени, используя текст, зависящий от времени. Следующие классы позволяют создавать такие значения, зависящие от времени:
-
TimeFormatComplicationText— форматирует значение даты или времени. -
TimeDifferenceComplicationText— отсчитывает время в прямом или обратном порядке до указанного момента времени.
Данные временной шкалы
Для источников данных о осложнениях, предоставляющих последовательность значений в заранее определенные моменты времени, используйте SuspendingTimelineComplicationDataSourceService .
Примером может служить источник данных «следующее событие» из календарного приложения: вместо того, чтобы системе приходилось регулярно опрашивать источник данных на предмет следующего события, источник данных может предоставить хронологию событий один раз, а затем инициировать обновления, если календарь изменится. Это минимизирует нагрузку на систему и позволяет виджету своевременно отображать правильное событие.
class MyTimelineComplicationDataSourceService : SuspendingTimelineComplicationDataSourceService() { override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationDataTimeline? { if (request.complicationType != ComplicationType.SHORT_TEXT) { return ComplicationDataTimeline( defaultComplicationData = NoDataComplicationData(), timelineEntries = emptyList() ) } // Retrieve list of events from your own datasource / database. val events = getCalendarEvents() return ComplicationDataTimeline( defaultComplicationData = shortTextComplicationData("No event"), timelineEntries = events.map { TimelineEntry( validity = TimeInterval(it.start, it.end), complicationData = shortTextComplicationData(it.name) ) } ) } override fun getPreviewData(type: ComplicationType): ComplicationData? { return shortTextComplicationData("Event 1") } private fun shortTextComplicationData(text: String) = ShortTextComplicationData.Builder( text = PlainComplicationText.Builder(text).build(), contentDescription = PlainComplicationText.Builder(text).build() ) // Add further optional details here such as icon, tap action, title etc .build() // ... }
Поведение объекта SuspendingTimelineComplicationDataSourceService следующее:
- Если текущее время попадает в диапазон между временем начала и окончания записи на временной шкале, циферблат часов использует это значение.
- Если текущее время не попадает ни в одну запись на временной шкале, используется значение по умолчанию. Например, в приложении «Календарь» это может быть «Нет события».
- Если текущее время попадает в период между несколькими событиями, используется кратчайшее из них.
Предоставляйте динамические значения
Начиная с Wear OS 4, некоторые виджеты могут отображать значения, которые обновляются чаще в зависимости от значений, доступных непосредственно платформе. Чтобы обеспечить эту возможность в ваших виджетах, используйте поля ComplicationData , принимающие динамические значения . Платформа часто оценивает и обновляет эти значения, не требуя запуска поставщика виджетов.
В качестве примеров полей можно привести динамическое поле значений из класса GoalProgressComplicationData и поле DynamicComplicationText , которое можно использовать в любом поле ComplicationText . Эти динамические значения основаны на библиотеке androidx.wear.protolayout.expression .
В определенных ситуациях платформа не может обрабатывать динамические значения:
- Динамическое значение иногда недоступно: это происходит, например, когда устройство снято с запястья. В таких ситуациях платформа использует вместо этого значение резервного поля для аннулирования динамического значения , находящегося в поле-заполнителе объекта
NoDataComplicationData. - Динамическое значение никогда недоступно: это происходит на устройстве, работающем под управлением более старой версии Wear OS 4. В этой ситуации платформа использует дополнительное резервное поле, например,
getFallbackValue ().