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 TV, dispositivos móviles y tablets.
Recommendation 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 Recommendation y puede haber un máximo de 7 clústeres de Recommendation por solicitud.
Trabajo previo
Antes de comenzar, completa los siguientes pasos. 1. Para esta integración, verifica que tu app esté orientada al nivel de API 19 o superior.
Agrega la biblioteca
com.google.android.engage
a tu app.Existen SDKs independientes para usar en la integración: uno para apps para dispositivos móviles y otro para apps para TV.
Para dispositivos móviles
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
para TV
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
Establece el entorno de servicio de Engage en producción en el archivo
AndroidManifest.xml
.Para el APK para dispositivos móviles
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Para el APK de TV
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Ejecuta la publicación en un servicio en primer plano.
Publica los datos de Recomendaciones una vez al día como máximo, activados por cualquiera de las siguientes opciones:
- Primer acceso del día del usuario. (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.
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 Recommendation 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 tu preferencia y cómo crear una solicitud de publicación para todos los clústeres.
// cluster for popular movies
val recommendationCluster1 = RecommendationCluster
.Builder()
.addEntity(movie)
.addEntity(tvShow)
.setTitle("Popular Movies")
.build()
// cluster for top searches
val recommendationCluster2 = RecommendationCluster
.Builder()
.addEntity(movie)
.addEntity(tvShow)
.setTitle("Top Searches")
.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 del perfil. Usa AccountProfile
para proporcionar lo siguiente:
- ID de la cuenta: Es un identificador único que representa la cuenta del usuario dentro de tu aplicación. Puede ser el ID de la cuenta real o una versión ofuscada de forma adecuada.
- ID de perfil (opcional): Si tu aplicación admite varios perfiles dentro de una sola cuenta, proporciona un identificador único para el perfil de usuario específico.
- Configuración regional(opcional): De manera opcional, puedes proporcionar el idioma preferido del usuario.
Este campo es útil si envías
MediaActionFeedEntity
en elRecommendationRequest
.
// 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 del clúster de recomendaciones de un usuario se comparten con Google TV y están disponibles en todos sus dispositivos, como TVs, teléfonos y tablets. Para que la recomendación funcione, se debe establecer como verdadero.
Cómo obtener el consentimiento
La aplicación de música debe proporcionar una configuración clara para habilitar o inhabilitar la sincronización entre dispositivos. Explica los beneficios al usuario y almacena su preferencia una vez y aplícala 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
a 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 de descubrimiento de videos existentes 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 al salir.
// 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 Recommendation:
MediaActionFeedEntity
MovieEntity
TvShowEntity
Descripción
Proporciona una breve descripción para cada entidad. Esta descripción se mostrará cuando los usuarios coloquen el cursor sobre la entidad y 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 correspondiente.
En el caso poco frecuente en el que los URIs de reproducción sean idénticos para todas las plataformas, repite el proceso 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 de píxeles (altura y ancho). Proporciona varias imágenes de póster para segmentar anuncios para diferentes factores de forma, pero verifica que todas las imágenes tengan una relación de aspecto de 16:9 y una altura mínima de 200 píxeles para que se muestre correctamente la entidad "Recommendations", especialmente en el Entertainment Space 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 pueda usar para crear motivos por los que sugerir 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 un tiempo de vencimiento personalizado. Sin un tiempo de vencimiento explícito, las entidades vencerán automáticamente y se borrarán después de 60 días. Por lo tanto, establece una fecha de vencimiento solo cuando las entidades deban vencer antes. Especifica varias de estas ventanas de disponibilidad.
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 feed de acciones de medios con Google TV, no es necesario que crees entidades independientes para películas o programas de TV. En su lugar, puedes crear una entidad MediaActionFeed que incluya el campo obligatorio DataFeedElementId. Este ID debe ser único y debe coincidir con el ID del feed de acciones multimedia, ya que ayuda a identificar el contenido del feed transferido y a realizar búsquedas de contenido multimedia.
val id = "dataFeedEleemntId"
MovieEntity
El siguiente es un ejemplo de cómo crear un 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, clasificaciones de contenido, fecha de lanzamiento, motivo de la 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
El siguiente es un ejemplo de cómo crear un 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 del contenido, razón de la recomendación, precio de la oferta, recuento 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 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 las pantallas 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()
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.