Questa guida contiene le istruzioni per gli sviluppatori per integrare i contenuti video consigliati utilizzando l'SDK Engage per popolare le esperienze di consigli sulle piattaforme Google, come TV, dispositivi mobili e tablet.
I consigli utilizzano il cluster di consigli per mostrare film e programmi TV da più app in un unico raggruppamento dell'interfaccia utente. Ogni partner sviluppatore può trasmettere un massimo di 25 entità in ogni cluster di consigli e può esserci un massimo di 7 cluster di consigli per richiesta.
Preparazione
Segui le istruzioni di preparazione nella guida introduttiva.
- Esegui la pubblicazione su un servizio in primo piano.
- Pubblica i dati dei consigli al massimo una volta al giorno, attivati da uno dei seguenti eventi:
- Il primo accesso dell'utente della giornata. (oppure)
- Quando l'utente inizia a interagire con l'applicazione.
Integrazione
AppEngagePublishClient pubblica il cluster di consigli. Utilizza il metodo publishRecommendationClusters per pubblicare un oggetto di consigli.
Assicurati di inizializzare il client e verificare la disponibilità del servizio come descritto nella guida introduttiva.
client.publishRecommendationClusters(recommendationRequest)
Eseguire l'upsert dei cluster di consigli
I cluster sono raggruppamenti logici delle entità. Gli esempi di codice riportati di seguito spiegano come creare i cluster in base alle tue preferenze e come creare una richiesta di pubblicazione ed eseguire l'upsert di tutti i cluster.
Il RecommendationClusterType determina la modalità di visualizzazione del
cluster.
// 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 il servizio riceve la richiesta, le seguenti azioni vengono eseguite in una transazione:
- I dati
RecommendationsClusteresistenti del partner sviluppatore vengono rimossi. - I dati della richiesta vengono analizzati e archiviati in
RecommendationsClusteraggiornato. In caso di errore, l'intera richiesta viene rifiutata e lo stato esistente viene mantenuto.
Sincronizzazione cross-device
Il flag SyncAcrossDevices controlla se i dati del cluster di consigli di un utente vengono condivisi con Google TV e sono disponibili sui suoi dispositivi, come TV, smartphone e tablet. Affinché il consiglio funzioni, deve essere impostato su true.
Ottenere il consenso
L'applicazione multimediale deve fornire un'impostazione chiara per attivare o disattivare la sincronizzazione cross-device. Spiega i vantaggi all'utente, memorizza la sua preferenza una sola volta e applicala di conseguenza nella richiesta publishRecommendations. Per sfruttare al meglio la funzionalità cross-device, verifica che l'app ottenga il consenso dell'utente e che SyncAcrossDevices sia impostato su true.
Eliminare i dati di Video Discovery
Per eliminare manualmente i dati di un utente dal server di Google TV prima del periodo di conservazione standard di 60 giorni, utilizza il metodo client.deleteClusters(). Dopo aver ricevuto la richiesta, il servizio elimina tutti i dati di Video Discovery esistenti per il profilo dell'account o per l'intero account.
L'enum DeleteReason definisce il motivo dell'eliminazione dei dati.
Il seguente codice rimuove i consigli al momento del 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()
)
Creare entità
L'SDK ha definito diverse entità per rappresentare ogni tipo di articolo. Per il cluster di consigli sono supportate le seguenti entità:
Fornire descrizioni
Fornisci una breve descrizione per ogni entità. Questa descrizione verrà visualizzata quando gli utenti passano il mouse sopra l'entità, fornendo loro ulteriori dettagli.
Testo dell'invito all'azione
Fornisci un testo dell'invito all'azione facoltativo per ogni entità. Questo testo verrà mostrato all'utente per incoraggiarlo a interagire.
Tag
Se vuoi, puoi fornire un elenco di tag per ogni entità. I tag possono essere utilizzati per la categorizzazione e il filtraggio.
URI di riproduzione specifici della piattaforma
Crea URI di riproduzione per ogni piattaforma supportata: Android TV, Android o iOS. In questo modo, il sistema può selezionare l'URI appropriato per la riproduzione video sulla rispettiva piattaforma.
Nel raro caso in cui gli URI di riproduzione siano identici per tutte le piattaforme, ripetili per ogni piattaforma.
// 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()
Immagini poster
Le immagini poster richiedono un URI e dimensioni in pixel (altezza e larghezza). Rivolgiti a diversi fattori di forma fornendo più immagini poster, ma verifica che tutte le immagini mantengano le proporzioni 16:9 e un'altezza minima di 200 pixel per la corretta visualizzazione dell'entità "Consigli", in particolare all'interno di Entertainment Space di Google. Le immagini con un'altezza inferiore a 200 pixel potrebbero non essere mostrate.
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 del consiglio
Se vuoi, puoi fornire un motivo del consiglio che Google TV può utilizzare per spiegare all'utente perché suggerire un film o un programma TV specifico.
//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()
Finestra del tempo di visualizzazione
Se un'entità deve essere disponibile solo per un periodo di tempo limitato, imposta un tempo di scadenza personalizzato. Senza un tempo di scadenza esplicito, le entità scadranno e verranno eliminate automaticamente dopo 60 giorni. Imposta un tempo di scadenza solo quando le entità devono scadere prima. Specifica più finestre di disponibilità di questo 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
Se hai integrato il catalogo multimediale o il feed di azioni multimediali con Google TV,
non devi creare entità separate per film o programmi TV, ma puoi
creare un MediaActionFeedEntity che includa il
campo obbligatorio DataFeedElementId. Questo ID deve essere univoco e deve corrispondere all'ID nel feed di azioni multimediali, in quanto aiuta a identificare i contenuti del feed importati ed eseguire ricerche di contenuti multimediali.
val id = "dataFeedElementId"
MovieEntity
Ecco un esempio di creazione di una MovieEntity con tutti i campi obbligatori:
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()
Puoi fornire dati aggiuntivi come generi, valutazioni dei contenuti, data di uscita, motivo del consiglio e finestre temporali di disponibilità, che Google TV può utilizzare per migliorare la visualizzazione o per il filtraggio.
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
Ecco un esempio di creazione di una TvShowEntity con tutti i campi obbligatori:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.setCallToActionText("Watch Now")
.addTag("Drama")
.build();
Se vuoi, puoi fornire dati aggiuntivi come generi, valutazioni dei contenuti, motivo del consiglio, prezzo dell'offerta, numero di stagioni o finestra temporale di disponibilità, che Google TV può utilizzare per migliorare la visualizzazione o per il filtraggio.
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
Ecco un esempio di creazione di una MediaActionFeedEntity con tutti i campi obbligatori:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.setCallToActionText("Watch Now")
.addTag("Action")
.build()
Se vuoi, puoi fornire dati aggiuntivi come descrizione, motivo del consiglio e finestra temporale di visualizzazione, che Google TV può utilizzare per migliorare la visualizzazione o per il filtraggio.
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
Questa entità rappresenta un canale TV in diretta. Ecco un esempio di creazione di una LiveTvChannelEntity con tutti i campi obbligatori:
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()
Se vuoi, puoi fornire dati aggiuntivi come valutazioni dei contenuti o motivo del consiglio.
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
Questa entità rappresenta una scheda di un programma TV in diretta in onda o in programma su un canale TV in diretta. Ecco un esempio di creazione di una LiveTvProgramEntity con tutti i campi obbligatori:
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()
Se vuoi, puoi fornire dati aggiuntivi come valutazioni dei contenuti, generi o motivo del consiglio.
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()