Как создать хост виджета

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

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

Ниже приведены основные классы и понятия, связанные с реализацией собственного 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.provider)
    // This is the options bundle described in the preceding section.
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options)
}
startActivityForResult(intent, REQUEST_BIND_APPWIDGET)

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

Обязанности организатора

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

Все ведущие должны:

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

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

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

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

Советы по подходу

Помимо требований, перечисленных в предыдущем разделе, учитывайте следующие рекомендации:

Набор вариантов может содержать List<SizeF>, в котором указан список возможных размеров в единицах dp, которые может принимать экземпляр виджета. Количество доступных размеров зависит от реализации хоста. Обычно хосты предоставляют два размера для телефонов (вертикальный и горизонтальный) и четыре размера для складных устройств.

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

Если в виджетах указаны атрибуты maxResizeWidth и maxResizeHeight в единицах dp, рекомендуем, чтобы виджет, в котором используется хотя бы один из этих атрибутов, не превышал размер, заданный атрибутами.

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

  • Подробная информация приведена в справочной документации по Glance.