Создайте хост виджетов

Главный экран Android, доступный на большинстве устройств под управлением Android, позволяет пользователю встраивать виджеты приложений (или виджеты ) для быстрого доступа к контенту. Если вы создаете замену домашнего экрана или подобное приложение, вы также можете разрешить пользователю встраивать виджеты, реализовав AppWidgetHost . Это не то, что нужно делать большинству приложений, но если вы создаете свой собственный хост, важно понимать договорные обязательства, с которыми хост неявно соглашается.

На этой странице основное внимание уделяется обязанностям, связанным с реализацией пользовательского AppWidgetHost . Конкретный пример реализации AppWidgetHost см. в исходном коде LauncherAppWidgetHost для домашнего экрана Android.

Вот обзор ключевых классов и концепций, задействованных в реализации пользовательского AppWidgetHost :

  • Хост виджетов приложения : AppWidgetHost обеспечивает взаимодействие со службой AppWidget для приложений, которые встраивают виджеты в свой пользовательский интерфейс. AppWidgetHost должен иметь уникальный идентификатор в пределах собственного пакета узла. Этот идентификатор сохраняется при любом использовании хоста. Идентификатор обычно представляет собой жестко закодированное значение, которое вы назначаете в своем приложении.

  • Идентификатор виджета приложения : каждому экземпляру виджета присваивается уникальный идентификатор во время привязки. См. bindAppWidgetIdIfAllowed() и более подробную информацию в следующем разделе «Привязка виджетов» . Хост получает уникальный идентификатор с помощью allocateAppWidgetId() . Этот идентификатор сохраняется на протяжении всего времени существования виджета, пока он не будет удален с хоста. Любое состояние, зависящее от хоста, например размер и расположение виджета, должно сохраняться в пакете хостинга и быть связано с идентификатором виджета приложения.

  • Представление хоста виджета приложения : думайте о AppWidgetHostView как о рамке, в которую помещается виджет всякий раз, когда его необходимо отобразить. Виджет связывается с AppWidgetHostView каждый раз, когда виджет раздувается узлом.

    • По умолчанию система создает AppWidgetHostView , но хост может создать свой собственный подкласс AppWidgetHostView , расширив его.
    • Начиная с Android 12 (уровень API 31), AppWidgetHostView представляет методы setColorResources() и resetColorResources() для обработки динамически перегруженных цветов. Хост отвечает за предоставление цветов этим методам.
  • Пакет параметров : AppWidgetHost использует пакет параметров для передачи информации AppWidgetProvider о том, как отображается виджет — например, список диапазонов размеров — и находится ли виджет на экране блокировки или на главном экране. Эта информация позволяет AppWidgetProvider адаптировать содержимое и внешний вид виджета в зависимости от того, как и где он отображается. Вы можете использовать updateAppWidgetOptions() и updateAppWidgetSize() для изменения пакета виджета. Оба эти метода запускают обратный вызов onAppWidgetOptionsChanged() для AppWidgetProvider .

Привязка виджетов

Когда пользователь добавляет виджет на хост, происходит процесс, называемый привязкой . Привязка означает связывание определенного идентификатора виджета приложения с определенным хостом и конкретным AppWidgetProvider .

API-интерфейсы привязки также позволяют хосту предоставлять собственный пользовательский интерфейс для привязки. Чтобы использовать этот процесс, ваше приложение должно объявить разрешение BIND_APPWIDGET в манифесте хоста:

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

Но это только первый шаг. Во время выполнения пользователь должен явно предоставить разрешение вашему приложению, чтобы оно могло добавить виджет на хост. Чтобы проверить, имеет ли ваше приложение разрешение на добавление виджета, используйте метод bindAppWidgetIdIfAllowed() . Если bindAppWidgetIdIfAllowed() возвращает false , ваше приложение должно отобразить диалоговое окно, предлагающее пользователю предоставить разрешение: «разрешить» для текущего добавления виджета или «всегда разрешать», чтобы охватить все будущие добавления виджетов.

В этом фрагменте приведен пример отображения диалогового окна:

Котлин

val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply {
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName)
    // This is the options bundle described in the preceding section.
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options)
}
startActivityForResult(intent, REQUEST_BIND_APPWIDGET)

Ява

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
// This is the options bundle described in the preceding section.
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET);

Хост должен проверить, нуждается ли виджет, добавляемый пользователем, в настройке. Дополнительные сведения см. в разделе Разрешение пользователям настраивать виджеты приложений .

Обязанности принимающей стороны

Вы можете указать ряд настроек конфигурации виджетов с помощью метаданных AppWidgetProviderInfo . Вы можете получить эти параметры конфигурации, более подробно описанные в следующих разделах, из объекта AppWidgetProviderInfo , связанного с поставщиком виджетов.

Независимо от версии Android, на которую вы ориентируетесь, все хосты имеют следующие обязанности:

  • При добавлении виджета назначьте идентификатор виджета, как описано ранее. Когда виджет удаляется с хоста, вызовите deleteAppWidgetId() чтобы освободить идентификатор виджета.

  • При добавлении виджета проверьте, нужно ли запускать конфигурационное действие. Обычно хосту необходимо запустить действие настройки виджета, если он существует и не помечен как необязательный, путем указания флагов configuration_optional и reconfigurable . Подробности см. в разделе Обновление виджета из действия конфигурации . Это необходимый шаг для многих виджетов, прежде чем они смогут отображаться.

  • Виджеты указывают ширину и высоту по умолчанию в метаданных AppWidgetProviderInfo . Эти значения определяются в ячейках (начиная с Android 12, если указаны targetCellWidth и targetCellHeight ) или в dps, если указаны только minWidth и minHeight . См. Атрибуты размера виджета .

    Убедитесь, что виджет выложен как минимум с таким количеством dps. Например, многие хостеры выравнивают значки и виджеты по сетке. В этом сценарии по умолчанию хост добавляет виджет, используя минимальное количество ячеек, удовлетворяющее ограничениям minWidth и minHeight .

В дополнение к требованиям, перечисленным в предыдущем разделе, определенные версии платформы вводят функции, которые налагают новые обязанности на хост.

Определите свой подход на основе целевой версии Android.

Андроид 12

Android 12 (уровень API 31) включает дополнительный List<SizeF> , который содержит список возможных размеров в dps, которые экземпляр виджета может принимать в пакете параметров. Количество предоставляемых размеров зависит от реализации хоста. Хозяева обычно предоставляют два размера для телефонов — книжную и альбомную — и четыре размера для складных.

Существует ограничение MAX_INIT_VIEW_COUNT (16) на количество различных RemoteViews , которые AppWidgetProvider может предоставить RemoteViews . Поскольку объекты AppWidgetProvider сопоставляют объект RemoteViews с каждым размером в List<SizeF> , не указывайте размеры, превышающие MAX_INIT_VIEW_COUNT .

В Android 12 также представлены атрибуты maxResizeWidth и maxResizeHeight в dps. Мы рекомендуем, чтобы виджет, использующий хотя бы один из этих атрибутов, не превышал размера, указанного атрибутами.

Дополнительные ресурсы

  • См. справочную документацию Glance .