Guida all'integrazione dell'SDK Engage per la TV

La sezione Continua a guardare sfrutta il cluster di continuazione per mostrare i video non completati e le puntate successive da guardare della stessa stagione TV da più app in un unico raggruppamento dell'interfaccia utente. Puoi mettere in evidenza le sue entità in questo cluster di continuazione. Segui questa guida per scoprire come migliorare il coinvolgimento degli utenti tramite l'esperienza Continua a guardare utilizzando l'SDK Engage.

Passaggio 1: operazioni preliminari

Prima di iniziare, completa i seguenti passaggi:

Assicurati che l'app abbia come target il livello API 19 o versioni successive per questa integrazione

  1. Aggiungi la raccolta com.google.android.engage alla tua app:

    Nell'integrazione sono disponibili SDK separati: uno per le app mobile e uno per le app per TV.

    Dispositivo mobile

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

    TV

    
      dependencies {
        implementation 'com.google.android.engage:engage-tv:1.0.2
      }
    
  2. Imposta l'ambiente di servizio Engage su produzione nel file AndroidManifest.xml.

    Dispositivo mobile

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

    TV

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. Aggiungere l'autorizzazione per WRITE_EPG_DATA per l'APK per TV

      <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
    
  4. Assicurati una pubblicazione affidabile dei contenuti utilizzando un servizio in background, come androidx.work, per la pianificazione.

  5. Per offrire un'esperienza di visualizzazione senza interruzioni, pubblica i dati sulla visualizzazione continua quando si verificano questi eventi:

    1. Primo accesso: quando un utente accede per la prima volta, la pubblicazione dei suoi dati garantisce che la cronologia delle visualizzazioni sia immediatamente disponibile.
    2. Creazione o cambio di profilo (app con più profili): se la tua app supporta più profili, pubblica i dati quando un utente crea o cambia profilo. In questo modo, ogni utente ha un'esperienza personalizzata.
    3. Interruzione della riproduzione video: per aiutare gli utenti a riprendere da dove avevano interrotto, vengono pubblicati i dati quando mettono in pausa o interrompono un video o quando l'app esce durante la riproduzione.
    4. Aggiornamenti della sezione Continua a guardare (se supportata): quando un utente rimuove un elemento dalla sezione Continua a guardare, la modifica viene applicata pubblicando i dati aggiornati. In questo modo, la sezione rimane pertinente e personalizzata.
    5. Completamento video:
      1. Per i film, rimuovi il film completato dal riquadro Continua a guardare. Se il film fa parte di una serie, aggiungi il film successivo per mantenere attivo il coinvolgimento dell'utente.
      2. Per le puntate, rimuovi la puntata completata e aggiungi la puntata successiva della serie, se disponibile, per incoraggiare la visualizzazione continua.

Integrazione

AccountProfile

Per consentire un'esperienza personalizzata di "Continua a guardare" su Google TV, fornisci informazioni sull'account e sul profilo. Utilizza AccountProfile per fornire:

  1. ID account: un identificatore univoco che rappresenta l'account dell'utente all'interno della tua applicazione. Può trattarsi dell'ID account effettivo o di una versione adeguatamente offuscata.

  2. (Facoltativo) ID profilo: se la tua applicazione supporta più profili all'interno di un singolo account, fornisci un identificatore univoco per il profilo utente specifico (di nuovo, reale o offuscato).

// If your app only supports account
val accountProfile = AccountProfile.Builder()
      .setAccountId("your_users_account_id")
      .build()
// If your app supports both account and profile
val accountProfile = AccountProfile.Builder()
      .setAccountId("your_users_account_id")
      .setProfileId("your_users_profile_id")
.build()

Crea entità

L'SDK ha definito entità diverse per rappresentare ogni tipo di elemento. Il cluster di interruzioni supporta le seguenti entità:

  1. MovieEntity
  2. TvEpisodeEntity
  3. LiveStreamingVideoEntity
  4. VideoClipEntity

Specifica gli URI e le immagini poster specifici della piattaforma per queste entità.

Se non l'hai ancora fatto, crea anche gli URI di riproduzione per ogni piattaforma, ad esempio Android TV, Android o iOS. Pertanto, quando un utente continua a guardare su ogni piattaforma, l'app utilizza un URI di riproduzione mirato per riprodurre i contenuti video.

// Required. Set this when you want continue watching 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()

// Required. Set this when you want continue watching entities to show up on
// Google TV Android app, Entertainment Space, Playstore Widget
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 continue watching 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)

Le immagini dei poster richiedono un URI e le dimensioni in pixel (altezza e larghezza). Scegli come target diversi fattori di forma fornendo più immagini poster, ma assicurati che tutte le immagini mantengano un formato 16:9 e un'altezza minima di 200 pixel per la visualizzazione corretta dell'entità "Continua a guardare", in particolare all'interno di Entertainment Space di Google. Le immagini con un'altezza inferiore a 200 pixel potrebbero non essere visualizzate.


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)
MovieEntity

Questo esempio mostra come creare un MovieEntity con tutti i campi obbligatori:

val movieEntity = MovieEntity.Builder()
   .setWatchNextType(WatchNextType.TYPE_CONTINUE)
   .setName("Movie name")
   .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
   .addPosterImages(images)
   // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
   .setLastEngagementTimeMillis(1701388800000)
   // Suppose the duration is 2 hours, it is 72000000 in milliseconds
   .setDurationMills(72000000)
   // Suppose last playback offset is 1 hour, 36000000 in milliseconds
   .setLastPlayBackPositionTimeMillis(36000000)
   .build()

Fornendo dettagli come generi e valutazioni dei contenuti, Google TV può mostrare i tuoi contenuti in modi più dinamici e metterli in contatto con gli spettatori giusti.

val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build();
val contentRatings = Arrays.asList(rating1);
val movieEntity = MovieEntity.Builder()
    ...
    .addGenres(genres)
    .addContentRatings(contentRatings)
    .build()

Le entità rimangono disponibili automaticamente per 60 giorni, a meno che non specifichi un valore di scadenza più breve. Imposta una scadenza personalizzata solo se devi rimuovere l'entità prima di questo periodo predefinito.

// Set the expiration time to be now plus 30 days in milliseconds
val expirationTime = new DisplayTimeWindow.Builder()
             .setEndTimestampMillis(now().toMillis()+2592000000).build()
val movieEntity = MovieEntity.Builder()
    ...
    .addAvailabilityTimeWindow(expirationTime)
    .build()
TvEpisodeEntity

Questo esempio mostra come creare un TvEpisodeEntity con tutti i campi obbligatori:

val tvEpisodeEntity = TvEpisodeEntity.Builder()
    .setWatchNextType(WatchNextType.TYPE_CONTINUE)
    .setName("Episode name")
    .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
    .addPosterImages(images)
    // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
    .setLastEngagementTimeMillis(1701388800000)
    .setDurationMills(72000000) // 2 hours in milliseconds
    // 45 minutes and 15 seconds in milliseconds is 2715000
    .setLastPlayBackPositionTimeMillis(2715000)
    .setEpisodeNumber("2")
    .setSeasonNumber("1")
    .setShowTitle("Title of the show")
    .build();

La stringa del numero di puntata (ad es. "2") e la stringa del numero di stagione (ad es. "1") verranno espanse nella forma corretta prima di essere visualizzate nella scheda Continua la visione. Tieni presente che devono essere stringhe numeriche, quindi non inserire "e2", o "puntata 2", o "s1" o "stagione 1".

Se un determinato programma TV ha una sola stagione, imposta il numero di stagione su 1.

Per massimizzare le probabilità che gli spettatori trovino i tuoi contenuti su Google TV, ti consigliamo di fornire dati aggiuntivi, come generi, valutazioni dei contenuti e finestre di disponibilità, in quanto questi dettagli possono migliorare le visualizzazioni e le opzioni di filtro.

val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val tvEpisodeEntity = TvEpisodeEntity.Builder()
    ...
    .addGenres(genres)
    .addContentRatings(contentRatings)
    .setSeasonTitle("Season Title")
    .setShowTitle("Show Title)
    .build();
VideoClipEntity

Ecco un esempio di creazione di un VideoClipEntity con tutti i campi obbligatori.

VideoClipEntity indica un clip generato dagli utenti, ad esempio un video di YouTube.

val videoClipEntity = VideoClipEntity.Builder()
    .setPlaybackUri(Uri.parse("https://www.example.com/uri_for_current_platform")
    .setWatchNextType(WatchNextType.TYPE_CONTINUE)
    .setName("Video clip name")
    .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
    .addPosterImages(images)
    // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
    .setLastEngagementTimeMillis(1701388800000)
    .setDurationMills(600000) //10 minutes in milliseconds
    .setLastPlayBackPositionTimeMillis(300000) //5 minutes in milliseconds
    .addContentRating(contentRating)
    .build();

Se vuoi, puoi impostare il creator, l'immagine del creator, la data e l'ora di creazione in millisecondi o la finestra temporale di disponibilità .

LiveStreamingVideoEntity

Ecco un esempio di creazione di un LiveStreamingVideoEntity con tutti i campi obbligatori.

val liveStreamingVideoEntity = LiveStreamingVideoEntity.Builder()
    .setPlaybackUri(Uri.parse("https://www.example.com/uri_for_current_platform")
    .setWatchNextType(WatchNextType.TYPE_CONTINUE)
    .setName("Live streaming name")
    .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
    .addPosterImages(images)
    // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
    .setLastEngagementTimeMillis(1701388800000)
    .setDurationMills(72000000) //2 hours in milliseconds
    .setLastPlayBackPositionTimeMillis(36000000) //1 hour in milliseconds
    .addContentRating(contentRating)
    .build();

Se vuoi, puoi impostare l'ora di inizio, l'emittente, l'icona dell'emittente o la finestra temporale di disponibilità per l'entità del live streaming.

Per informazioni dettagliate su attributi e requisiti, consulta il riferimento all'API.

Fornisci i dati del cluster di continuazione

AppEngagePublishClient è responsabile della pubblicazione del cluster di continuazione. Utilizza il metodo publishContinuationCluster() per pubblicare un oggetto ContinuationCluster.

Innanzitutto, devi utilizzare isServiceAvailable() per verificare se il servizio è disponibile per l'integrazione.

client.publishContinuationCluster(
    PublishContinuationClusterRequest
        .Builder()
        .setContinuationCluster(
            ContinuationCluster
                .Builder()
                .setAccountProfile(accountProfile)
                .addEntity(movieEntity1)
                .addEntity(movieEntity2)
                .addEntity(tvEpisodeEntity1)
                .addEntity(tvEpisodeEntity2)
                .setSyncAcrossDevices(true)
                .build()
        )
        .build();
)

Quando il servizio riceve la richiesta, vengono eseguite le seguenti azioni all'interno di una transazione:

  • I dati ContinuationCluster esistenti del partner sviluppatore vengono rimossi.
  • I dati della richiesta vengono analizzati e archiviati nel ContinuationCluster aggiornato.

In caso di errore, l'intera richiesta viene rifiutata e lo stato esistente viene mantenuto.

Le API di pubblicazione sono API upsert; sostituiscono i contenuti esistenti. Se devi aggiornare un'entità specifica in ContinuationCluster, dovrai nuovamente pubblicare tutte le entità.

I dati di ContinuationCluster devono essere forniti solo per gli account di adulti. Pubblica solo quando AccountProfile appartiene a una persona adulta.

Sincronizzazione cross-device

Flag SyncAcrossDevices

Questo flag controlla se i dati di ContinuationCluster di un utente vengono sincronizzati tra i suoi dispositivi (TV, smartphone, tablet e così via). Il valore predefinito è false, il che significa che la sincronizzazione cross-device è disattivata per impostazione predefinita.

Valori:

  • true: i dati di ContinuationCluster vengono condivisi su tutti i dispositivi dell'utente per un'esperienza di visualizzazione senza interruzioni. Consigliamo vivamente questa opzione per la migliore esperienza cross-device.
  • false: i dati di ContinuationCluster sono limitati al dispositivo corrente.

L'applicazione multimediale deve fornire un'impostazione chiara per attivare/disattivare la sincronizzazione tra dispositivi. Spiega i vantaggi all'utente, memorizza la sua preferenza una volta e applicala di conseguenza in publishContinuationCluster.

// Example to allow cross device syncing.
client.publishContinuationCluster(
    PublishContinuationClusterRequest
        .Builder()
        .setContinuationCluster(
            ContinuationCluster
                .Builder()
                .setAccountProfile(accountProfile)
                .setSyncAcrossDevices(true)
                .build();
        )
        .build();
)

Per ottenere il massimo dalla nostra funzionalità cross-device, assicurati che la tua app ottenga il consenso dell'utente e imposta SyncAcrossDevices su true. In questo modo, i contenuti possono essere sincronizzati senza problemi su più dispositivi, migliorando l'esperienza utente e aumentando il coinvolgimento. Ad esempio, un partner che ha implementato questa funzionalità ha registrato un aumento del 40% dei clic "Continua a guardare" perché i suoi contenuti sono stati visualizzati su più dispositivi.

Eliminare i dati di Video Discovery

Per eliminare manualmente i dati di un utente dal server Google TV prima del periodo di conservazione standard di 60 giorni, utilizza il metodo client.deleteClusters(). Al ricevimento della richiesta, il servizio eliminerà tutti i dati esistenti sulla scoperta dei video 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 dati relativi alla ripresa della visione al momento della disconnessione.


// If the user logs out from your media app, you must make the following call
// to remove continue watching data from the current google TV device,
// otherwise, the continue watching data will persist on the current
// google TV device until 60 days later.
client.deleteClusters(
  new DeleteClustersRequest.Builder()
        .setAccountProfile(AccountProfile())
        .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
        .setSyncAcrossDevices(true)
        .build()
)

Test

Utilizza l'app di verifica per assicurarti che l'integrazione dell'SDK Engage funzioni correttamente. Questa applicazione per Android fornisce strumenti per aiutarti a verificare i tuoi dati e confermare che gli intent di trasmissione vengono gestiti correttamente.

Dopo aver invocato l'API di pubblicazione, verifica che i dati vengano pubblicati correttamente controllando l'app di verifica. Il cluster di continuazione dovrebbe essere visualizzato come riga distinta all'interno dell'interfaccia dell'app.

  • Assicurati che il flag del servizio Engage NON sia impostato su produzione nel file manifest Android della tua app.
  • Installa e apri l'app Engage Verify
  • Se isServiceAvailable è false, fai clic sul pulsante "Attiva/Disattiva" per attivare l'opzione.
  • Inserisci il nome del pacchetto dell'app per visualizzare automaticamente i dati pubblicati quando inizi la pubblicazione.
  • Testa queste azioni nella tua app:
    • Accedi.
    • Passare da un profilo all'altro(se applicabile).
    • Avvia e metti in pausa un video oppure torna alla home page.
    • Chiudi l'app durante la riproduzione di un video.
    • Rimuovi un elemento dalla riga "Continua a guardare" (se supportata).
  • Dopo ogni azione, verifica che la tua app abbia invocato l'API publishContinuationClusters e che i dati vengano visualizzati correttamente nell'app di verifica.
  • L'app di verifica mostrerà un segno di spunta verde "Tutto a posto" per le entità implementate correttamente.

    Screenshot dell&#39;app di verifica riuscita
    Figura 1. Verifica App Success
  • L'app di verifica segnalerà eventuali entità problematiche.

    Screenshot dell&#39;errore dell&#39;app di verifica
    Figura 2. Errore dell'app di verifica
  • Per risolvere i problemi relativi alle entità con errori, utilizza il telecomando della TV per selezionare e fare clic sull'entità nell'app di verifica. I problemi specifici verranno visualizzati e evidenziati in rosso per la tua revisione (vedi l'esempio di seguito).

    Dettagli errore dell&#39;app di verifica
    Figura 3. Dettagli errore dell'app di verifica