SDK de Engage para recomendaciones de videos

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

Antes de comenzar, completa los siguientes pasos. 1. Verifica que tu app esté orientada al nivel de API 19 o superior para esta integración.

  1. Agrega la biblioteca com.google.android.engage a tu app.

    Existen SDKs separados para usar en la integración: uno para apps para dispositivos móviles y otro para apps para TVs.

    Para dispositivos móviles

    
      dependencies {
        implementation 'com.google.android.engage:engage-core:1.5.9
      }
    

    para TV

    
      dependencies {
        implementation 'com.google.android.engage:engage-tv:1.0.5
      }
    
  2. Establece el entorno del servicio de Engage como producción en el archivo AndroidManifest.xml.

    Para APK de dispositivos móviles

    
    <meta-data
          android:name="com.google.android.engage.service.ENV"
          android:value="PRODUCTION">
    </meta-data>
    

    APK para TV

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. Ejecutar la publicación en un servicio en primer plano

  4. Los datos de las recomendaciones de publicación se deben actualizar como máximo una vez al día, ya sea por uno de los siguientes activadores:

    1. Es el primer acceso del usuario en el día. (o)
    2. Es el momento en que el usuario comienza a interactuar con la aplicación.

Integración

AppEngagePublishClient publica el clúster de recomendaciones. Usa el método publishRecommendationClusters para publicar un objeto de recomendaciones.

Usa isServiceAvailable()2 para verificar si el servicio está disponible para la integración.

val client = AppEngagePublishClient(context)

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.
      client.publishRecommendationClusters(recommendationRequest)
    } else {
      // Service is not available
    }
  } else {
    // The IPC call itself fails, proceed with error handling logic here,
    // such as retry.
  }
}

Clústeres de recomendaciones y una solicitud de publicación

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 para todos los clústeres.

// 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()

Crea un perfil de cuenta

Para permitir una experiencia personalizada en Google TV, proporciona información de la cuenta y el perfil. Usa AccountProfile para proporcionar lo siguiente:

  1. ID de la cuenta: Es un identificador único que representa la cuenta del usuario en tu aplicación. Puede ser el ID de la cuenta real o una versión ofuscada adecuada.
  2. ID de perfil (opcional): Si tu aplicación admite varios perfiles en una sola cuenta, proporciona un identificador único para el perfil de usuario específico.
  3. Configuración regional(opcional): De manera opcional, puedes proporcionar el idioma preferido del usuario. Este campo es útil si envías MediaActionFeedEntity en RecommendationRequest.
// If app only supports account
val accountProfile = AccountProfile.Builder()
  .setAccountId("account_id")
  .build();

// If app supports both account and profile
val accountProfile = AccountProfile.Builder()
  .setAccountId("account_id")
  .setProfileId("profile_id")
  .build();

// set Locale
val accountProfile = AccountProfile.Builder()
  .setAccountId("account_id")
  .setProfileId("profile_id")
  .setLocale("en-US")
  .build();

Cuando el servicio recibe la solicitud, se realizan las siguientes acciones en una transacción:

  • Se quitan los datos existentes de RecommendationsCluster del socio desarrollador.
  • Los datos de la solicitud se analizan y se almacenan en el RecommendationsCluster actualizado. 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.

La aplicación 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:

  1. MediaActionFeedEntity
  2. MovieEntity
  3. TvShowEntity
  4. LiveTvChannelEntity
  5. LiveTvProgramEntity

Descripción

Proporciona una breve descripción para 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ícula o Programa de TV. En cambio, puedes crear una entidad MediaActionFeed 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 = "dataFeedEleemntId"

MovieEntity

Este es 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

Este es 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 manera 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")
  .setChanelId("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 Desccription")
  .addAvailabilityTimeWindow(
      DisplayTimeWindow.Builder()
        .setStartTimestampMillis(1756713600000L)// 2025-09-01T07:30:00+0000
        .setEndTimestampMillis(1756715400000L))// 2025-09-01T08:00:00+0000
  .addPosterImage(programImage)
  .build()

De forma 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()

Si implementan estos pasos, los desarrolladores pueden integrar correctamente las recomendaciones de contenido de video en Google TV, lo que aumenta el descubrimiento y la participación de los usuarios, y proporciona una experiencia de visualización coherente y personalizada para los usuarios en todos sus dispositivos.