В этом руководстве рассказывается, как интегрировать блок "Продолжить просмотр" в приложение для Android TV с помощью Engage SDK.
Подготовка
Выполните инструкции из раздела Предварительная работа в руководстве по началу работы.
Интеграция
Создание объектов
В SDK определены разные объекты, представляющие каждый тип товара. Кластер продолжения поддерживает следующие объекты:
Укажите URI для разных платформ и постеры для этих объектов.
Если вы ещё этого не сделали, создайте URI воспроизведения для каждой платформы, например Android TV, Android или iOS. Поэтому, когда пользователь продолжает просмотр на каждой платформе, приложение использует целевой URI воспроизведения для воспроизведения видеоконтента.
// Required. Set this when you want continue watching entities to show up on
// Google TV
val playbackUriTv = PlatformSpecificUri.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_TV)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_tv"))
.build()
// Required. Set this when you want continue watching entities to show up on
// Google TV Android app, Entertainment Space, Playstore Widget
val playbackUriAndroid = PlatformSpecificUri.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_MOBILE)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_android"))
.build()
// Optional. Set this when you want continue watching entities to show up on
// Google TV iOS app
val playbackUriIos = PlatformSpecificUri.Builder()
.setPlatformType(PlatformType.TYPE_IOS)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_ios"))
.build()
val platformSpecificPlaybackUris =
Arrays.asList(playbackUriTv, playbackUriAndroid, playbackUriIos)
Для постеров необходимо указать URI и размеры в пикселях (высоту и ширину). Чтобы объект "Продолжить просмотр" корректно отображался на разных устройствах, особенно в Entertainment Space, добавьте несколько постеров с соотношением сторон 16:9 и высотой не менее 200 пикселей. Изображения высотой менее 200 пикселей могут не показываться.
val images = Arrays.asList(
Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image1.png"))
.setImageHeightInPixel(300)
.setImageWidthInPixel(169)
.build(),
Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image2.png"))
.setImageHeightInPixel(640)
.setImageWidthInPixel(360)
.build()
// Consider adding other images for different form factors
)
MovieEntity
В примере ниже показано, как создать объект MovieEntity со всеми обязательными полями.
val movieEntity = MovieEntity.Builder()
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Movie name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
// Suppose the duration is 2 hours, it is 72000000 in milliseconds
.setDurationMillis(72000000)
// Suppose last playback offset is 1 hour, 36000000 in milliseconds
.setLastPlayBackPositionTimeMillis(36000000)
.setCallToActionText("Resume")
.addTag("Action")
.build()
Указывая жанры и возрастные ограничения, вы помогаете Google TV показывать ваш контент в более динамичном формате и находить для него подходящую аудиторию.
val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val movieEntity = MovieEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.build()
Объекты автоматически остаются доступными в течение 60 дней, если вы не укажете более короткий срок действия. Задавайте собственный срок хранения, только если вам нужно, чтобы объект был удален раньше.
// Set the expiration time to be now plus 30 days in milliseconds
val expirationTime = DisplayTimeWindow.Builder()
.setEndTimestampMillis(now().toMillis()+2592000000).build()
val movieEntity = MovieEntity.Builder()
...
.addAvailabilityTimeWindow(expirationTime)
.build()
TvEpisodeEntity
В примере ниже показано, как создать объект TvEpisodeEntity со всеми обязательными полями.
val tvEpisodeEntity = TvEpisodeEntity.Builder()
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Episode name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
.setDurationMillis(72000000) // 2 hours in milliseconds
// 45 minutes and 15 seconds in milliseconds is 2715000
.setLastPlayBackPositionTimeMillis(2715000)
.setEpisodeNumber("2")
.setSeasonNumber("1")
.setShowTitle("Title of the show")
.setCallToActionText("Resume")
.addTag("Comedy")
.build()
Строка с номером серии (например, "2") и строка с номером сезона (например, "1") будут преобразованы в правильный формат перед показом на карточке "Продолжить просмотр". Обратите внимание, что это должна быть числовая строка. Не указывайте "e2", "episode 2", "s1" или "season 1".
Если у телешоу только один сезон, укажите номер 1.
Чтобы зрителям было проще находить ваш контент в Google TV, рекомендуем предоставлять дополнительные данные, например жанры, возрастные ограничения и периоды доступности. Это позволит улучшить отображение и фильтрацию контента.
val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val tvEpisodeEntity = TvEpisodeEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.setSeasonTitle("Season Title")
.setShowTitle("Show Title")
.build()
VideoClipEntity
Ниже приведен пример создания VideoClipEntity со всеми обязательными полями.
VideoClipEntity – это пользовательский клип, например видео на YouTube.
val videoClipEntity = VideoClipEntity.Builder()
.setPlayBackUri(Uri.parse("https://www.example.com/uri_for_current_platform"))
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Video clip name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
.setDurationMillis(600000) //10 minutes in milliseconds
.setLastPlayBackPositionTimeMillis(300000) //5 minutes in milliseconds
.setCallToActionText("Resume")
.addTag("Vlog")
.build()
При желании вы можете указать автора, его изображение, время создания в миллисекундах или период доступности .
LiveStreamingVideoEntity
Ниже приведен пример создания LiveStreamingVideoEntity со всеми обязательными полями.
val liveStreamingVideoEntity = LiveStreamingVideoEntity.Builder()
.setPlayBackUri(Uri.parse("https://www.example.com/uri_for_current_platform"))
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Live streaming name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
.setLastPlayBackPositionTimeMillis(36000000) //1 hour in milliseconds
.addContentRating(contentRating)
.setCallToActionText("Resume")
.addTag("Live")
.build()
При необходимости вы можете указать время начала, вещательную компанию, ее значок или временной интервал доступности для объекта трансляции.
Подробную информацию об атрибутах и требованиях можно найти в документации по API.
Предоставьте данные о кластере продолжения
AppEngagePublishClient отвечает за публикацию кластера продолжения действий.
Для публикации объекта ContinuationCluster используется метод publishContinuationCluster.
Инициализируйте клиент и проверьте доступность сервиса, как описано в руководстве по началу работы.
client.publishContinuationCluster(
PublishContinuationClusterRequest
.Builder()
.setContinuationCluster(
ContinuationCluster.Builder()
.setAccountProfile(accountProfile)
.addEntity(movieEntity1)
.addEntity(movieEntity2)
.addEntity(tvEpisodeEntity1)
.addEntity(tvEpisodeEntity2)
.setSyncAcrossDevices(true)
.build()
)
.build()
)
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
ContinuationClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном объекте
ContinuationCluster.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
API публикации – это API upsert, который заменяет существующий контент. Если вам нужно обновить определенный объект в кластере продолжения, вам потребуется опубликовать все объекты заново.
Данные о кластере продолжения должны предоставляться только для аккаунтов взрослых. Публиковать контент можно, только если профиль аккаунта принадлежит взрослому.
Синхронизация между устройствами
setSyncAcrossDevices определяет, синхронизируются ли данные ContinuationCluster пользователя между устройствами, такими как телевизор, телефон, планшет и т. д. По умолчанию синхронизация между устройствами отключена.
Значения:
true: данные кластера продолжения просмотра передаются на все устройства пользователя, чтобы он мог смотреть контент без перерывов. Мы настоятельно рекомендуем этот вариант, чтобы обеспечить наилучшее взаимодействие между устройствами.false: данные кластера продолжения ограничены текущим устройством.
Кроме того, чтобы синхронизировать контент между устройствами, необходимо указать AccountProfile с идентификатором аккаунта. Подробнее о том, как создать профиль аккаунта…
Получение согласия
В мультимедийном приложении должна быть понятная настройка, позволяющая включить или отключить синхронизацию между устройствами. Объясните пользователю преимущества, сохраните его выбор и примените его в publishContinuationCluster.
// Example to allow cross device syncing.
client.publishContinuationCluster(
PublishContinuationClusterRequest
.Builder()
.setContinuationCluster(
ContinuationCluster.Builder()
.setAccountProfile(accountProfile)
.setSyncAcrossDevices(true)
.build()
)
.build()
)
Чтобы максимально эффективно использовать функцию для нескольких устройств, убедитесь, что приложение получает согласие пользователя, и включите SyncAcrossDevices для true. Это позволяет синхронизировать контент на разных устройствах, что повышает удобство для пользователей и их вовлеченность. Например, у одного из партнеров, который реализовал эту функцию, количество кликов по кнопке "Продолжить просмотр" увеличилось на 40 %, поскольку его контент стал доступен на нескольких устройствах.
Удалить данные Engage
Чтобы вручную удалить данные пользователя с сервера Google TV до истечения стандартного 60-дневного срока хранения, используйте метод deleteClusters. После получения запроса сервис удалит все существующие данные Engage для профиля аккаунта или для всего аккаунта.
Перечисление DeleteReason определяет причину удаления данных.
Следующий код удаляет данные о продолжении просмотра при выходе из аккаунта.
// If the user logs out from your media app, you must make the following call
// to remove continue watching data from the current google TV device,
// otherwise, the continue watching data will persist on the current
// google TV device until 60 days later.
client.deleteClusters(
DeleteClustersRequest.Builder()
.setAccountProfile(accountProfile)
.setDeleteReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
.setSyncAcrossDevices(true)
.build()
)
Тестирование
Чтобы проверить, правильно ли работает интеграция Engage SDK, используйте приложение для проверки.
После вызова API публикации убедитесь, что ваши данные публикуются правильно, проверив приложение для проверки. Ваш кластер продолжения должен отображаться в виде отдельной строки в интерфейсе приложения.
- Протестируйте следующие действия в приложении:
- Войдите в аккаунт.
- Переключаться между профилями(если применимо).
- Запустите видео, а затем приостановите его или вернитесь на главную страницу.
- Закройте приложение во время воспроизведения видео.
- Удалить контент из раздела "Продолжить просмотр" (если поддерживается).
- После каждого действия убедитесь, что приложение вызвало API
publishContinuationClustersи данные правильно отображаются в приложении для проверки. Если объект реализован правильно, в приложении для проверки появится зеленая галочка и надпись "Все в порядке".
Рисунок 1. Verification App Success Приложение для проверки пометит все проблемные объекты.
Рисунок 2. Ошибка приложения для подтверждения Чтобы устранить неполадки с объектами, выберите объект в приложении для проверки с помощью пульта телевизора. Проблемы будут выделены красным цветом (см. пример ниже).
Рисунок 3. Сведения об ошибке приложения для проверки