book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml
Esta guía contiene instrucciones para que los desarrolladores integren su contenido de video recomendado con el SDK de Engage para propagar experiencias de recomendaciones en las plataformas de Google, como TVs, dispositivos móviles y tablets.
La recomendación aprovecha el clúster de Recommendation para mostrar películas y programas de TV de varias apps en una sola agrupación de IU. Cada socio desarrollador puede transmitir un máximo de 25 entidades en cada clúster de recomendaciones, y puede haber un máximo de 7 clústeres de recomendaciones por solicitud.
Trabajo previo
Completa las instrucciones de Trabajo previo en la guía de introducción.
- Ejecutar la publicación en un servicio en primer plano
- Publica los datos de recomendaciones como máximo una vez al día, ya sea con uno de los siguientes activadores:
- Es el primer acceso del usuario en el día. (o)
- Cuando el usuario comienza a interactuar con la aplicación.
Integración
AppEngagePublishClient publica el clúster de Recommendation. Usa el método publishRecommendationClusters para publicar un objeto de recomendaciones.
Asegúrate de inicializar el cliente y verificar la disponibilidad del servicio como se describe en la guía de introducción.
client.publishRecommendationClusters(recommendationRequest)
Cómo insertar y actualizar clústeres de recomendaciones
Los clústeres son agrupaciones lógicas de las entidades. En los siguientes ejemplos de código, se explica cómo compilar los clústeres según tus preferencias y cómo crear una solicitud de publicación y, luego, insertar o actualizar todos los clústeres.
El RecommendationClusterType determina cómo se mostrará el clúster.
// cluster for popular movies
val recommendationCluster1 = RecommendationCluster
.Builder()
.addEntity(movie1)
.addEntity(movie2)
.addEntity(movie3)
.addEntity(movie4)
.addEntity(tvShow)
// This cluster is meant to be used as an individual provider row
.setRecommendationClusterType(TYPE_PROVIDER_ROW)
.setTitle("Popular Movies")
.build()
// cluster for live TV programs
val recommendationCluster2 = RecommendationCluster
.Builder()
.addEntity(liveTvProgramEntity1)
.addEntity(liveTvProgramEntity2)
.addEntity(liveTvProgramEntity3)
.addEntity(liveTvProgramEntity4)
.addEntity(liveTvProgramEntity5)
// This cluster is meant to be used as an individual provider row
.setRecommendationClusterType(TYPE_PROVIDER_ROW)
.setTitle("Popular Live TV Programs")
.build()
// creating a publishing request
val recommendationRequest = PublishRecommendationClustersRequest
.Builder()
.setSyncAcrossDevices(true)
.setAccountProfile(accountProfile)
.addRecommendationCluster(recommendationCluster1)
.addRecommendationCluster(recommendationCluster2)
.build()
Cuando el servicio recibe la solicitud, se realizan las siguientes acciones en una transacción:
- Se quitan los datos existentes de
RecommendationsClusterdel socio desarrollador. - Los datos de la solicitud se analizan y se almacenan en el
RecommendationsClusteractualizado. En caso de error, se rechaza la solicitud completa y se mantiene el estado existente.
Sincronización entre dispositivos
La marca SyncAcrossDevices controla si los datos de clúster de recomendaciones de un usuario se comparten con Google TV y están disponibles en sus dispositivos, como TVs, teléfonos y tablets. Para que la recomendación funcione, se debe establecer como verdadero.
Obtén el consentimiento
La app de medios debe proporcionar un parámetro de configuración claro para habilitar o inhabilitar la sincronización multidispositivo. Explica los beneficios al usuario y almacena su preferencia una vez para aplicarla en la solicitud de publishRecommendations según corresponda. Para aprovechar al máximo la función multidispositivo, verifica que la app obtenga el consentimiento del usuario y habilite SyncAcrossDevices para true.
Borra los datos de descubrimiento de videos
Para borrar manualmente los datos de un usuario del servidor de Google TV antes del período de retención estándar de 60 días, usa el método client.deleteClusters(). Cuando recibe la solicitud, el servicio borra todos los datos existentes de descubrimiento de videos del perfil de la cuenta o de toda la cuenta.
La enumeración DeleteReason define el motivo de la eliminación de datos.
El siguiente código quita las recomendaciones cuando se cierra la sesión.
// If the user logs out from your media app, you must make the following call
// to remove recommendations data from the current Google TV device, otherwise,
// the recommendations data persists on the current Google TV device until 60
// days later.
client.deleteClusters(
new DeleteClustersRequest.Builder()
.setAccountProfile(AccountProfile())
.setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
.build()
)
// If the user revokes the consent to share data with Google TV, you must make
// the following call to remove recommendations data from all current Google TV
// devices. Otherwise, the recommendations data persists until 60 days later.
client.deleteClusters(
new DeleteClustersRequest.Builder()
.setAccountProfile(AccountProfile())
.setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
.build()
)
Crea entidades
El SDK definió distintas entidades para representar cada tipo de elemento. Las siguientes entidades son compatibles con el clúster de recomendaciones:
Proporciona descripciones
Proporciona una breve descripción de cada entidad. Esta descripción se mostrará cuando los usuarios coloquen el cursor sobre la entidad, lo que les proporcionará detalles adicionales.
URIs de reproducción específicos de la plataforma
Crea URIs de reproducción para cada plataforma compatible: Android TV, Android o iOS. Esto permite que el sistema seleccione el URI adecuado para la reproducción de video en la plataforma respectiva.
En el caso poco frecuente en que los URIs de reproducción sean idénticos para todas las plataformas, repítelos para cada una.
// Required. Set this when you want recommended 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()
// Optional. Set this when you want recommended entities to show up on
// Google TV Android app
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 recommended 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)
// Provide appropriate rating for the system.
val contentRating = new RatingSystem
.Builder()
.setAgencyName("MPAA")
.setRating("PG-13")
.build()
Imágenes de pósteres
Las imágenes de póster requieren un URI y dimensiones en píxeles (alto y ancho). Proporciona varias imágenes de póster para segmentar diferentes factores de forma, pero verifica que todas las imágenes mantengan una relación de aspecto de 16:9 y una altura mínima de 200 píxeles para que la entidad "Recomendaciones" se muestre correctamente, en especial dentro del Espacio de entretenimiento de Google. Es posible que no se muestren las imágenes con una altura inferior a 200 píxeles.
Image image1 = new Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image1.png");)
.setImageHeightInPixel(300)
.setImageWidthInPixel(169)
.build()
Image image2 = new Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image2.png");)
.setImageHeightInPixel(640)
.setImageWidthInPixel(360)
.build()
// And other images for different form factors.
val images = Arrays.asList(image1, image2)
Motivo de la recomendación
De forma opcional, proporciona un motivo de recomendación que Google TV puede usar para explicar por qué se sugiere una película o un programa de TV específicos al usuario.
//Allows us to construct reason: "Because it is top 10 on your Channel"
val topOnPartner = RecommendationReasonTopOnPartner
.Builder()
.setNum(10) //any valid integer value
.build()
//Allows us to construct reason: "Because it is popular on your Channel"
val popularOnPartner = RecommendationReasonPopularOnPartner
.Builder()
.build()
//Allows us to construct reason: "New to your channel, or Just added"
val newOnPartner = RecommendationReasonNewOnPartner
.Builder()
.build()
//Allows us to construct reason: "Because you watched Star Wars"
val watchedSimilarTitles = RecommendationReasonWatchedSimilarTitles
.addSimilarWatchedTitleName("Movie or TV Show Title")
.addSimilarWatchedTitleName("Movie or TV Show Title")
.Builder()
.build()
//Allows us to construct reason: "Recommended for you by ChannelName"
val recommendedForUser = RecommendationReasonRecommendedForUser
.Builder()
.build()
val watchAgain = RecommendationReasonWatchAgain
.Builder()
.build()
val fromUserWatchList = RecommendationReasonFromUserWatchlist
.Builder()
.build()
val userLikedOnPartner = RecommendationReasonUserLikedOnPartner
.Builder()
.setTitleName("Movie or TV Show Title")
.build()
val generic = RecommendationReasonGeneric.Builder().build()
Período de visualización
Si una entidad solo debe estar disponible por un tiempo limitado, establece una fecha de vencimiento personalizada. Sin un tiempo de vencimiento explícito, las entidades vencerán y se borrarán automáticamente después de 60 días. Por lo tanto, establece una fecha de vencimiento solo cuando las entidades deban vencer antes. Especifica varios períodos de disponibilidad de este tipo.
val window1 = DisplayTimeWindow
.Builder()
.setStartTimeStampMillis(now()+ 1.days.toMillis())
.setEndTimeStampMillis(now()+ 30.days.toMillis())
val window2 = DisplayTimeWindow
.Builder()
.setEndTimeStampMillis(now()+ 30.days.toMillis())
val availabilityTimeWindows: List<DisplayTimeWindow> = listof(window1,window2)
DataFeedElementId
Si integraste tu catálogo de medios o tu feed de acciones de medios con Google TV, no es necesario que crees entidades separadas para películas o programas de TV. En cambio, puedes crear un objeto MediaActionFeedEntity que incluya el campo obligatorio DataFeedElementId. Este ID debe ser único y coincidir con el ID del feed de acciones multimedia, ya que ayuda a identificar el contenido del feed que se ingirió y a realizar búsquedas de contenido multimedia.
val id = "dataFeedElementId"
MovieEntity
A continuación, se muestra un ejemplo de cómo crear un objeto MovieEntity con todos los campos obligatorios:
val movieEntity = MovieEntity.Builder()
.setName("Movie name")
.setDescription("A sentence describing movie.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
// Suppose the duration is 2 hours, it is 72000000 in milliseconds
.setDurationMills(72000000)
.build()
Puedes proporcionar datos adicionales, como géneros, calificaciones de contenido, fecha de lanzamiento, motivo de recomendación y períodos de disponibilidad, que Google TV puede usar para mejorar las pantallas o filtrar contenido.
val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("pg-13").build();
val contentRatings = Arrays.asList(rating1);
//Suppose release date is 11-02-2025
val releaseDate = 1739233800000L
val movieEntity = MovieEntity.Builder()
...
.addGenres(genres)
.setReleaseDateEpochMillis(releaseDate)
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addAllAvailabilityTimeWindows(availabilityTimeWindows)
.build()
TvShowEntity
A continuación, se muestra un ejemplo de cómo crear un objeto TvShowEntity con todos los campos obligatorios:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.build();
De forma opcional, proporciona datos adicionales, como géneros, calificaciones de contenido, motivo de la recomendación, precio de la oferta, cantidad de temporadas o período de disponibilidad, que Google TV puede usar para mejorar las pantallas o filtrar contenido.
val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build();
val price = Price.Builder()
.setCurrentPrice("$14.99")
.setStrikethroughPrice("$16.99")
.build();
val contentRatings = Arrays.asList(rating1);
val seasonCount = 5;
val tvShowEntity = TvShowEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addAllAvailabilityTimeWindows(availabilityTimeWindows)
.setSeasonCount(seasonCount)
.setPrice(price)
.build()
MediaActionFeedEntity
Este es un ejemplo de cómo crear un objeto MediaActionFeedEntity con todos los campos obligatorios:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.build()
De manera opcional, proporciona datos adicionales, como la descripción, el motivo de la recomendación y el período de visualización, que Google TV puede usar para mejorar la visualización o filtrar contenido.
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setName("Movie name or TV Show name")
.setDescription("A sentence describing an entity")
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addPosterImages(images)
.build()
LiveTvChannelEntity
Representa un canal de TV en vivo. A continuación, se muestra un ejemplo de cómo crear un objeto LiveTvChannelEntity con todos los campos obligatorios:
val liveTvChannelEntity = LiveTvChannelEntity.Builder()
.setName("Channel Name")
// ID of the live TV channel
.setEntityId("https://www.example.com/channel/12345")
.setDescription("A sentence describing this live TV channel.")
// channel playback uri must contain at least PlatformType.TYPE_ANDROID_TV
.addPlatformSpecificPlaybackUri(channelPlaybackUris)
.addLogoImage(logoImage)
.build()
De forma opcional, proporciona datos adicionales, como clasificaciones de contenido o motivos de recomendación.
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build()
val contentRatings = Arrays.asList(rating1)
val liveTvChannelEntity = LiveTvChannelEntity.Builder()
...
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner)
.build()
LiveTvProgramEntity
Representa una tarjeta de programa de TV en vivo que se emite o está programada para emitirse en un canal de TV en vivo. A continuación, se muestra un ejemplo de cómo crear un objeto LiveTvProgramEntity con todos los campos obligatorios:
val liveTvProgramEntity = LiveTvProgramEntity.Builder()
// First set the channel information
.setChannelName("Channel Name")
.setChannelId("https://www.example.com/channel/12345")
// channel playback uri must contain at least PlatformType.TYPE_ANDROID_TV
.addPlatformSpecificPlaybackUri(channelPlaybackUris)
.setChannelLogoImage(channelLogoImage)
// Then set the program or card specific information.
.setName("Program Name")
.setEntityId("https://www.example.com/schedule/123")
.setDescription("Program Description")
.addAvailabilityTimeWindow(
DisplayTimeWindow.Builder()
.setStartTimestampMillis(1756713600000L)// 2025-09-01T07:30:00+0000
.setEndTimestampMillis(1756715400000L))// 2025-09-01T08:00:00+0000
.addPosterImage(programImage)
.build()
De manera opcional, proporciona datos adicionales, como calificaciones de contenido, géneros o motivos de recomendación.
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build()
val contentRatings = Arrays.asList(rating1)
val genres = Arrays.asList("Action", "Science fiction")
val liveTvProgramEntity = LiveTvProgramEntity.Builder()
...
.addContentRatings(contentRatings)
.addGenres(genres)
.setRecommendationReason(topOnPartner)
.build()