Este guia contém instruções para que os desenvolvedores integrem o conteúdo de vídeo recomendado usando o SDK Engage para preencher as experiências de recomendação nas 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 desenvolvedor pode transmitir no máximo 25 entidades em cada cluster de recomendação, e pode haver no máximo 7 clusters de recomendação por solicitação.
Pré-trabalho
Conclua as instruções de pré-trabalho no guia para iniciantes.
- Execute a publicação em um serviço em primeiro plano.
- Publique dados de recomendação no máximo uma vez por dia, acionados por um dos seguintes eventos:
- Primeiro login do usuário no dia. (ou)
- Quando o usuário começa a interagir com o aplicativo.
Integração
O AppEngagePublishClient publica o cluster de recomendação. Use o método publishRecommendationClusters para publicar um objeto de recomendações.
Inicialize o cliente e verifique a disponibilidade do serviço conforme descrito no guia para iniciantes.
client.publishRecommendationClusters(recommendationRequest)
Inserir clusters de recomendaçã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 e inserir todos os clusters.
O RecommendationClusterType determina como o
cluster será exibido.
// 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()
Quando o serviço recebe a solicitação, as seguintes ações ocorrem em uma transação:
- Os dados
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
O flag SyncAcrossDevices controla se os dados do cluster de recomendações de um usuário são compartilhados com o Google TV e disponibilizados em dispositivos como TVs, smartphones e tablets. Para que a recomendação funcione, ela precisa ser definida como "true".
Conseguir consentimento
O aplicativo de mídia precisa fornecer uma configuração clara para ativar ou desativar a sincronização entre dispositivos. Explique os benefícios ao usuário e armazene a preferência dele uma vez e aplique-a na solicitação publishRecommendations de acordo. 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 de armazenamento padrã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 para o perfil da conta ou para a conta inteira.
A DeleteReason enumeração 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ção:
Fornecer descrições
Forneça uma breve descrição para cada entidade. Essa descrição será exibida quando os usuários passarem o cursor sobre a entidade, fornecendo mais detalhes.
Texto de call-to-action
Forneça um texto de call-to-action opcional para cada entidade. Esse texto será mostrado ao usuário para incentivar o engajamento.
Tags
Opcionalmente, forneça uma lista de tags para cada entidade. As tags podem ser usadas para categorização e filtragem.
URIs de reprodução específicos 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 respectiva plataforma.
No caso raro em que os URIs de reprodução são idênticos para todas as plataformas, repita-os para cada plataforma.
// 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 as imagens mantêm uma proporção de 16:9 e uma altura mínima de 200 pixels para a exibição correta da entidade "Recomendações", especialmente no Entertainment Space do Google. As imagens com altura inferior a 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
Opcionalmente, forneça um motivo de recomendação que pode ser usado pelo Google TV para criar motivos para sugerir um filme ou programa de TV específico 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()
Janela de tempo 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 vão expirar e serão apagadas automaticamente após 60 dias. Portanto, defina um prazo de validade apenas quando as entidades precisarem expirar mais cedo. Especifique várias janelas 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ê tiver integrado seu catálogo de mídia ou feed de ações de mídia ao Google TV,
não será necessário criar entidades separadas para filmes ou programas de TV. Em vez disso, você pode
criar uma MediaActionFeedEntity 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 a realizar pesquisas de conteúdo de mídia.
val id = "dataFeedElementId"
MovieEntity
Confira um exemplo de como criar uma 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)
.setCallToActionText("Watch Now")
.addTag("Action")
.build()
Você pode fornecer dados adicionais, como gêneros, classificações de conteúdo, data de lançamento, motivo da recomendação e janelas de tempo de disponibilidade, que podem ser usados pelo Google TV para exibições aprimoradas ou 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 uma TvShowEntity com todos os campos obrigatórios:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.setCallToActionText("Watch Now")
.addTag("Drama")
.build();
Opcionalmente, forneça dados adicionais, como gêneros, classificações de conteúdo, motivo da recomendação, preço da oferta, contagem de temporadas ou janela de tempo de disponibilidade, que podem ser usados pelo Google TV para exibições aprimoradas ou 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 uma MediaActionFeedEntity com todos os campos obrigatórios:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.setCallToActionText("Watch Now")
.addTag("Action")
.build()
Opcionalmente, forneça dados adicionais, como descrição, motivo da recomendação e janela de tempo de exibição, que podem ser usados pelo Google TV para exibições aprimoradas ou 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
Isso representa um canal de TV ao vivo. Confira um exemplo de como criar uma 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)
.setCallToActionText("Watch Now")
.addTag("News")
.build()
Opcionalmente, forneça dados adicionais, 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
Isso representa um card de programa de TV ao vivo que está sendo transmitido ou programado para ser transmitido em um canal de TV ao vivo. Confira um exemplo de como criar uma LiveTvProgramEntity com todos os campos obrigatórios:
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)
.setCallToActionText("Watch Now")
.addTag("Sports")
.build()
Opcionalmente, forneça dados adicionais, 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()