Engage SDK Watch: инструкции по технической интеграции сторонних разработчиков

Повысьте вовлеченность приложения, охватывая пользователей там, где они находятся. Интегрируйте Engage SDK, чтобы доставлять контент Continue Watching и персонализированные рекомендации непосредственно пользователям на нескольких поверхностях устройства, включая Google TV, Collections , Entertainment Space и Play Store. Интеграция добавляет менее 50 КБ (сжатый) к среднему APK и занимает у большинства приложений около недели времени разработчика. Узнайте больше на нашем бизнес-сайте .

В этом руководстве содержатся инструкции для партнеров-разработчиков по интеграции их видеоконтента с использованием Engage SDK для заполнения как этой новой области поверхности, так и существующих поверхностей Google.

Детали интеграции

Терминология

Эта интеграция включает в себя следующие три типа кластеров: Рекомендация , Продолжение и Избранное .

  • Кластеры рекомендаций отображают персонализированные предложения по просмотру контента от конкретного партнера-разработчика.

    Ваши рекомендации имеют следующую структуру:

    • Кластер рекомендаций: представление пользовательского интерфейса, содержащее группу рекомендаций от одного и того же партнера-разработчика.

      Рисунок 1. Пользовательский интерфейс Entertainment Space, демонстрирующий кластер рекомендаций от одного партнера.
    • Сущность: объект, представляющий один элемент в кластере. Сущность может быть фильмом, телешоу, сериалом, живым видео и т. д. Список поддерживаемых типов сущностей см. в разделе «Предоставление данных сущности» .

      Рисунок 2. Пользовательский интерфейс пространства развлечений, показывающий одну сущность в кластере рекомендаций одного партнера.
  • Кластер Continuation показывает незаконченные видео и соответствующие недавно выпущенные эпизоды от нескольких партнеров-разработчиков в одной группе пользовательского интерфейса. Каждому партнеру-разработчику будет разрешено транслировать максимум 10 объектов в кластере Continuation. Исследования показали, что персонализированные рекомендации вместе с персонализированным контентом Continuation создают наилучшее взаимодействие с пользователем.

    Рисунок 3. Пользовательский интерфейс Entertainment Space, показывающий кластер Continuation с незавершенными рекомендациями от нескольких партнеров (в настоящее время видна только одна рекомендация).
  • Кластер Featured демонстрирует выборку сущностей от нескольких партнеров-разработчиков в одной группе пользовательского интерфейса. Будет один кластер Featured, который будет отображаться в верхней части пользовательского интерфейса с приоритетным размещением над всеми кластерами Recommendation. Каждому партнеру-разработчику будет разрешено транслировать до 10 сущностей в кластере Featured.

    Рисунок 4. Пользовательский интерфейс Entertainment Space, отображающий избранный кластер с рекомендациями от нескольких партнеров (в настоящее время видна только одна рекомендация).

Предварительная работа

Минимальный уровень API: 19

Добавьте библиотеку com.google.android.engage:engage-core в свое приложение:

dependencies {
    // Make sure you also include that repository in your project's build.gradle file.
    implementation 'com.google.android.engage:engage-core:1.5.2'
}

Более подробную информацию см. в разделе Видимость пакетов в Android 11 .

Краткое содержание

Проект основан на реализации связанной службы .

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

Тип кластера Ограничения кластера Максимальные пределы сущностей в кластере
Кластер(ы) рекомендаций Максимум 7 Максимум 50
Продолжение кластера Максимум 1 Максимум 20
Избранный кластер Максимум 1 Максимум 20

Шаг 0: Миграция из существующей интеграции Media Home SDK

Модели картографических данных из существующей интеграции

Если вы переходите с существующей интеграции Media Home, в следующей таблице показано, как сопоставить модели данных в существующих SDK с новым Engage SDK:

Эквивалент интеграции MediaHomeVideoContract Эквивалент интеграции SDK Engage
com.google.android.mediahome.video.PreviewChannel com.google.android.engage.common.datamodel.RecommendationCluster
com.google.android.mediahome.video.PreviewChannel.Builder com.google.android.engage.common.datamodel.RecommendationCluster.Builder
com.google.android.mediahome.video.PreviewChannelHelper com.google.android.engage.video.service.AppEngageVideoClient
com.google.android.mediahome.video.PreviewProgram Разделены на отдельные классы: EventVideo , LiveStreamingVideo , Movie , TvEpisode , TvSeason , TvShow , VideoClipEntity
com.google.android.mediahome.video.PreviewProgram.Builder Разделено на конструкторы в отдельных классах: EventVideo , LiveStreamingVideo , Movie , TvEpisode , TvSeason , TvShow , VideoClipEntity
com.google.android.mediahome.video.VideoContract Больше не нужно.
com.google.android.mediahome.video.WatchNextProgram Разделено на атрибуты в отдельных классах: EventVideoEntity , LiveStreamingVideoEntity , MovieEntity , TvEpisodeEntity , TvSeasonEntity , TvShowEntity , VideoClipEntity
com.google.android.mediahome.video.WatchNextProgram.Builder Разделено на атрибуты в отдельных классах: EventVideoEntity , LiveStreamingVideoEntity , MovieEntity , TvEpisodeEntity , TvSeasonEntity , TvShowEntity , VideoClipEntity

Публикация кластеров в Media Home SDK против Engage SDK

С помощью Media Home SDK кластеры и сущности публиковались через отдельные API:

// 1. Fetch existing channels
List<PreviewChannel> channels = PreviewChannelHelper.getAllChannels();

// 2. If there are no channels, publish new channels
long channelId = PreviewChannelHelper.publishChannel(builder.build());

// 3. If there are existing channels, decide whether to update channel contents
PreviewChannelHelper.updatePreviewChannel(channelId, builder.build());

// 4. Delete all programs in the channel
PreviewChannelHelper.deleteAllPreviewProgramsByChannelId(channelId);

// 5. publish new programs in the channel
PreviewChannelHelper.publishPreviewProgram(builder.build());

С помощью Engage SDK публикация кластера и сущности объединены в один вызов API. Все сущности, принадлежащие кластеру, публикуются вместе с этим кластером:

Котлин

RecommendationCluster.Builder()
            .addEntity(MOVIE_ENTITY)
            .addEntity(MOVIE_ENTITY)
            .addEntity(MOVIE_ENTITY)
            .setTitle("Top Picks For You")
            .build()

Ява

new RecommendationCluster.Builder()
                        .addEntity(MOVIE_ENTITY)
                        .addEntity(MOVIE_ENTITY)
                        .addEntity(MOVIE_ENTITY)
                        .setTitle("Top Picks For You")
                        .build();

Шаг 1: Предоставьте данные об организации

SDK определил различные сущности для представления каждого типа элемента. Мы поддерживаем следующие сущности для категории Watch:

  1. MovieEntity
  2. TvShowEntity
  3. TvSeasonEntity
  4. TvEpisodeEntity
  5. LiveStreamingVideoEntity
  6. VideoClipEntity

В следующей таблице приведены атрибуты и требования для каждого типа.

MovieEntity

Атрибут Требование Примечания
Имя Необходимый
Изображения постеров Необходимый Требуется как минимум одно изображение, и оно должно быть предоставлено с указанием соотношения сторон. (Предпочтительно альбомная ориентация, но рекомендуется передавать как портретные, так и альбомные изображения для разных сценариев.)

Инструкции см. в разделе «Характеристики изображения» .

URI воспроизведения Необходимый

Глубокая ссылка на приложение провайдера для начала воспроизведения фильма.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Информационный адрес страницы Необязательный

Глубокая ссылка на приложение провайдера для просмотра подробностей о фильме.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Дата выпуска Необязательный В миллисекундах эпохи.
Доступность Необходимый

ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий.

FREE_WITH_SUBSCRIPTION: Контент доступен после приобретения пользователем подписки.

PAID_CONTENT: контент требует покупки или аренды пользователем.

КУПЛЕНО: Контент был куплен или арендован пользователем.

Цена предложения Необязательный Свободный текст
Продолжительность Необходимый В миллисекундах.
Жанр Необходимый Свободный текст
Рейтинги контента Необязательный Свободный текст, соответствующий отраслевому стандарту. ( Пример )
Смотреть следующий тип Условно требуется

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

ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента.

НОВОЕ: Пользователь посмотрел все доступные эпизоды из какого-то эпизодического контента, но стал доступен новый эпизод, и есть ровно один непросмотренный эпизод. Это работает для телешоу, записанных футбольных матчей в серии и т. д.

ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент.

СПИСОК НАБЛЮДЕНИЯ: Пользователь явно решил добавить фильм, событие или сериал в список наблюдения, чтобы вручную выбрать, что он хочет посмотреть дальше.

Время последнего участия Условно требуется Необходимо указать, когда элемент находится в кластере Continuation. В миллисекундах эпохи.
Время последней позиции воспроизведения Условно требуется Необходимо указать, когда элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. В миллисекундах эпохи.

TvShowEntity

Атрибут Требование Примечания
Имя Необходимый
Изображения постеров Необходимый Требуется как минимум одно изображение, и оно должно быть предоставлено с указанием соотношения сторон. (Предпочтительно альбомная ориентация, но рекомендуется передавать как портретные, так и альбомные изображения для разных сценариев.)

Инструкции см. в разделе «Характеристики изображения» .

Информационный адрес страницы Необходимый

Глубокая ссылка на приложение провайдера для просмотра подробностей телешоу.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

URI воспроизведения Необязательный

Глубокая ссылка на приложение провайдера для начала воспроизведения телешоу.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Дата выхода первого эпизода в эфир Необязательный В миллисекундах эпохи.
Дата выхода последней серии Необязательный В миллисекундах эпохи.
Доступность Необходимый

ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий.

FREE_WITH_SUBSCRIPTION: Контент доступен после приобретения пользователем подписки.

PAID_CONTENT: контент требует покупки или аренды пользователем.

КУПЛЕНО: Контент был куплен или арендован пользователем.

Цена предложения Необязательный Свободный текст
Количество сезонов Необходимый Положительное целое число
Жанр Необходимый Свободный текст
Рейтинги контента Необязательный Свободный текст, соответствующий отраслевому стандарту. ( Пример )
Смотреть следующий тип Условно требуется

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

ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента.

НОВОЕ: Пользователь посмотрел все доступные эпизоды из какого-то эпизодического контента, но стал доступен новый эпизод, и есть ровно один непросмотренный эпизод. Это работает для телешоу, записанных футбольных матчей в серии и т. д.

ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент.

СПИСОК НАБЛЮДЕНИЯ: Пользователь явно решил добавить фильм, событие или сериал в список наблюдения, чтобы вручную выбрать, что он хочет посмотреть дальше.

Время последнего участия Условно требуется Необходимо указать, когда элемент находится в кластере Continuation. В миллисекундах эпохи.
Время последней позиции воспроизведения Условно требуется Необходимо указать, когда элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. В миллисекундах эпохи.

TvSeasonEntity

Атрибут Требование Примечания
Имя Необходимый
Изображения постеров Необходимый Требуется как минимум одно изображение, и оно должно быть предоставлено с указанием соотношения сторон. (Предпочтительно альбомная ориентация, но рекомендуется передавать как портретные, так и альбомные изображения для разных сценариев.)

Инструкции см. в разделе «Характеристики изображения» .

Информационный адрес страницы Необходимый

Глубокая ссылка на приложение провайдера для отображения подробностей сезона телешоу.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

URI воспроизведения Необязательный

Глубокая ссылка на приложение провайдера для начала просмотра сезона телешоу.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Отображение номера сезона

Необязательный

Доступно в версии 1.3.1

Нить
Дата выхода первого эпизода в эфир Необязательный В миллисекундах эпохи.
Дата выхода последней серии Необязательный В миллисекундах эпохи.
Доступность Необходимый

ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий.

FREE_WITH_SUBSCRIPTION: Контент доступен после приобретения пользователем подписки.

PAID_CONTENT: контент требует покупки или аренды пользователем.

КУПЛЕНО: Контент был куплен или арендован пользователем.

Цена предложения Необязательный Свободный текст
Количество эпизодов Необходимый Положительное целое число
Жанр Необходимый Свободный текст
Рейтинги контента Необязательный Свободный текст, соответствующий отраслевому стандарту. ( Пример )
Смотреть следующий тип Условно требуется

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

ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента.

НОВОЕ: Пользователь посмотрел все доступные эпизоды из какого-то эпизодического контента, но стал доступен новый эпизод, и есть ровно один непросмотренный эпизод. Это работает для телешоу, записанных футбольных матчей в серии и т. д.

ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент.

СПИСОК НАБЛЮДЕНИЯ: Пользователь явно решил добавить фильм, событие или сериал в список наблюдения, чтобы вручную выбрать, что он хочет посмотреть дальше.

Время последнего участия Условно требуется Необходимо указать, когда элемент находится в кластере Continuation. В миллисекундах эпохи.
Время последней позиции воспроизведения Условно требуется Необходимо указать, когда элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. В миллисекундах эпохи.

TvEpisodeEntity

Атрибут Требование Примечания
Имя Необходимый
Изображения постеров Необходимый Требуется как минимум одно изображение, и оно должно быть предоставлено с указанием соотношения сторон. (Предпочтительно альбомная ориентация, но рекомендуется передавать как портретные, так и альбомные изображения для разных сценариев.)

Инструкции см. в разделе «Характеристики изображения» .

URI воспроизведения Необходимый

Глубокая ссылка на приложение провайдера для начала воспроизведения эпизода.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Информационный адрес страницы Необязательный

Глубокая ссылка на приложение провайдера для отображения подробностей об эпизоде ​​телешоу.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Отображение номера эпизода

Необязательный

Доступно в версии 1.3.1

Нить
Дата выхода в эфир Необходимый В миллисекундах эпохи.
Доступность Необходимый

ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий.

FREE_WITH_SUBSCRIPTION: Контент доступен после приобретения пользователем подписки.

PAID_CONTENT: контент требует покупки или аренды пользователем.

КУПЛЕНО: Контент был куплен или арендован пользователем.

Цена предложения Необязательный Свободный текст
Продолжительность Необходимый Должно быть положительное значение в миллисекундах.
Жанр Необходимый Свободный текст
Рейтинги контента Необязательный Свободный текст, соответствующий отраслевому стандарту. ( Пример )
Смотреть следующий тип Условно требуется

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

ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента.

НОВОЕ: Пользователь посмотрел все доступные эпизоды из какого-то эпизодического контента, но стал доступен новый эпизод, и есть ровно один непросмотренный эпизод. Это работает для телешоу, записанных футбольных матчей в серии и т. д.

ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент.

СПИСОК НАБЛЮДЕНИЯ: Пользователь явно решил добавить фильм, событие или сериал в список наблюдения, чтобы вручную выбрать, что он хочет посмотреть дальше.

Время последнего участия Условно требуется Необходимо указать, когда элемент находится в кластере Continuation. В миллисекундах эпохи.
Время последней позиции воспроизведения Условно требуется Необходимо указать, когда элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. В миллисекундах эпохи.

LiveStreamingVideoEntity

Атрибут Требование Примечания
Имя Необходимый
Изображения постеров Необходимый Требуется как минимум одно изображение, и оно должно быть предоставлено с указанием соотношения сторон. (Предпочтительно альбомная ориентация, но рекомендуется передавать как портретные, так и альбомные изображения для разных сценариев.)

Инструкции см. в разделе «Характеристики изображения» .

URI воспроизведения Необходимый

Глубокая ссылка на приложение провайдера для начала воспроизведения видео.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

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

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

ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента.

НОВОЕ: Пользователь посмотрел все доступные эпизоды из какого-то эпизодического контента, но стал доступен новый эпизод, и есть ровно один непросмотренный эпизод. Это работает для телешоу, записанных футбольных матчей в серии и т. д.

ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент.

СПИСОК НАБЛЮДЕНИЯ: Пользователь явно решил добавить фильм, событие или сериал в список наблюдения, чтобы вручную выбрать, что он хочет посмотреть дальше.

Время последнего участия Условно требуется Необходимо указать, когда элемент находится в кластере Continuation. В миллисекундах эпохи.
Время последней позиции воспроизведения Условно требуется Необходимо указать, когда элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. В миллисекундах эпохи.

VideoClipEntity

Объект VideoClipEntity представляет собой видеообъект из социальных сетей, таких как TikTok или YouTube.

Атрибут Требование Примечания
Имя Необходимый
Изображения постеров Необходимый Требуется как минимум одно изображение, и оно должно быть предоставлено с указанием соотношения сторон. (Предпочтительно альбомная ориентация, но рекомендуется передавать как портретные, так и альбомные изображения для разных сценариев.)

Инструкции см. в разделе «Характеристики изображения» .

URI воспроизведения Необходимый

Глубокая ссылка на приложение провайдера для начала воспроизведения видео.

Примечание: Вы можете использовать глубокие ссылки для атрибуции. Обратитесь к этому FAQ

Время создания Необходимый В миллисекундах эпохи.
Продолжительность Необходимый Должно быть положительное значение в миллисекундах.
Создатель Необходимый Свободный текст
Создатель изображения Необязательный Изображение аватара Создателя
Количество просмотров Необязательный Свободный текст, должен быть локализован.
Смотреть следующий тип Условно требуется

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

ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента.

НОВОЕ: Пользователь посмотрел все доступные эпизоды из какого-то эпизодического контента, но стал доступен новый эпизод, и есть ровно один непросмотренный эпизод. Это работает для телешоу, записанных футбольных матчей в серии и т. д.

ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент.

СПИСОК НАБЛЮДЕНИЯ: Пользователь явно решил добавить фильм, событие или сериал в список наблюдения, чтобы вручную выбрать, что он хочет посмотреть дальше.

Время последнего участия Условно требуется Необходимо указать, когда элемент находится в кластере Continuation. В миллисекундах эпохи.
Время последней позиции воспроизведения Условно требуется Необходимо указать, когда элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. В миллисекундах эпохи.

Характеристики изображения

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

Форматы файлов

PNG, JPG, статический GIF, WebP

Максимальный размер файла

5120 КБ

Дополнительные рекомендации

  • Безопасная область изображения: разместите важный контент в центре изображения (80%).

Пример

Котлин

var movie = MovieEntity.Builder()
    .setName("Avengers")
    .addPosterImage(Image.Builder()
                          .setImageUri(Uri.parse("http://www.x.com/image.png"))
                          .setImageHeightInPixel(960)
                          .setImageWidthInPixel(408)
                          .build())
    .setPlayBackUri(Uri.parse("http://tv.com/playback/1"))
    .setReleaseDateEpochMillis(1633032895L)
    .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE)
    .setDurationMillis(12345678L)
    .addGenre("action")
    .addContentRating("R")
    .setWatchNextType(WatchNextType.TYPE_NEW)
    .setLastEngagementTimeMillis(1664568895L)
    .build()

Ява

MovieEntity movie = new MovieEntity.Builder()
                  .setName("Avengers")
                  .addPosterImage(
                      new Image.Builder()
                          .setImageUri(Uri.parse("http://www.x.com/image.png"))
                          .setImageHeightInPixel(960)
                          .setImageWidthInPixel(408)
                          .build())
                  .setPlayBackUri(Uri.parse("http://tv.com/playback/1"))
                  .setReleaseDateEpochMillis(1633032895L)
                  .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE)
                  .setDurationMillis(12345678L)
                  .addGenre("action")
                  .addContentRating("R")
                  .setWatchNextType(WatchNextType.TYPE_NEW)
                  .setLastEngagementTimeMillis(1664568895L)
                  .build();

Шаг 2: Предоставьте данные кластера

Рекомендуется, чтобы задание по публикации контента выполнялось в фоновом режиме (например, с помощью WorkManager ) и планировалось на регулярной основе или на основе события (например, каждый раз, когда пользователь открывает приложение или когда пользователь просто добавляет что-то в свою корзину).

AppEngagePublishClient отвечает за публикацию кластеров. В клиенте доступны следующие API:

  • isServiceAvailable
  • publishRecommendationClusters
  • publishFeaturedCluster
  • publishContinuationCluster
  • publishUserAccountManagementRequest
  • updatePublishStatus
  • deleteRecommendationsClusters
  • deleteFeaturedCluster
  • deleteContinuationCluster
  • deleteUserManagementCluster
  • deleteClusters

isServiceAvailable

Этот API используется для проверки доступности сервиса для интеграции и возможности отображения контента на устройстве.

Котлин

client.isServiceAvailable.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        // Handle IPC call success
        if(task.result) {
          // Service is available on the device, proceed with content publish
          // calls.
        } else {
          // Service is not available, no further action is needed.
        }
    } else {
      // The IPC call itself fails, proceed with error handling logic here,
      // such as retry.
    }
}

Ява

client.isServiceAvailable().addOnCompleteListener(task - > {
    if (task.isSuccessful()) {
        // Handle success
        if(task.getResult()) {
          // Service is available on the device, proceed with content publish
          // calls.
        } else {
          // Service is not available, no further action is needed.
        }
    } else {
      // The IPC call itself fails, proceed with error handling logic here,
      // such as retry.
    }
});

publishRecommendationClusters

Этот API используется для публикации списка объектов RecommendationCluster .

Котлин

client.publishRecommendationClusters(
      PublishRecommendationClustersRequest.Builder()
        .addRecommendationCluster(
          RecommendationCluster.Builder()
            .addEntity(entity1)
            .addEntity(entity2)
            .setTitle("Top Picks For You")
            .build()
        )
        .build()
    )

Ява

client.publishRecommendationClusters(
            new PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    new RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Top Picks For You")
                        .build())
                .build());

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

  • Существующие данные RecommendationCluster от партнера-разработчика удаляются.
  • Данные из запроса анализируются и сохраняются в обновленном кластере рекомендаций.

В случае ошибки весь запрос отклоняется и сохраняется текущее состояние.

publishFeaturedCluster

Этот API используется для публикации списка объектов FeaturedCluster .

Котлин

client.publishFeaturedCluster(
    PublishFeaturedClusterRequest.Builder()
      .setFeaturedCluster(
        FeaturedCluster.Builder()
          .addEntity(entity1)
          .addEntity(entity2)
          .build())
      .build())

Ява

client.publishFeaturedCluster(
            new PublishFeaturedClustersRequest.Builder()
                .addFeaturedCluster(
                    new FeaturedCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .build())
                .build());

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

  • Существующие данные FeaturedCluster от партнера-разработчика удаляются.
  • Данные из запроса анализируются и сохраняются в обновленном Featured Cluster.

В случае ошибки весь запрос отклоняется и сохраняется текущее состояние.

publishContinuationCluster

Этот API используется для публикации объекта ContinuationCluster .

Котлин

client.publishContinuationCluster(
    PublishContinuationClusterRequest.Builder()
      .setContinuationCluster(
        ContinuationCluster.Builder()
          .addEntity(entity1)
          .addEntity(entity2)
          .build())
      .build())

Ява

client.publishContinuationCluster(
            new PublishContinuationClusterRequest.Builder()
                .setContinuationCluster(
                    new ContinuationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .build())
                .build());

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

  • Существующие данные ContinuationCluster от партнера-разработчика удаляются.
  • Данные из запроса анализируются и сохраняются в обновленном кластере продолжения.

В случае ошибки весь запрос отклоняется и сохраняется текущее состояние.

publishUserAccountManagementRequest

Этот API используется для публикации карты входа. Действие входа направляет пользователей на страницу входа в приложение, чтобы приложение могло опубликовать контент (или предоставить более персонализированный контент)

Следующие метаданные являются частью карты входа в систему:

Атрибут Требование Описание
Действие Uri Необходимый Глубокая ссылка на действие (т.е. переход на страницу входа в приложение)
Изображение Необязательно - если не указано, необходимо указать название

Изображение на карте

Изображения с соотношением сторон 16x9 и разрешением 1264x712

Заголовок Необязательно - если не указано, необходимо предоставить изображение Название на карте
Текст действия Необязательный Текст, отображаемый на призыве к действию (например, «Войти»)
Подзаголовок Необязательный Дополнительный подзаголовок на карточке

Котлин

var SIGN_IN_CARD_ENTITY =
      SignInCardEntity.Builder()
          .addPosterImage(
              Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build()

client.publishUserAccountManagementRequest(
            PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

Ява

SignInCardEntity SIGN_IN_CARD_ENTITY =
      new SignInCardEntity.Builder()
          .addPosterImage(
              new Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build();

client.publishUserAccountManagementRequest(
            new PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

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

  • Существующие данные UserAccountManagementCluster от партнера-разработчика удаляются.
  • Данные из запроса анализируются и сохраняются в обновленном кластере UserAccountManagementCluster.

В случае ошибки весь запрос отклоняется и сохраняется текущее состояние.

updatePublishStatus

Если по какой-либо внутренней бизнес-причине ни один из кластеров не опубликован, мы настоятельно рекомендуем обновить статус публикации с помощью API updatePublishStatus . Это важно, потому что:

  • Предоставление статуса во всех сценариях, даже если контент опубликован (СТАТУС == ОПУБЛИКОВАНО), имеет решающее значение для заполнения панелей мониторинга, которые используют этот явный статус для отображения работоспособности и других показателей вашей интеграции.
  • Если контент не опубликован, но статус интеграции не нарушен (STATUS == NOT_PUBLISHED), Google может не выдавать оповещения на панелях мониторинга работоспособности приложения. Это подтверждает, что контент не опубликован из-за ожидаемой ситуации с точки зрения поставщика.
  • Это помогает разработчикам получить представление о том, когда данные публикуются, а когда нет.
  • Google может использовать коды статуса, чтобы подтолкнуть пользователя к выполнению определенных действий в приложении, чтобы он мог увидеть содержимое приложения или преодолеть его.

Список допустимых кодов статуса публикации:

// Content is published
AppEngagePublishStatusCode.PUBLISHED,

// Content is not published as user is not signed in
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN,

// Content is not published as user is not subscribed
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SUBSCRIPTION,

// Content is not published as user location is ineligible
AppEngagePublishStatusCode.NOT_PUBLISHED_INELIGIBLE_LOCATION,

// Content is not published as there is no eligible content
AppEngagePublishStatusCode.NOT_PUBLISHED_NO_ELIGIBLE_CONTENT,

// Content is not published as the feature is disabled by the client
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_FEATURE_DISABLED_BY_CLIENT,

// Content is not published as the feature due to a client error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_CLIENT_ERROR,

// Content is not published as the feature due to a service error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_SERVICE_ERROR,

// Content is not published due to some other reason
// Reach out to engage-developers@ before using this enum.
AppEngagePublishStatusCode.NOT_PUBLISHED_OTHER

Если контент не опубликован из-за того, что пользователь не вошел в систему, Google рекомендует опубликовать Sign In Card. Если по какой-либо причине поставщики не могут опубликовать Sign In Card, мы рекомендуем вызвать API updatePublishStatus с кодом статуса NOT_PUBLISHED_REQUIRES_SIGN_IN

Котлин

client.updatePublishStatus(
   PublishStatusRequest.Builder()
     .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
     .build())

Ява

client.updatePublishStatus(
    new PublishStatusRequest.Builder()
        .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
        .build());

deleteRecommendationClusters

Этот API используется для удаления содержимого кластеров рекомендаций.

Котлин

client.deleteRecommendationClusters()

Ява

client.deleteRecommendationClusters();

Когда служба получает запрос, она удаляет существующие данные из Recommendation Clusters. В случае ошибки весь запрос отклоняется, а существующее состояние сохраняется.

deleteFeaturedCluster

Этот API используется для удаления содержимого Featured Cluster.

Котлин

client.deleteFeaturedCluster()

Ява

client.deleteFeaturedCluster();

Когда служба получает запрос, она удаляет существующие данные из Featured Cluster. В случае ошибки весь запрос отклоняется, а существующее состояние сохраняется.

deleteContinuationCluster

Этот API используется для удаления содержимого Continuation Cluster.

Котлин

client.deleteContinuationCluster()

Ява

client.deleteContinuationCluster();

Когда служба получает запрос, она удаляет существующие данные из Continuation Cluster. В случае ошибки весь запрос отклоняется, а существующее состояние сохраняется.

deleteUserManagementCluster

Этот API используется для удаления содержимого кластера UserAccountManagement.

Котлин

client.deleteUserManagementCluster()

Ява

client.deleteUserManagementCluster();

Когда служба получает запрос, она удаляет существующие данные из кластера UserAccountManagement. В случае ошибки весь запрос отклоняется, а существующее состояние сохраняется.

deleteClusters

Этот API используется для удаления содержимого заданного типа кластера.

Котлин

client.deleteClusters(
    DeleteClustersRequest.Builder()
      .addClusterType(ClusterType.TYPE_CONTINUATION)
      .addClusterType(ClusterType.TYPE_FEATURED)
      .addClusterType(ClusterType.TYPE_RECOMMENDATION)
      .build())

Ява

client.deleteClusters(
            new DeleteClustersRequest.Builder()
                .addClusterType(ClusterType.TYPE_CONTINUATION)
                .addClusterType(ClusterType.TYPE_FEATURED)
                .addClusterType(ClusterType.TYPE_RECOMMENDATION)
                .build());

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

Обработка ошибок

Настоятельно рекомендуется прослушивать результаты выполнения задачи из API публикации, чтобы можно было предпринять последующие действия для восстановления и повторной отправки успешно выполненной задачи.

Котлин

client.publishRecommendationClusters(
        PublishRecommendationClustersRequest.Builder()
          .addRecommendationCluster(..)
          .build())
      .addOnCompleteListener { task ->
        if (task.isSuccessful) {
          // do something
        } else {
          val exception = task.exception
          if (exception is AppEngageException) {
            @AppEngageErrorCode val errorCode = exception.errorCode
            if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
              // do something
            }
          }
        }
      }

Ява

client.publishRecommendationClusters(
              new PublishRecommendationClustersRequest.Builder()
                  .addRecommendationCluster(...)
                  .build())
          .addOnCompleteListener(
              task -> {
                if (task.isSuccessful()) {
                  // do something
                } else {
                  Exception exception = task.getException();
                  if (exception instanceof AppEngageException) {
                    @AppEngageErrorCode
                    int errorCode = ((AppEngageException) exception).getErrorCode();
                    if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
                      // do something
                    }
                  }
                }
              });

Ошибка возвращается как AppEngageException с причиной, указанной в виде кода ошибки.

Код ошибки Имя ошибки Примечание
1 SERVICE_NOT_FOUND Услуга недоступна на данном устройстве.
2 SERVICE_NOT_AVAILABLE Услуга доступна на данном устройстве, но недоступна на момент звонка (например, явно отключена).
3 SERVICE_CALL_EXECUTION_FAILURE Выполнение задачи не удалось из-за проблем с потоками. В этом случае ее можно повторить.
4 SERVICE_CALL_PERMISSION_DENIED Звонящему не разрешается совершать служебный вызов.
5 SERVICE_CALL_INVALID_ARGUMENT Запрос содержит недопустимые данные (например, больше допустимого количества кластеров).
6 SERVICE_CALL_INTERNAL Произошла ошибка на стороне сервиса.
7 SERVICE_CALL_RESOURCE_EXHAUSTED Вызов на обслуживание производится слишком часто.

Шаг 3: Обработка намерений трансляции

Помимо выполнения вызовов API публикации контента через задание, также необходимо настроить BroadcastReceiver для получения запроса на публикацию контента.

Целью широковещательных намерений является в основном повторная активация приложения и принудительная синхронизация данных. Широковещательные намерения не предназначены для очень частой отправки. Они срабатывают только тогда, когда Engage Service определяет, что контент может быть устаревшим (например, недельной давности). Таким образом, есть больше уверенности в том, что пользователь может получить свежий контент, даже если приложение не запускалось в течение длительного периода времени.

BroadcastReceiver необходимо настроить следующими двумя способами:

  • Динамически зарегистрируйте экземпляр класса BroadcastReceiver с помощью Context.registerReceiver() . Это позволяет осуществлять связь из приложений, которые все еще находятся в памяти.

Котлин

class AppEngageBroadcastReceiver : BroadcastReceiver(){
  // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
  // is received
  // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received
  // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
  // received
}

fun registerBroadcastReceivers(context: Context){
  var  context = context
  context = context.applicationContext

// Register Recommendation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_RECOMMENDATION))

// Register Featured Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_FEATURED))

// Register Continuation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION))
}

Ява

class AppEngageBroadcastReceiver extends BroadcastReceiver {
// Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
// is received

// Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received

// Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
// received
}

public static void registerBroadcastReceivers(Context context) {

context = context.getApplicationContext();

// Register Recommendation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_RECOMMENDATION));

// Register Featured Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED));

// Register Continuation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION));

}
  • Статически объявите реализацию с тегом <receiver> в вашем файле AndroidManifest.xml . Это позволяет приложению получать широковещательные намерения, когда оно не запущено, а также позволяет приложению публиковать контент.
<application>
   <receiver
      android:name=".AppEngageBroadcastReceiver"
      android:exported="true"
      android:enabled="true">
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_RECOMMENDATION" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_FEATURED" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_CONTINUATION" />
      </intent-filter>
   </receiver>
</application>

Служба отправляет следующие намерения :

  • com.google.android.engage.action.PUBLISH_RECOMMENDATION Рекомендуется начать вызов publishRecommendationClusters при получении этого намерения.
  • com.google.android.engage.action.PUBLISH_FEATURED При получении этого намерения рекомендуется запустить вызов publishFeaturedCluster .
  • com.google.android.engage.action.PUBLISH_CONTINUATION При получении этого намерения рекомендуется запустить вызов publishContinuationCluster .

Рабочий процесс интеграции

Пошаговое руководство по проверке интеграции после ее завершения см. в разделе Рабочий процесс интеграции Engage developer .

Часто задаваемые вопросы

См. раздел « Часто задаваемые вопросы по Engage SDK» .

Контакт

Если в процессе интеграции возникнут какие-либо вопросы, свяжитесь с нами по адресу Engage-Developers@google.com .

Следующие шаги

После завершения этой интеграции ваши дальнейшие шаги будут следующими:

  • Отправьте электронное письмо на адрес Engage-developers@google.com и прикрепите свой интегрированный APK-файл, готовый к тестированию Google.
  • Google выполняет проверку и внутренние обзоры, чтобы убедиться, что интеграция работает так, как ожидалось. Если необходимы изменения, Google свяжется с вами, чтобы предоставить необходимые данные.
  • После завершения тестирования и отсутствия необходимости внесения изменений Google свяжется с вами, чтобы уведомить вас о том, что вы можете начать публикацию обновленного и интегрированного APK в Play Store.
  • После того как Google подтвердит, что ваш обновленный APK был опубликован в Play Store, ваши кластеры «Рекомендации» , «Избранное » и «Продолжение» могут быть опубликованы и видны пользователям.