Повысьте вовлеченность пользователей в приложении, обращаясь к ним там, где они находятся. Интегрируйте Engage SDK, чтобы доставлять контент «Продолжить просмотр» и персонализированные рекомендации непосредственно пользователям на различных устройствах: в Collections , Entertainment Space и Play Store. Интеграция добавляет менее 50 КБ (в сжатом виде) к среднему размеру APK-файла и занимает у большинства приложений около недели времени разработки. Узнайте больше на нашем корпоративном сайте .
В этом руководстве содержатся инструкции для партнеров-разработчиков по интеграции их видеоконтента с использованием Engage SDK для заполнения как этой новой области поверхности, так и существующих поверхностей Google.
Детали интеграции
Терминология
Эта интеграция включает следующие три типа кластеров: Рекомендация , Продолжение и Избранное .
Кластеры рекомендаций отображают персонализированные предложения по контенту для просмотра от отдельного партнера-разработчика.
Ваши рекомендации имеют следующую структуру:
Кластер рекомендаций: представление пользовательского интерфейса, содержащее группу рекомендаций от одного и того же партнера-разработчика.
Рисунок 1. Пользовательский интерфейс Entertainment Space, отображающий кластер рекомендаций от одного партнера. Сущность: объект, представляющий отдельный элемент в кластере. Сущностью может быть фильм, телешоу, сериал, прямая трансляция и многое другое. Список поддерживаемых типов сущностей см. в разделе «Предоставление данных сущности» .
Рисунок 2. Пользовательский интерфейс пространства развлечений, показывающий одну сущность в кластере рекомендаций одного партнера.
Кластер Continuation отображает незаконченные видео и актуальные недавно выпущенные эпизоды от нескольких партнёров-разработчиков в одной группе пользовательского интерфейса. Каждому партнёру-разработчику будет разрешено транслировать не более 10 объектов в кластере Continuation. Исследования показали, что персонализированные рекомендации и персонализированный контент Continuation обеспечивают наилучшее взаимодействие с пользователями.
Рисунок 3. Пользовательский интерфейс Entertainment Space, отображающий кластер продолжения с незавершенными рекомендациями от нескольких партнеров (в настоящее время видна только одна рекомендация). Кластер «Избранное» отображает избранные сущности от нескольких партнёров-разработчиков в одной группе пользовательского интерфейса. Будет создан один кластер «Избранное», который будет отображаться в верхней части пользовательского интерфейса и будет иметь приоритет над всеми кластерами «Рекомендации». Каждому партнёру-разработчику будет разрешено транслировать до 10 сущностей в кластере «Избранное».
Рисунок 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 | Эквивалент интеграции Engage SDK |
---|---|
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 определены различные сущности для представления каждого типа элемента. Для категории «Наблюдение» поддерживаются следующие сущности:
В следующей таблице приведены атрибуты и требования для каждого типа.
MovieEntity
Атрибут | Требование | Примечания |
---|---|---|
Имя | Необходимый | |
Изображения постеров | Необходимый | Требуется как минимум одно изображение с указанием соотношения сторон. (Предпочтительно использовать альбомную ориентацию, но для разных сценариев рекомендуется передавать изображения как с портретной, так и с альбомной ориентацией.) Инструкции см. в разделе «Характеристики изображения» . |
URI воспроизведения | Необходимый | Глубокая ссылка на приложение провайдера для начала воспроизведения фильма. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Информационный адрес страницы | Необязательный | Глубокая ссылка на приложение провайдера для отображения подробностей о фильме. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Дата выпуска | Необязательный | В миллисекундах эпохи. |
Доступность | Необходимый | ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий. БЕСПЛАТНАЯ_ПО_ПОДПИСКЕ: Контент доступен после приобретения пользователем подписки. PAID_CONTENT: контент требует покупки или аренды пользователем. КУПЛЕНО: Контент был куплен или арендован пользователем. |
Цена предложения | Необязательный | Свободный текст |
Продолжительность | Необходимый | В миллисекундах. |
Жанр | Необходимый | Свободный текст |
Рейтинги контента | Необязательный | Свободный текст, соответствующий отраслевому стандарту. ( Пример ) |
Смотреть следующий тип | Условно требуется | Обязательно должно быть указано, если элемент находится в кластере продолжения и должен быть одного из следующих четырех типов: ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента. НОВОЕ: Пользователь посмотрел все доступные серии какого-либо сериала, но появилась новая серия, и осталась ровно одна непросмотренная серия. Это работает для телешоу, записей футбольных матчей в серии и т. д. ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент. СПИСОК ПРОСМОТРА: Пользователь явно решил добавить фильм, событие или сериал в список просмотра, чтобы вручную выбрать, что он хочет посмотреть дальше. |
Время последнего участия | Условно требуется | Необходимо указать, когда элемент находится в кластере продолжения. В миллисекундах эпохи. |
Время последней позиции воспроизведения | Условно требуется | Обязательно, если элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. Время указывается в миллисекундах эпохи. |
TvShowEntity
Атрибут | Требование | Примечания |
---|---|---|
Имя | Необходимый | |
Изображения постеров | Необходимый | Требуется как минимум одно изображение с указанием соотношения сторон. (Предпочтительно использовать альбомную ориентацию, но для разных сценариев рекомендуется передавать изображения как с портретной, так и с альбомной ориентацией.) Инструкции см. в разделе «Характеристики изображения» . |
Информационный адрес страницы | Необходимый | Глубокая ссылка на приложение провайдера для просмотра подробностей телешоу. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
URI воспроизведения | Необязательный | Глубокая ссылка на приложение провайдера для начала воспроизведения телепередачи. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Дата выхода первого эпизода в эфир | Необязательный | В миллисекундах эпохи. |
Дата выхода последней серии | Необязательный | В миллисекундах эпохи. |
Доступность | Необходимый | ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий. БЕСПЛАТНАЯ_ПО_ПОДПИСКЕ: Контент доступен после приобретения пользователем подписки. PAID_CONTENT: контент требует покупки или аренды пользователем. КУПЛЕНО: Контент был куплен или арендован пользователем. |
Цена предложения | Необязательный | Свободный текст |
Количество сезонов | Необходимый | Положительное целое число |
Жанр | Необходимый | Свободный текст |
Рейтинги контента | Необязательный | Свободный текст, соответствующий отраслевому стандарту. ( Пример ) |
Смотреть следующий тип | Условно требуется | Обязательно должно быть указано, если элемент находится в кластере продолжения и должен быть одного из следующих четырех типов: ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента. НОВОЕ: Пользователь посмотрел все доступные серии какого-либо сериала, но появилась новая серия, и осталась ровно одна непросмотренная серия. Это работает для телешоу, записей футбольных матчей в серии и т. д. ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент. СПИСОК ПРОСМОТРА: Пользователь явно решил добавить фильм, событие или сериал в список просмотра, чтобы вручную выбрать, что он хочет посмотреть дальше. |
Время последнего участия | Условно требуется | Необходимо указать, когда элемент находится в кластере продолжения. В миллисекундах эпохи. |
Время последней позиции воспроизведения | Условно требуется | Обязательно, если элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. Время указывается в миллисекундах эпохи. |
TvSeasonEntity
Атрибут | Требование | Примечания |
---|---|---|
Имя | Необходимый | |
Изображения постеров | Необходимый | Требуется как минимум одно изображение с указанием соотношения сторон. (Предпочтительно использовать альбомную ориентацию, но для разных сценариев рекомендуется передавать изображения как с портретной, так и с альбомной ориентацией.) Инструкции см. в разделе «Характеристики изображения» . |
Информационный адрес страницы | Необходимый | Глубокая ссылка на приложение провайдера для отображения подробностей сезона телешоу. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
URI воспроизведения | Необязательный | Прямая ссылка на приложение провайдера для начала просмотра сезона телешоу. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Отображение номера сезона | Необязательный Доступно в версии 1.3.1 | Нить |
Дата выхода первого эпизода в эфир | Необязательный | В миллисекундах эпохи. |
Дата выхода последней серии | Необязательный | В миллисекундах эпохи. |
Доступность | Необходимый | ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий. БЕСПЛАТНАЯ_ПО_ПОДПИСКЕ: Контент доступен после приобретения пользователем подписки. PAID_CONTENT: контент требует покупки или аренды пользователем. КУПЛЕНО: Контент был куплен или арендован пользователем. |
Цена предложения | Необязательный | Свободный текст |
Количество эпизодов | Необходимый | Положительное целое число |
Жанр | Необходимый | Свободный текст |
Рейтинги контента | Необязательный | Свободный текст, соответствующий отраслевому стандарту. ( Пример ) |
Смотреть следующий тип | Условно требуется | Обязательно должно быть указано, если элемент находится в кластере продолжения и должен быть одного из следующих четырех типов: ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента. НОВОЕ: Пользователь посмотрел все доступные серии какого-либо сериала, но появилась новая серия, и осталась ровно одна непросмотренная серия. Это работает для телешоу, записей футбольных матчей в серии и т. д. ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент. СПИСОК ПРОСМОТРА: Пользователь явно решил добавить фильм, событие или сериал в список просмотра, чтобы вручную выбрать, что он хочет посмотреть дальше. |
Время последнего участия | Условно требуется | Необходимо указать, когда элемент находится в кластере продолжения. В миллисекундах эпохи. |
Время последней позиции воспроизведения | Условно требуется | Обязательно, если элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. Время указывается в миллисекундах эпохи. |
TvEpisodeEntity
Атрибут | Требование | Примечания |
---|---|---|
Имя | Необходимый | |
Изображения постеров | Необходимый | Требуется как минимум одно изображение с указанием соотношения сторон. (Предпочтительно использовать альбомную ориентацию, но для разных сценариев рекомендуется передавать изображения как с портретной, так и с альбомной ориентацией.) Инструкции см. в разделе «Характеристики изображения» . |
URI воспроизведения | Необходимый | Глубокая ссылка на приложение провайдера для начала воспроизведения эпизода. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Информационный адрес страницы | Необязательный | Глубокая ссылка на приложение провайдера для просмотра подробностей об эпизоде телешоу. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Отображение номера эпизода | Необязательный Доступно в версии 1.3.1 | Нить |
Дата выхода в эфир | Необходимый | В миллисекундах эпохи. |
Доступность | Необходимый | ДОСТУПНО: Контент доступен пользователю без каких-либо дополнительных действий. БЕСПЛАТНАЯ_ПО_ПОДПИСКЕ: Контент доступен после приобретения пользователем подписки. PAID_CONTENT: контент требует покупки или аренды пользователем. КУПЛЕНО: Контент был куплен или арендован пользователем. |
Цена предложения | Необязательный | Свободный текст |
Продолжительность | Необходимый | Должно быть положительное значение в миллисекундах. |
Жанр | Необходимый | Свободный текст |
Рейтинги контента | Необязательный | Свободный текст, соответствующий отраслевому стандарту. ( Пример ) |
Смотреть следующий тип | Условно требуется | Обязательно должно быть указано, если элемент находится в кластере продолжения и должен быть одного из следующих четырех типов: ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента. НОВОЕ: Пользователь посмотрел все доступные серии какого-либо сериала, но появилась новая серия, и осталась ровно одна непросмотренная серия. Это работает для телешоу, записей футбольных матчей в серии и т. д. ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент. СПИСОК ПРОСМОТРА: Пользователь явно решил добавить фильм, событие или сериал в список просмотра, чтобы вручную выбрать, что он хочет посмотреть дальше. |
Время последнего участия | Условно требуется | Необходимо указать, когда элемент находится в кластере продолжения. В миллисекундах эпохи. |
Время последней позиции воспроизведения | Условно требуется | Обязательно, если элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. Время указывается в миллисекундах эпохи. |
LiveStreamingVideoEntity
Атрибут | Требование | Примечания |
---|---|---|
Имя | Необходимый | |
Изображения постеров | Необходимый | Требуется как минимум одно изображение с указанием соотношения сторон. (Предпочтительно использовать альбомную ориентацию, но для разных сценариев рекомендуется передавать изображения как с портретной, так и с альбомной ориентацией.) Инструкции см. в разделе «Характеристики изображения» . |
URI воспроизведения | Необходимый | Глубокая ссылка на приложение провайдера для начала воспроизведения видео. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Вещатель | Необходимый | Свободный текст |
Время начала | Необязательный | В миллисекундах эпохи. |
Время окончания | Необязательный | В миллисекундах эпохи. |
Количество просмотров | Необязательный | Свободный текст, должен быть локализован. |
Смотреть следующий тип | Условно требуется | Обязательно должно быть указано, если элемент находится в кластере продолжения и должен быть одного из следующих четырех типов: ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента. НОВОЕ: Пользователь посмотрел все доступные серии какого-либо сериала, но появилась новая серия, и осталась ровно одна непросмотренная серия. Это работает для телешоу, записей футбольных матчей в серии и т. д. ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент. СПИСОК ПРОСМОТРА: Пользователь явно решил добавить фильм, событие или сериал в список просмотра, чтобы вручную выбрать, что он хочет посмотреть дальше. |
Время последнего участия | Условно требуется | Необходимо указать, когда элемент находится в кластере продолжения. В миллисекундах эпохи. |
Время последней позиции воспроизведения | Условно требуется | Обязательно, если элемент находится в кластере Continuation и WatchNextType имеет значение CONTINUE. Время указывается в миллисекундах эпохи. |
VideoClipEntity
Объект VideoClipEntity
представляет собой видеообъект из социальных сетей, таких как TikTok или YouTube.
Атрибут | Требование | Примечания |
---|---|---|
Имя | Необходимый | |
Изображения постеров | Необходимый | Требуется как минимум одно изображение с указанием соотношения сторон. (Предпочтительно использовать альбомную ориентацию, но для разных сценариев рекомендуется передавать изображения как с портретной, так и с альбомной ориентацией.) Инструкции см. в разделе «Характеристики изображения» . |
URI воспроизведения | Необходимый | Глубокая ссылка на приложение провайдера для начала воспроизведения видео. Примечание: для атрибуции можно использовать внешние ссылки. См. раздел «Часто задаваемые вопросы». |
Созданное время | Необходимый | В миллисекундах эпохи. |
Продолжительность | Необходимый | Должно быть положительное значение в миллисекундах. |
Создатель | Необходимый | Свободный текст |
Создатель изображения | Необязательный | Изображение аватара Создателя |
Количество просмотров | Необязательный | Свободный текст, должен быть локализован. |
Смотреть следующий тип | Условно требуется | Обязательно должно быть указано, если элемент находится в кластере продолжения и должен быть одного из следующих четырех типов: ПРОДОЛЖИТЬ: Пользователь уже посмотрел более 1 минуты этого контента. НОВОЕ: Пользователь посмотрел все доступные серии какого-либо сериала, но появилась новая серия, и осталась ровно одна непросмотренная серия. Это работает для телешоу, записей футбольных матчей в серии и т. д. ДАЛЕЕ: Пользователь посмотрел один или несколько полных эпизодов некоторого эпизодического контента, но осталось либо больше одного эпизода, либо ровно один эпизод, последний из которых не является «НОВЫМ» и был выпущен до того, как пользователь начал смотреть эпизодический контент. СПИСОК ПРОСМОТРА: Пользователь явно решил добавить фильм, событие или сериал в список просмотра, чтобы вручную выбрать, что он хочет посмотреть дальше. |
Время последнего участия | Условно требуется | Необходимо указать, когда элемент находится в кластере продолжения. В миллисекундах эпохи. |
Время последней позиции воспроизведения | Условно требуется | Обязательно, если элемент находится в кластере 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 рекомендует опубликовать карту входа. Если по какой-либо причине поставщики не могут опубликовать карту входа, мы рекомендуем вызвать 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();
При получении запроса сервис удаляет существующие данные из кластеров рекомендаций. В случае ошибки весь запрос отклоняется, и текущее состояние сохраняется.
deleteFeaturedCluster
Этот API используется для удаления содержимого Featured Cluster.
Котлин
client.deleteFeaturedCluster()
Ява
client.deleteFeaturedCluster();
Получив запрос, сервис удаляет существующие данные из Featured Cluster. В случае ошибки запрос отклоняется полностью, а текущее состояние сохраняется.
deleteContinuationCluster
Этот API используется для удаления содержимого Continuation Cluster.
Котлин
client.deleteContinuationCluster()
Ява
client.deleteContinuationCluster();
Получив запрос, сервис удаляет существующие данные из кластера продолжения. В случае ошибки запрос отклоняется полностью, а текущее состояние сохраняется.
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 определяет, что контент может быть устаревшим (например, недельной давности). Таким образом, появляется больше уверенности в том, что пользователь получит актуальный контент, даже если приложение не запускалось в течение длительного времени.
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),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
// Register Featured Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_FEATURED),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
// Register Continuation Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
}
Ява
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),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
// Register Featured Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
// Register Continuation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
}
Статически объявите реализацию с помощью тега
<receiver>
в файлеAndroidManifest.xml
. Это позволит приложению получать широковещательные намерения, когда оно не запущено, а также публиковать контент.
<application>
<receiver
android:name=".AppEngageBroadcastReceiver"
android:permission="com.google.android.engage.REQUEST_ENGAGE_DATA"
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 SDK» .
Контакт
Если в процессе интеграции возникнут какие-либо вопросы, свяжитесь с нами по адресу Engage-developers@google.com .
Следующие шаги
После завершения этой интеграции ваши дальнейшие шаги будут следующими:
- Отправьте электронное письмо на адрес engagement-developers@google.com и прикрепите свой интегрированный APK-файл, готовый к тестированию Google.
- Google проводит внутреннюю проверку и анализ, чтобы убедиться, что интеграция работает должным образом. Если необходимы изменения, Google свяжется с вами и предоставит всю необходимую информацию.
- После завершения тестирования и отсутствия необходимости внесения изменений Google свяжется с вами, чтобы уведомить о возможности публикации обновленного и интегрированного APK в Play Store.
- После того как Google подтвердит, что ваш обновленный APK был опубликован в Play Store, ваши кластеры «Рекомендации» , «Избранное » и «Продолжение» могут быть опубликованы и видны пользователям.