Повышайте вовлеченность пользователей, обращаясь к ним там, где они находятся. Интегрируйте Engage SDK, чтобы показывать контент, который пользователи не досмотрели, и персональные рекомендации непосредственно пользователям на разных платформах на устройстве, например в подборках, Entertainment Space и Google Play. Интеграция добавляет к среднему размеру APK менее 50 КБ (в сжатом виде) и занимает у разработчиков около недели. Подробную информацию вы найдете на нашем сайте.
В этом руководстве содержатся инструкции для партнеров-разработчиков по интеграции видеоконтента с помощью Engage SDK для заполнения как этой новой области, так и существующих областей Google.
Поддерживаемые категории и платформы
Доступность платформ Engage SDK зависит от категории контента в приложении. В таблице ниже указано, какие требования нужно выполнить, чтобы ваши товары показывались на разных платформах.
| Статус | Категория контента или сценарий использования | Поддерживаемые платформы |
|---|---|---|
|
Поддерживается (Доступно на всех платформах) |
|
|
|
Частично поддерживается (Доступно на некоторых платформах) |
|
|
| Чего пользователь не может |
|
Навыки работы с Android
Посмотреть на GitHubИнтегрируйте Engage SDK
android skills add engage-sdk-integrationСведения об интеграции
В этом разделе подробно описаны шаги, модели данных и терминология, необходимые для интеграции с Engage SDK для видеоконтента.
Терминология
Интеграция включает три типа кластеров: Рекомендации, Продолжение и Рекомендуемые.
Рекомендации – персонализированные предложения контента от отдельного партнера-разработчика.
Рекомендации имеют следующую структуру:
Кластер рекомендаций. Раздел интерфейса, в котором собраны рекомендации от одного партнера-разработчика.
Рисунок 1. Интерфейс Entertainment Space с кластером рекомендаций от одного партнера. Объект. Объект, представляющий один элемент в кластере. Объектом может быть фильм, телешоу, сериал, прямая трансляция и т. д. Список поддерживаемых типов объектов приведен в разделе Предоставление данных об объектах.
Рисунок 2. Интерфейс Entertainment Space, в котором показан один объект в кластере рекомендаций одного партнера.
В кластере Продолжение собраны недосмотренные видео и новые серии от разных партнеров-разработчиков. Каждый партнер-разработчик может транслировать в кластере продолжения не более 10 объектов. Исследования показывают, что персональные рекомендации и персонализированный контент для продолжения просмотра обеспечивают наилучшую вовлеченность пользователей.
Рисунок 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.6.0'
}
Подробнее о видимости пакетов в Android 11…
Сводка
Дизайн основан на реализации привязанной службы.
На данные, которые может публиковать клиент, распространяются следующие ограничения для разных типов кластеров:
| Тип кластера | Ограничения кластера | Максимальное количество объектов в кластере |
|---|---|---|
| Кластеры рекомендаций | Не более 7 | Не более 50 |
| Кластер продолжения | Не более 1 | Не более 20 |
| Рекомендуемый кластер | Не более 1 | Не более 20 |
Шаг 0. Переход с существующей интеграции Media Home SDK
В этом разделе рассказывается, как перенести существующие модели данных Media Home SDK и вызовы API в Engage 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. Все объекты, принадлежащие кластеру, публикуются вместе с ним:
Kotlin
RecommendationCluster.Builder()
.addEntity(MOVIE_ENTITY)
.addEntity(MOVIE_ENTITY)
.addEntity(MOVIE_ENTITY)
.setTitle("Top Picks For You")
.build()
Java
new RecommendationCluster.Builder()
.addEntity(MOVIE_ENTITY)
.addEntity(MOVIE_ENTITY)
.addEntity(MOVIE_ENTITY)
.setTitle("Top Picks For You")
.build();
Шаг 1. Укажите данные о компании
В SDK определены разные объекты для представления каждого типа товара. Для категории Watch поддерживаются следующие объекты:
В таблице ниже приведены атрибуты и требования для каждого типа.
MovieEntity
| Атрибут | Требования | Примечания |
|---|---|---|
| Название | Обязательно | |
| Постеры | Обязательно | Необходимо добавить хотя бы одно изображение и указать его соотношение сторон. (Предпочтительна горизонтальная ориентация, но рекомендуется передавать изображения как в горизонтальной, так и в вертикальной ориентации для разных сценариев.)
Ознакомьтесь со спецификациями изображений. |
| URI воспроизведения | Обязательно для мобильных устройств. |
Ссылка на контент в приложении поставщика, по которой можно начать просмотр фильма. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения для определенных платформ | Необязательно для мобильных устройств; обязательно для Google TV. |
Ссылки на контент в приложении поставщика, позволяющие начать воспроизведение фильма на определенной платформе. |
| URI страницы с информацией | Необязательно |
Ссылка на контент в приложении поставщика, по которой можно посмотреть подробную информацию о фильме. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| Дата выпуска | Необязательно | В миллисекундах с начала эпохи. |
| Доступность | Необязательно | AVAILABLE – контент доступен пользователю без дополнительных действий. FREE_WITH_SUBSCRIPTION – контент доступен после оформления подписки. PAID_CONTENT: контент, который нужно купить или взять напрокат. PURCHASED – контент куплен или взят напрокат пользователем. |
| Цена предложения | Необязательно | Произвольный текст |
| Продолжительность | Обязательно | Значение указывается в миллисекундах. |
| жанр; | Необязательно | Произвольный текст |
| Возрастные ограничения | Необязательно | Произвольный текст, соответствующий отраслевому стандарту. (Пример) |
| Текст призыва к действию | Необязательно | Текст, который будет показываться в качестве призыва к действию. |
| Теги | Необязательно | Список тегов, связанных с объектом. |
| Тип рекомендованных видео | Условно обязательно | Обязательный атрибут для товаров из кластера продолжения. Допустимы следующие значения: CONTINUE: пользователь уже посмотрел более 1 минуты этого контента. NEW. Пользователь посмотрел все доступные серии сериала, но вышла новая серия, и теперь есть ровно одна непросмотренная серия. Это работает для сериалов, записей футбольных матчей и т. д. NEXT. Пользователь посмотрел один или несколько эпизодов сериала, но осталось ещё больше одного эпизода или ровно один эпизод, который не является новым и был выпущен до того, как пользователь начал смотреть сериал. WATCHLIST. Пользователь добавил фильм, мероприятие или сериал в список просмотра, чтобы вручную выбрать, что посмотреть дальше. |
| Время последнего взаимодействия | Условно обязательно | Обязательно, если объект находится в кластере продолжения. В миллисекундах с начала эпохи. |
| Время последней позиции воспроизведения | Условно обязательно | Обязательно, если объект находится в кластере продолжения и WatchNextType имеет значение CONTINUE. В миллисекундах с начала эпохи. |
TvShowEntity
| Атрибут | Требования | Примечания |
|---|---|---|
| Название | Обязательно | |
| Постеры | Обязательно | Необходимо добавить хотя бы одно изображение и указать его соотношение сторон. (Предпочтительна горизонтальная ориентация, но рекомендуется передавать изображения как в горизонтальной, так и в вертикальной ориентации для разных сценариев.)
Ознакомьтесь со спецификациями изображений. |
| URI страницы с информацией | Обязательно |
Ссылка на контент в приложении поставщика, по которой можно посмотреть подробную информацию о телешоу. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения | Необязательно |
Ссылка на контент в приложении поставщика, по которой можно начать просмотр телешоу. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения для определенных платформ | Необязательно для мобильных устройств; обязательно для Google TV. |
Ссылки на контент в приложении поставщика, позволяющие начать просмотр телешоу на определенной платформе. |
| Дата выхода первого эпизода | Необязательно | В миллисекундах с начала эпохи. |
| Дата выхода последней серии | Необязательно | В миллисекундах с начала эпохи. |
| Доступность | Необязательно | AVAILABLE – контент доступен пользователю без дополнительных действий. FREE_WITH_SUBSCRIPTION – контент доступен после оформления подписки. PAID_CONTENT: контент, который нужно купить или взять напрокат. PURCHASED – контент куплен или взят напрокат пользователем. |
| Цена предложения | Необязательно | Произвольный текст |
| Количество сезонов | Необязательно | Положительное целое число |
| жанр; | Необязательно | Произвольный текст |
| Возрастные ограничения | Необязательно | Произвольный текст, соответствующий отраслевому стандарту. (Пример) |
| Текст призыва к действию | Необязательно | Текст, который будет показываться в качестве призыва к действию. |
| Теги | Необязательно | Список тегов, связанных с объектом. |
| Тип рекомендованных видео | Условно обязательно | Обязательный атрибут для товаров из кластера продолжения. Допустимы следующие значения: CONTINUE: пользователь уже посмотрел более 1 минуты этого контента. NEW. Пользователь посмотрел все доступные серии сериала, но вышла новая серия, и теперь есть ровно одна непросмотренная серия. Это работает для сериалов, записей футбольных матчей и т. д. NEXT. Пользователь посмотрел один или несколько эпизодов сериала, но осталось ещё больше одного эпизода или ровно один эпизод, который не является новым и был выпущен до того, как пользователь начал смотреть сериал. WATCHLIST. Пользователь добавил фильм, мероприятие или сериал в список просмотра, чтобы вручную выбрать, что посмотреть дальше. |
| Время последнего взаимодействия | Условно обязательно | Обязательно, если объект находится в кластере продолжения. В миллисекундах с начала эпохи. |
| Время последней позиции воспроизведения | Условно обязательно | Обязательно, если объект находится в кластере продолжения и WatchNextType имеет значение CONTINUE. В миллисекундах с начала эпохи. |
TvSeasonEntity
| Атрибут | Требования | Примечания |
|---|---|---|
| Название | Обязательно | |
| Постеры | Обязательно | Необходимо добавить хотя бы одно изображение и указать его соотношение сторон. (Предпочтительна горизонтальная ориентация, но рекомендуется передавать изображения как в горизонтальной, так и в вертикальной ориентации для разных сценариев.)
Ознакомьтесь со спецификациями изображений. |
| URI страницы с информацией | Обязательно |
Ссылка на контент в приложении поставщика, по которой можно посмотреть информацию о сезоне сериала. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения | Необязательно |
Ссылка на контент в приложении поставщика, по которой можно начать просмотр сезона телесериала. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| Номер сезона |
Необязательно Доступно в версии 1.3.1 |
Строка |
| Дата выхода первого эпизода | Необязательно | В миллисекундах с начала эпохи. |
| Дата выхода последней серии | Необязательно | В миллисекундах с начала эпохи. |
| Доступность | Необязательно | AVAILABLE – контент доступен пользователю без дополнительных действий. FREE_WITH_SUBSCRIPTION – контент доступен после оформления подписки. PAID_CONTENT: контент, который нужно купить или взять напрокат. PURCHASED – контент куплен или взят напрокат пользователем. |
| Цена предложения | Необязательно | Произвольный текст |
| Количество выпусков | Необязательно | Положительное целое число |
| жанр; | Необязательно | Произвольный текст |
| Возрастные ограничения | Необязательно | Произвольный текст, соответствующий отраслевому стандарту. (Пример) |
| Текст призыва к действию | Необязательно | Текст, который будет показываться в качестве призыва к действию. |
| Теги | Необязательно | Список тегов, связанных с объектом. |
| Тип рекомендованных видео | Условно обязательно | Обязательный атрибут для товаров из кластера продолжения. Допустимы следующие значения: CONTINUE: пользователь уже посмотрел более 1 минуты этого контента. NEW. Пользователь посмотрел все доступные серии сериала, но вышла новая серия, и теперь есть ровно одна непросмотренная серия. Это работает для сериалов, записей футбольных матчей и т. д. NEXT. Пользователь посмотрел один или несколько эпизодов сериала, но осталось ещё больше одного эпизода или ровно один эпизод, который не является новым и был выпущен до того, как пользователь начал смотреть сериал. WATCHLIST. Пользователь добавил фильм, мероприятие или сериал в список просмотра, чтобы вручную выбрать, что посмотреть дальше. |
| Время последнего взаимодействия | Условно обязательно | Обязательно, если объект находится в кластере продолжения. В миллисекундах с начала эпохи. |
| Время последней позиции воспроизведения | Условно обязательно | Обязательно, если объект находится в кластере продолжения и WatchNextType имеет значение CONTINUE. В миллисекундах с начала эпохи. |
TvEpisodeEntity
| Атрибут | Требования | Примечания |
|---|---|---|
| Название | Обязательно | |
| Постеры | Обязательно | Необходимо добавить хотя бы одно изображение и указать его соотношение сторон. (Предпочтительна горизонтальная ориентация, но рекомендуется передавать изображения как в горизонтальной, так и в вертикальной ориентации для разных сценариев.)
Ознакомьтесь со спецификациями изображений. |
| URI воспроизведения | Обязательно для мобильных устройств. |
Ссылка на контент в приложении поставщика, по которой можно начать воспроизведение выпуска. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения для определенных платформ | Необязательно для мобильных устройств; обязательно для Google TV. |
Ссылки на контент в приложении поставщика, позволяющие начать воспроизведение выпуска на определенной платформе. |
| URI страницы с информацией | Необязательно |
Ссылка на контент в приложении поставщика, по которой можно посмотреть подробную информацию о серии телесериала. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| Название телешоу | Необязательно для мобильных устройств; обязательно для функции "Продолжить просмотр" в Google TV. | Название телешоу, к которому относится серия. |
| Номер сезона | Необязательно для мобильных устройств; обязательно для функции "Продолжить просмотр" в Google TV. | Строка |
| Отображаемый номер серии |
Необязательно для мобильных устройств; обязательно для функции "Продолжить просмотр" в Google TV. Доступно в версии 1.3.1 |
Строка |
| Дата выхода в эфир | Необязательно | В миллисекундах с начала эпохи. |
| Доступность | Необязательно | AVAILABLE – контент доступен пользователю без дополнительных действий. FREE_WITH_SUBSCRIPTION – контент доступен после оформления подписки. PAID_CONTENT: контент, который нужно купить или взять напрокат. PURCHASED – контент куплен или взят напрокат пользователем. |
| Цена предложения | Необязательно | Произвольный текст |
| Продолжительность | Обязательно | Значение должно быть положительным и указываться в миллисекундах. |
| жанр; | Необязательно | Произвольный текст |
| Возрастные ограничения | Необязательно | Произвольный текст, соответствующий отраслевому стандарту. (Пример) |
| Текст призыва к действию | Необязательно | Текст, который будет показываться в качестве призыва к действию. |
| Теги | Необязательно | Список тегов, связанных с объектом. |
| Тип рекомендованных видео | Условно обязательно | Обязательный атрибут для товаров из кластера продолжения. Допустимы следующие значения: CONTINUE: пользователь уже посмотрел более 1 минуты этого контента. NEW. Пользователь посмотрел все доступные серии сериала, но вышла новая серия, и теперь есть ровно одна непросмотренная серия. Это работает для сериалов, записей футбольных матчей и т. д. NEXT. Пользователь посмотрел один или несколько эпизодов сериала, но осталось ещё больше одного эпизода или ровно один эпизод, который не является новым и был выпущен до того, как пользователь начал смотреть сериал. WATCHLIST. Пользователь добавил фильм, мероприятие или сериал в список просмотра, чтобы вручную выбрать, что посмотреть дальше. |
| Время последнего взаимодействия | Условно обязательно | Обязательно, если объект находится в кластере продолжения. В миллисекундах с начала эпохи. |
| Время последней позиции воспроизведения | Условно обязательно | Обязательно, если объект находится в кластере продолжения и WatchNextType имеет значение CONTINUE. В миллисекундах с начала эпохи. |
LiveStreamingVideoEntity
| Атрибут | Требования | Примечания |
|---|---|---|
| Название | Обязательно | |
| Постеры | Обязательно | Необходимо добавить хотя бы одно изображение и указать его соотношение сторон. (Предпочтительна горизонтальная ориентация, но рекомендуется передавать изображения как в горизонтальной, так и в вертикальной ориентации для разных сценариев.)
Ознакомьтесь со спецификациями изображений. |
| URI воспроизведения | Обязательно для мобильных устройств. |
Ссылка на контент в приложении поставщика, по которой можно начать воспроизведение видео. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения для определенных платформ | Необязательно для мобильных устройств; обязательно для Google TV. |
Ссылки на контент в приложении поставщика, которые позволяют начать воспроизведение видео на определенной платформе. |
| Телевещание | Необязательно | Произвольный текст |
| Время начала | Необязательно | В миллисекундах с начала эпохи. |
| Время окончания | Необязательно | В миллисекундах с начала эпохи. |
| Количество просмотров. | Необязательно | Произвольный текст, который нужно локализовать. |
| Текст призыва к действию | Необязательно | Текст, который будет показываться в качестве призыва к действию. |
| Теги | Необязательно | Список тегов, связанных с объектом. |
| Тип рекомендованных видео | Условно обязательно | Обязательный атрибут для товаров из кластера продолжения. Допустимы следующие значения: CONTINUE: пользователь уже посмотрел более 1 минуты этого контента. NEW. Пользователь посмотрел все доступные серии сериала, но вышла новая серия, и теперь есть ровно одна непросмотренная серия. Это работает для сериалов, записей футбольных матчей и т. д. NEXT. Пользователь посмотрел один или несколько эпизодов сериала, но осталось ещё больше одного эпизода или ровно один эпизод, который не является новым и был выпущен до того, как пользователь начал смотреть сериал. WATCHLIST. Пользователь добавил фильм, мероприятие или сериал в список просмотра, чтобы вручную выбрать, что посмотреть дальше. |
| Время последнего взаимодействия | Условно обязательно | Обязательно, если объект находится в кластере продолжения. В миллисекундах с начала эпохи. |
| Время последней позиции воспроизведения | Условно обязательно | Обязательно, если объект находится в кластере продолжения и WatchNextType имеет значение CONTINUE. В миллисекундах с начала эпохи. |
VideoClipEntity
Объект VideoClipEntity представляет видео из социальных сетей, таких как TikTok или YouTube.
| Атрибут | Требования | Примечания |
|---|---|---|
| Название | Обязательно | |
| Постеры | Обязательно | Необходимо добавить хотя бы одно изображение и указать его соотношение сторон. (Предпочтительна горизонтальная ориентация, но рекомендуется передавать изображения как в горизонтальной, так и в вертикальной ориентации для разных сценариев.)
Ознакомьтесь со спецификациями изображений. |
| URI воспроизведения | Обязательно для мобильных устройств. |
Ссылка на контент в приложении поставщика, по которой можно начать воспроизведение видео. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
| URI воспроизведения для определенных платформ | Необязательно для мобильных устройств; обязательно для Google TV. |
Ссылки на контент в приложении поставщика, которые позволяют начать воспроизведение видео на определенной платформе. |
| Время создания | Необязательно | В миллисекундах с начала эпохи. |
| Продолжительность | Обязательно | Значение должно быть положительным и указываться в миллисекундах. |
| Автор | Необязательно | Произвольный текст |
| Изображение автора | Необязательно | Аватар автора |
| Количество просмотров. | Необязательно | Произвольный текст, который нужно локализовать. |
| Текст призыва к действию | Необязательно | Текст, который будет показываться в качестве призыва к действию. |
| Теги | Необязательно | Список тегов, связанных с объектом. |
| Тип рекомендованных видео | Условно обязательно | Обязательный атрибут для товаров из кластера продолжения. Допустимы следующие значения: CONTINUE: пользователь уже посмотрел более 1 минуты этого контента. NEW. Пользователь посмотрел все доступные серии сериала, но вышла новая серия, и теперь есть ровно одна непросмотренная серия. Это работает для сериалов, записей футбольных матчей и т. д. NEXT. Пользователь посмотрел один или несколько эпизодов сериала, но осталось ещё больше одного эпизода или ровно один эпизод, который не является новым и был выпущен до того, как пользователь начал смотреть сериал. WATCHLIST. Пользователь добавил фильм, мероприятие или сериал в список просмотра, чтобы вручную выбрать, что посмотреть дальше. |
| Время последнего взаимодействия | Условно обязательно | Обязательно, если объект находится в кластере продолжения. В миллисекундах с начала эпохи. |
| Время последней позиции воспроизведения | Условно обязательно | Обязательно, если объект находится в кластере продолжения и WatchNextType имеет значение CONTINUE. В миллисекундах с начала эпохи. |
Требования к картинкам
Ниже приведены требования к объектам изображений.
Форматы файлов
PNG, JPG, статический GIF, WebP
Максимальный размер файла
5120 КБ
Дополнительные рекомендации
- Рекомендуемые пределы допустимой области изображения: важный контент должен занимать центральные 80% изображения.
Пример
Kotlin
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)
.setCallToActionText("Watch Now")
.addTag("Action")
.build()
Java
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)
.setCallToActionText("Watch Now")
.addTag("Action")
.build();
Шаг 2. Предоставьте данные о кластере
Рекомендуется выполнять публикацию контента в фоновом режиме (например, с помощью WorkManager) и запланировать ее на регулярной основе или на основе событий (например, каждый раз, когда пользователь открывает приложение или добавляет что-то в корзину).
AppEngagePublishClient отвечает за публикацию кластеров. В клиенте доступны следующие API:
isServiceAvailablepublishRecommendationClusterspublishFeaturedClusterpublishContinuationClusterpublishUserAccountManagementRequestupdatePublishStatusdeleteRecommendationsClustersdeleteFeaturedClusterdeleteContinuationClusterdeleteUserManagementClusterdeleteClusters
isServiceAvailable
Этот API используется, чтобы проверить, доступен ли сервис для интеграции и можно ли показывать контент на устройстве.
Для Engage SDK версии 1.6.0 и выше (рекомендуется)
Навыки работы с Android
Посмотреть на GitHubИнтеграция Engage SDK
android skills add engage-sdk-integrationUse the engage-sdk-integration skill to use Engage SDK 1.6.0 and refactor isServiceAvailable to pass ServiceAvailabilityRequest for publishing all cluster types.Вы можете проверить доступность сервиса для каждого типа кластера, который вы собираетесь опубликовать. API isServiceAvailable принимает объект запроса ServiceAvailabilityRequest, который содержит типы кластеров, для которых необходимо проверить доступность сервиса. В таблице ниже приведены значения перечисления ClusterType, необходимые для ServiceAvailabilityRequest.
| Тип кластера | Константа типа кластера | Целочисленное значение |
|---|---|---|
| Неизвестно | TYPE_UNKNOWN |
0 |
| Кластер рекомендаций | TYPE_RECOMMENDATION |
1 |
| Рекомендуемый кластер | TYPE_FEATURED |
2 |
| Кластер продолжения | TYPE_CONTINUATION |
3 |
| Кластер управления пользователями | TYPE_ENGAGEMENT |
8 |
| Кластер подписок | TYPE_SUBSCRIPTION |
12 |
Kotlin
val request = ServiceAvailabilityRequest.Builder()
.addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
.addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
.build()
client.isServiceAvailable(request).addOnCompleteListener { task ->
if (task.isSuccessful) {
val availabilityMap = task.result
if (availabilityMap[ClusterType.TYPE_CONTINUATION] == true) {
// Proceed with publishing continuation content
}
if (availabilityMap[ClusterType.TYPE_RECOMMENDATION] == true) {
// Proceed with publishing recommendation content
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
}
Java
ServiceAvailabilityRequest request =
new ServiceAvailabilityRequest.Builder()
.addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
.addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
.build();
client.isServiceAvailable(request).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Map<Integer, Boolean> availabilityMap = task.getResult();
if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_CONTINUATION))) {
// Proceed with publishing continuation content
}
if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_RECOMMENDATION))) {
// Proceed with publishing recommendation content
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
});
Функция условной доступности сервиса
В некоторых интегрированных приложениях запрашивается специальная конфигурация, которая периодически включает и отключает сервис Engage, чтобы снизить общую стоимость. Однако такая стратегия периодического приема контента негативно влияет на удобство использования: устаревший контент не будет показываться, а некоторые платформы не будут обслуживаться.
Начиная с версии 1.6.0 Engage SDK позволяет проверять доступность определенных типов кластеров. Если ваше приложение использует прерывистую передачу данных:
- Кластеры продолжения (например, "Продолжить просмотр") по умолчанию включены на всех поддерживаемых устройствах.
- Другие типы кластеров (например, рекомендации) включаются и отключаются периодически.
Если эта конфигурация по умолчанию вам не подходит, напишите на адрес engage-developers@google.com.
Для версий SDK до 1.6.0 (поддержка прекращена)
Kotlin
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.
}
}
Java
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.
Kotlin
client.publishRecommendationClusters(
PublishRecommendationClustersRequest.Builder()
.addRecommendationCluster(
RecommendationCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.setTitle("Top Picks For You")
.build()
)
.build()
)
Java
client.publishRecommendationClusters(
new PublishRecommendationClustersRequest.Builder()
.addRecommendationCluster(
new RecommendationCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.setTitle("Top Picks For You")
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
RecommendationClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере рекомендаций.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishFeaturedCluster
Этот API используется для публикации списка объектов FeaturedCluster.
Kotlin
client.publishFeaturedCluster(
PublishFeaturedClusterRequest.Builder()
.setFeaturedCluster(
FeaturedCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.build())
.build())
Java
client.publishFeaturedCluster(
new PublishFeaturedClusterRequest.Builder()
.setFeaturedCluster(
new FeaturedCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
FeaturedClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishContinuationCluster
Этот API используется для публикации объекта ContinuationCluster.
Kotlin
client.publishContinuationCluster(
PublishContinuationClusterRequest.Builder()
.setContinuationCluster(
ContinuationCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.build())
.build())
Java
client.publishContinuationCluster(
new PublishContinuationClusterRequest.Builder()
.setContinuationCluster(
new ContinuationCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
ContinuationClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере продолжения.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishUserAccountManagementRequest
Этот API используется для публикации карточки входа . Действие "Войти" направляет пользователей на страницу входа в приложение, чтобы оно могло публиковать контент (или предоставлять более персонализированный контент).
Карточка входа содержит следующие метаданные:
| Атрибут | Требования | Описание |
|---|---|---|
| URI действия | Обязательно | Ссылка на контент для действия (например, переход на страницу входа в приложение) |
| Изображение | Необязательно. Если не указано, необходимо указать название. |
Изображение на карточке Изображения с соотношением сторон 16:9 и разрешением 1264 x 712. |
| Название | Необязательно. Если не указано, необходимо добавить изображение. | Название на карточке |
| Текст действия | Необязательно | Текст, который будет показан на кнопке с призывом к действию (например, "Войти") |
| Подзаголовок | Необязательно | Необязательный подзаголовок на карточке |
Kotlin
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());
Java
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 == PUBLISHED). Это необходимо для заполнения панелей управления, на которых статус используется для передачи данных о работоспособности и других показателей интеграции.
- Если контент не опубликован, но статус интеграции не нарушен (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.
Kotlin
client.updatePublishStatus(
PublishStatusRequest.Builder()
.setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
.build())
Java
client.updatePublishStatus(
new PublishStatusRequest.Builder()
.setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
.build());
deleteRecommendationsClusters
Этот API используется для удаления контента из кластеров рекомендаций.
Kotlin
client.deleteRecommendationsClusters()
Java
client.deleteRecommendationsClusters();
Когда сервис получает запрос, он удаляет существующие данные из кластеров рекомендаций. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteFeaturedCluster
Этот API используется для удаления контента из рекомендуемой группы.
Kotlin
client.deleteFeaturedCluster()
Java
client.deleteFeaturedCluster();
Когда сервис получает запрос, он удаляет существующие данные из рекомендуемого кластера. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteContinuationCluster
Этот API используется для удаления контента из кластера продолжения.
Kotlin
client.deleteContinuationCluster()
Java
client.deleteContinuationCluster();
Когда сервис получает запрос, он удаляет существующие данные из кластера продолжения. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteUserManagementCluster
Этот API используется для удаления контента кластера UserAccountManagement.
Kotlin
client.deleteUserManagementCluster()
Java
client.deleteUserManagementCluster();
Когда сервис получает запрос, он удаляет существующие данные из кластера UserAccountManagement. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteClusters
Этот API используется для удаления контента кластера определенного типа.
Kotlin
client.deleteClusters(
DeleteClustersRequest.Builder()
.addClusterType(ClusterType.TYPE_CONTINUATION)
.addClusterType(ClusterType.TYPE_FEATURED)
.addClusterType(ClusterType.TYPE_RECOMMENDATION)
.build())
Java
client.deleteClusters(
new DeleteClustersRequest.Builder()
.addClusterType(ClusterType.TYPE_CONTINUATION)
.addClusterType(ClusterType.TYPE_FEATURED)
.addClusterType(ClusterType.TYPE_RECOMMENDATION)
.build());
Когда сервис получает запрос, он удаляет существующие данные из всех кластеров, соответствующих указанным типам. Клиенты могут передавать один или несколько типов кластеров. В случае ошибки весь запрос отклоняется, а существующее состояние сохраняется.
Обработка ошибок
Настоятельно рекомендуем отслеживать результаты выполнения задач, полученные от API публикации, чтобы при необходимости можно было принять меры по восстановлению и повторной отправке успешной задачи.
Kotlin
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
}
}
}
}
Java
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(). Это позволяет приложениям, которые все ещё находятся в памяти, обмениваться данными.
Kotlin
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)
}
Java
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.
Дальнейшие действия
После завершения интеграции выполните следующие действия:
- Отправьте письмо на адрес
engage-developers@google.comи прикрепите к нему интегрированный APK-файл, готовый к тестированию в Google. - Google выполняет проверку, чтобы убедиться, что интеграция работает правильно. Если потребуются изменения, Google свяжется с вами и сообщит необходимые сведения.
- Если тестирование прошло успешно и изменения не требуются, Google сообщит вам, что вы можете опубликовать обновленный APK-файл в Google Play.
- После того как Google подтвердит, что обновленный APK-файл опубликован в Google Play, ваши кластеры Рекомендации, Избранное и Продолжение могут быть опубликованы и стать видны пользователям.