Condividere i diritti di app con Google TV utilizzando l'SDK Engage

Questa guida contiene le istruzioni per gli sviluppatori per condividere i dati relativi agli abbonamenti e ai diritti delle app con Google TV utilizzando l'SDK Engage. Gli utenti possono trovare i contenuti a cui hanno diritto e consentire a Google TV di fornire consigli sui contenuti altamente pertinenti direttamente nelle esperienze di Google TV su TV, dispositivi mobili e tablet.

Prerequisiti

Prima di poter utilizzare l'API per i diritti del dispositivo, devi eseguire l'onboarding del feed delle azioni multimediali. Se non l'hai ancora fatto, completa la procedura di onboarding del feed delle azioni multimediali.

Preparazione

Completa le istruzioni di preparazione nella guida introduttiva.

  1. Pubblica le informazioni sull'abbonamento per i seguenti eventi:
    1. L'utente accede alla tua app.
    2. L'utente passa da un profilo all'altro (se i profili sono supportati).
    3. L'utente acquista un nuovo abbonamento.
    4. L'utente esegue l'upgrade di un abbonamento esistente.
    5. L'abbonamento dell'utente scade.

Integrazione

Questa sezione fornisce gli esempi di codice e le istruzioni necessari per implementare SubscriptionEntity per gestire vari tipi di abbonamento.

Abbonamento di livello comune

Per gli utenti con abbonamenti di base ai servizi dei fornitori di contenuti multimediali, ad esempio un servizio con un livello di abbonamento che concede l'accesso a tutti i contenuti a pagamento, fornisci questi dettagli essenziali:

  1. SubscriptionType: indica chiaramente il piano di abbonamento specifico dell'utente.

    • SUBSCRIPTION_TYPE_ACTIVE: l'utente ha un abbonamento a pagamento attivo.
    • SUBSCRIPTION_TYPE_ACTIVE_TRIAL: l'utente ha un abbonamento di prova.
    • SUBSCRIPTION_TYPE_INACTIVE: l'utente ha un account, ma nessun abbonamento o prova attivo.
  2. ExpirationTimeMillis: tempo facoltativo in millisecondi. Specifica quando scadrà l'abbonamento.

  3. ProviderPackageName: specifica il nome del pacchetto dell'app che gestisce l'abbonamento.

Esempio per il feed del fornitore di contenuti multimediali di esempio.

"actionAccessibilityRequirement": [
  {
    "@type": "ActionAccessSpecification",
    "category": "subscription",
    "availabilityStarts": "2022-06-01T07:00:00Z",
    "availabilityEnds": "2026-05-31T07:00:00Z",
    "requiresSubscription": {
    "@type": "MediaSubscription",
    // Don't match this string,
    // ID is only used to for reconciliation purpose
    "@id": "https://www.example.com/971bfc78-d13a-4419",
    // Don't match this, as name is only used for displaying purpose
    "name": "Basic common name",
    "commonTier": true
  }

L'esempio seguente crea un SubscriptionEntity per un utente:

val subscription = SubscriptionEntity.Builder()
  setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds since epoch
  .setExpirationTimeMillis(1767052800000)
  .build()

Abbonamento premium

Se l'offerta dell'app include pacchetti di abbonamento premium a più livelli, che includono contenuti o funzionalità estesi oltre il livello comune, rappresentali aggiungendo uno o più diritti all'abbonamento.

Questo diritto ha i seguenti campi:

  1. Identifier: stringa identificatore obbligatoria per questo diritto. Deve corrispondere a uno degli identificatori dei diritti (tieni presente che non è il campo ID) forniti nel feed del fornitore di contenuti multimediali pubblicato su Google TV.
  2. Name: si tratta di informazioni ausiliarie utilizzate per la corrispondenza dei diritti. Anche se facoltativo, fornire un nome di diritto leggibile migliora la comprensione dei diritti utente sia per gli sviluppatori sia per i team di assistenza. Ad esempio: Sling Orange.
  3. ExpirationTimeMillis: se vuoi, specifica la data e l'ora di scadenza in millisecondi per questo diritto, se diversa dalla data e ora di scadenza dell'abbonamento. Per impostazione predefinita, il diritto scadrà con la scadenza dell'abbonamento.

Per il seguente snippet del feed del fornitore di contenuti multimediali di esempio:

"actionAccessibilityRequirement": [
  {
    "@type": "ActionAccessSpecification",
    "category": "subscription",
    "availabilityStarts": "2022-06-01T07:00:00Z",
    "availabilityEnds": "2026-05-31T07:00:00Z",
    "requiresSubscription": {
    "@type": "MediaSubscription",
    // Don't match this string,
    // ID is only used to for reconciliation purpose
    "@id": "https://www.example.com/971bfc78-d13a-4419",

    // Don't match this, as name is only used for displaying purpose
    "name": "Example entitlement name",
    "commonTier": false,
    // match this identifier in your API. This is the crucial
    // entitlement identifier used for recommendation purpose.
    "identifier": "example.com:entitlementString1"
  }

L'esempio seguente crea un SubscriptionEntity per un utente abbonato:

// Subscription with entitlements.
// The entitlement expires at the same time as its subscription.
val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds
  .setExpirationTimeMillis(1767052800000)
  .addEntitlement(
    SubscriptionEntitlement.Builder()
    // matches with the identifier in media provider feed
    .setEntitlementId("example.com:entitlementString1")
    .setDisplayName("entitlement name1")
    .build()
  )
  .build()
// Subscription with entitlements
// The entitement has different expiration time from its subscription
val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds
  .setExpirationTimeMillis(1767052800000)
  .addEntitlement(
    SubscriptionEntitlement.Builder()
    .setEntitlementId("example.com:entitlementString1")
    .setDisplayName("entitlement name1")
    // You may set the expiration time for entitlement
    // December 15, 2025 10:00:00 AM in milliseconds
    .setExpirationTimeMillis(1765792800000)
    .build())
  .build()

Abbonamento per il pacchetto di servizi collegati

Sebbene gli abbonamenti appartengano in genere al fornitore di contenuti multimediali dell'app di origine, un abbonamento può essere attribuito a un pacchetto di servizi collegati specificando il nome del pacchetto di servizi collegati all'interno dell'abbonamento.

Il seguente esempio di codice mostra come creare un abbonamento utente.

// Subscription for linked service package
val subscription = SubscriptionEntity.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("com.google.android.example")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds since epoch
  .setExpirationTimeMillis(1767052800000)
  .build()

Inoltre, se l'utente ha un altro abbonamento a un servizio sussidiario, aggiungi un altro abbonamento e imposta il nome del pacchetto di servizi collegati di conseguenza.

// Subscription for linked service package
val linkedSubscription = Subscription.Builder()
  .setSubscriptionType(
    SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE
  )
  .setProviderPackageName("linked service package name")
  // Optional
  // December 30, 2025 12:00:00AM in milliseconds since epoch
  .setExpirationTimeMillis(1767052800000)
  .addBundledSubscription(
    BundledSubscription.Builder()
      .setBundledSubscriptionProviderPackageName(
        "bundled-subscription-package-name"
      )
      .setSubscriptionType(SubscriptionType.SUBSCRIPTION_TYPE_ACTIVE)
      .setExpirationTimeMillis(111)
      .addEntitlement(
        SubscriptionEntitlement.Builder()
        .setExpirationTimeMillis(111)
        .setDisplayName("Silver subscription")
        .setEntitlementId("subscription.tier.platinum")
        .build()
      )
      .build()
  )
    .build()

Se vuoi, puoi aggiungere diritti anche a un abbonamento a un servizio collegato.

Fornisci l'insieme di abbonamenti

Esegui il job di pubblicazione dei contenuti mentre l'app è in primo piano.

Utilizza il metodo publishSubscriptionCluster() della classe AppEngagePublishClient per pubblicare un oggetto SubscriptionCluster.

Assicurati di inizializzare il client e verificare la disponibilità del servizio come descritto nella guida introduttiva.

client.publishSubscription(
  PublishSubscriptionRequest.Builder()
    .setAccountProfile(accountProfile)
    .setSubscription(subscription)
    .build()
  )

Utilizza setSubscription() per verificare che l'utente debba avere un solo abbonamento al servizio.

Utilizza addLinkedSubscription() o addLinkedSubscriptions(), che accettano un elenco di abbonamenti collegati, per consentire all'utente di avere zero o più abbonamenti collegati.

Quando il servizio riceve la richiesta, viene creata una nuova voce e quella precedente viene eliminata automaticamente dopo 60 giorni. Il sistema utilizza sempre l'ultima voce. In caso di errore, l'intera richiesta viene rifiutata e lo stato esistente viene mantenuto.

Mantieni aggiornato l'abbonamento

  1. Per fornire aggiornamenti immediati in caso di modifiche, chiama publishSubscriptionCluster ogni volta che lo stato dell'abbonamento di un utente cambia, ad esempio attivazione, disattivazione, upgrade, downgrade.

  2. Per fornire una convalida regolare per l'accuratezza continua, chiama publishSubscriptionCluster almeno una volta al mese.

  3. Per eliminare i dati di Engage, elimina manualmente i dati di un utente dal server di Google TV prima del periodo di conservazione standard di 60 giorni utilizzando il metodo client.deleteClusters. Vengono eliminati tutti i dati di Engage esistenti per il profilo dell'account o per l'intero account a seconda del specificato DeleteReason.

    Il seguente snippet di codice mostra come rimuovere l'abbonamento di un utente:

    // If the user logs out from your media app, you must make the following call
    // to remove subscription and other Engage data from the current
    // google TV device.
    client.deleteClusters(
      new DeleteClustersRequest.Builder()
        .setAccountProfile(accountProfile)
      .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
      .build()
      )
    

    Il seguente snippet di codice mostra la rimozione dell'abbonamento utente quando l'utente revoca il consenso:

    // If the user revokes the consent to share across device, make the call
    // to remove subscription and other Engage data from all google
    // TV devices.
    client.deleteClusters(
      new DeleteClustersRequest.Builder()
        .setAccountProfile(accountProfile)
        .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
        .build()
    )
    

    Il seguente codice mostra come rimuovere i dati dell'abbonamento all'eliminazione del profilo utente.

    // If the user delete a specific profile, you must make the following call
    // to remove subscription data and other Engage data.
    client.deleteClusters(
      new DeleteClustersRequest.Builder()
      .setAccountProfile(accountProfile)
      .setReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION)
      .build()
    )
    

Test

Questa sezione fornisce una guida passo passo per testare l'implementazione dell'abbonamento. Verifica l'accuratezza dei dati e la funzionalità corretta prima del lancio.

Elenco di controllo per la pubblicazione dell'integrazione

  1. La pubblicazione deve avvenire quando l'app è in primo piano e l'utente interagisce attivamente con essa.

  2. Pubblica quando:

    • L'utente accede per la prima volta.
    • L'utente cambia profilo (se i profili sono supportati).
    • L'utente acquista un nuovo abbonamento.
    • L'utente esegue l'upgrade dell'abbonamento.
    • L'abbonamento dell'utente scade.
  3. Controlla se l'app chiama correttamente le API isServiceAvailable e publishClusters in logcat, negli eventi di pubblicazione.

  4. Verifica che i dati siano visibili nell'app di verifica. L'app di verifica deve mostrare l'abbonamento come riga separata. Quando viene richiamata l'API di pubblicazione, i dati devono essere visualizzati nell'app di verifica.

  5. Vai all'app ed esegui ognuna delle seguenti azioni:

    • Accedi.
    • Passa da un profilo all'altro (se supportato).
    • Acquista un nuovo abbonamento.
    • Esegui l'upgrade di un abbonamento esistente.
    • Fai scadere l'abbonamento.

Verifica l'integrazione

Per testare l'integrazione, utilizza l'app di verifica.

  1. Per ogni evento, controlla se l'app ha richiamato l'API publishSubscription. Verifica i dati pubblicati nell'app di verifica. Verifica che tutto sia verde nell'app di verifica
  2. Se tutte le informazioni dell'entità sono corrette, viene visualizzato un segno di spunta verde "Tutto ok" in tutte le entità.

    Screenshot della verifica riuscita dell'app
    Figura 1. Abbonamento riuscito
  3. I problemi vengono evidenziati anche nell'app di verifica

    Screenshot dell'errore dell'app di verifica
    Figura 2.Abbonamento non riuscito
  4. Per visualizzare i problemi nell'abbonamento in bundle, utilizza il telecomando della TV per concentrarti su quell'abbonamento in bundle specifico e fai clic per visualizzare i problemi. Potresti dover prima concentrarti sulla riga e spostarti verso destra per trovare la scheda Abbonamento in bundle. I problemi vengono evidenziati in rosso, come mostrato nella Figura 3. Inoltre, utilizza il telecomando per spostarti verso il basso per visualizzare i problemi relativi ai diritti all'interno dell'abbonamento in bundle.

    Screenshot dei dettagli dell'errore dell'app di verifica
    Figura 3.Errori di abbonamento
  5. Per visualizzare i problemi relativi al diritto, utilizza il telecomando della TV per concentrarti su quel diritto specifico e fai clic per visualizzare i problemi. I problemi vengono evidenziati in rosso.

    Screenshot dell'errore dell'app di verifica
    Figura 4.Dettagli degli errori di abbonamento