Este guia contém instruções para que os desenvolvedores integrem o conteúdo de vídeo recomendado usando o SDK Engage para preencher experiências de recomendações em plataformas do Google, como TV, dispositivos móveis e tablets.
A recomendação usa o cluster de recomendação para mostrar filmes e programas de TV de vários apps em um único grupo de interfaces. Cada parceiro de desenvolvimento pode transmitir no máximo 25 entidades em cada cluster de recomendações, e pode haver no máximo 7 clusters de recomendações por solicitação.
Pré-trabalho
Antes de começar, siga estas etapas. 1. Verifique se o app é direcionado à API de nível 19 ou mais recente para essa integração.
Adicione a biblioteca
com.google.android.engageao app.Há SDKs separados para usar na integração: um para apps para dispositivos móveis e outro para apps de TV.
Para dispositivos móveis
dependencies { implementation 'com.google.android.engage:engage-core:1.5.9 }para TV
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.5 }Defina o ambiente de serviço do Engage como produção no arquivo
AndroidManifest.xml.Para APKs de dispositivos móveis
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>Para APK de TV
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>Executar a publicação em um serviço em primeiro plano.
Publicar dados de recomendações no máximo uma vez por dia, acionados por qualquer uma das seguintes opções:
- O primeiro login do usuário no dia. (ou)
- Quando o usuário começa a interagir com o aplicativo.
Integração
AppEngagePublishClient publica o cluster de recomendações. Use o método publishRecommendationClusters para publicar um objeto de
recomendações.
Use isServiceAvailable()2 para verificar se o serviço está disponível para
integração.
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.
}
}
Clusters de recomendação e uma solicitação de publicação
Os clusters são agrupamentos lógicos das entidades. Os exemplos de código a seguir explicam como criar os clusters com base na sua preferência e como criar uma solicitação de publicação para todos eles.
// 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()
Criar um perfil de conta
Para permitir uma experiência personalizada no Google TV, forneça informações da conta e do perfil. Use o AccountProfile para fornecer:
- ID da conta: um identificador exclusivo que representa a conta do usuário no aplicativo. Pode ser o ID da conta real ou uma versão adequadamente ofuscada.
- ID do perfil (opcional): se o aplicativo for compatível com vários perfis em uma única conta, forneça um identificador exclusivo para o perfil de usuário específico.
- Localidade(opcional): você pode fornecer o idioma preferido do usuário.
Esse campo é útil se você enviar
MediaActionFeedEntitynoRecommendationRequest.
// 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();
Quando o serviço recebe a solicitação, as ações abaixo ocorrem em uma transação:
- Os dados do
RecommendationsClusterdo parceiro do desenvolvedor são removidos. - Os dados da solicitação são analisados e armazenados no
RecommendationsClusteratualizado. Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
Sincronização entre dispositivos
A flag SyncAcrossDevices controla se os dados de um cluster de recomendações do usuário
são compartilhados com o Google TV e estão disponíveis em dispositivos como TV, smartphone
e tablets. Para que a recomendação funcione, ela precisa ser definida como "true".
Obter consentimento
O aplicativo de mídia precisa oferecer uma configuração clara para ativar ou desativar
a sincronização entre dispositivos. Explique os benefícios para o usuário, armazene a preferência dele uma vez e aplique-a na solicitação publishRecommendations. Para
aproveitar ao máximo o recurso entre dispositivos, verifique se o app recebe o consentimento do usuário
e ativa SyncAcrossDevices para true.
Excluir os dados de descoberta de vídeo
Para excluir manualmente os dados de um usuário do servidor do Google TV antes do período padrão de retenção de 60 dias, use o método client.deleteClusters(). Ao receber a solicitação, o serviço exclui todos os dados de descoberta de vídeo existentes do perfil da conta ou da conta inteira.
O enum DeleteReason define o motivo da exclusão de dados.
O código a seguir remove as recomendações ao fazer logout.
// 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()
)
Criar entidades
O SDK definiu entidades diferentes para representar cada tipo de item. As seguintes entidades são compatíveis com o cluster de recomendações:
MediaActionFeedEntityMovieEntityTvShowEntityLiveTvChannelEntityLiveTvProgramEntity
Descrição
Forneça uma breve descrição para cada entidade. Ela será exibida quando os usuários passarem o cursor sobre a entidade, fornecendo mais detalhes.
URIs de reprodução específicas da plataforma
Crie URIs de reprodução para cada plataforma compatível: Android TV, Android ou iOS. Isso permite que o sistema selecione o URI adequado para a reprodução de vídeo na plataforma respectiva.
No raro caso em que os URIs de reprodução são idênticos para todas as plataformas, repita-os para cada uma delas.
// 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()
Poster images
As imagens de pôster exigem um URI e dimensões de pixel (altura e largura). Para segmentar diferentes formatos, forneça várias imagens de pôster, mas verifique se todas mantêm uma proporção de 16:9 e uma altura mínima de 200 pixels para exibição correta da entidade "Recomendações", principalmente no Espaço de entretenimento do Google. Imagens com altura menor que 200 pixels podem não ser mostradas.
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 da recomendação
Se quiser, forneça um motivo para a recomendação, que pode ser usado pelo Google TV para explicar por que um filme ou programa de TV específico foi sugerido ao usuário.
//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 exibição
Se uma entidade só estiver disponível por um período limitado, defina um prazo de validade personalizado. Sem um prazo de validade explícito, as entidades expiram e são apagadas automaticamente após 60 dias. Portanto, defina um prazo de validade apenas quando as entidades precisarem expirar antes. Especifique vários períodos de disponibilidade.
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
Se você integrou seu catálogo de mídia ou feed de ações de mídia ao Google TV, não é necessário criar entidades separadas para filmes ou programas de TV. Em vez disso, crie uma entidade MediaActionFeed que inclua o campo obrigatório DataFeedElementId. Esse ID precisa ser exclusivo e corresponder ao ID no feed de ações de mídia, já que ajuda a identificar o conteúdo do feed ingerido e realizar pesquisas de conteúdo de mídia.
val id = "dataFeedEleemntId"
MovieEntity
Confira um exemplo de como criar um MovieEntity com todos os campos obrigatórios:
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()
Você pode fornecer outros dados, como gêneros, classificação de conteúdo, data de lançamento, motivo da recomendação e períodos de disponibilidade, que podem ser usados pelo Google TV para melhorar as exibições ou para fins de filtragem.
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
Confira um exemplo de como criar um TvShowEntity com todos os campos obrigatórios:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.build();
Se quiser, forneça outros dados, como gêneros, classificação de conteúdo, motivo da recomendação, preço da oferta, número de temporadas ou período de disponibilidade, que podem ser usados pelo Google TV para melhorar as exibições ou para fins de filtragem.
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
Confira um exemplo de como criar um MediaActionFeedEntity com todos os campos
obrigatórios:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.build()
Se quiser, forneça outros dados, como descrição, motivo da recomendação e período de exibição, que podem ser usados pelo Google TV para melhorar as exibições ou para fins de filtragem.
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 um canal de TV ao vivo. Confira um exemplo de como criar um
LiveTvChannelEntity com todos os campos obrigatórios:
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()
Se quiser, forneça outros dados, como classificações de conteúdo ou motivo da recomendação.
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 um card de programa de TV ao vivo que está sendo exibido ou tem exibição programada em um canal de TV ao vivo. Confira um exemplo de como criar um LiveTvProgramEntity
com todos os campos obrigatórios:
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()
Se quiser, forneça outros dados, como classificações de conteúdo, gêneros ou motivo da recomendação.
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()
Ao implementar essas etapas, os desenvolvedores podem integrar recomendações de conteúdo de vídeo ao Google TV, aumentando a descoberta e o engajamento dos usuários e oferecendo uma experiência de visualização consistente e personalizada em todos os dispositivos.