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 all'interno delle esperienze Google TV su TV, dispositivi mobili e tablet.
Prerequisiti
L'onboarding del feed di azioni multimediali è necessario prima di poter utilizzare l'API Diritti dispositivo. Se non l'hai ancora fatto, completa la procedura di onboarding del feed di azioni media.
Preparazione
Prima di iniziare, completa i seguenti passaggi: Verifica che l'app abbia come target il livello API 19 o versioni successive per questa integrazione
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.
Per dispositivi mobili
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
per TV
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
Imposta l'ambiente di servizio Engage su produzione nel file
AndroidManifest.xml
.Per apk mobile
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
APK per TV
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Prima di inviare l'APK a Google, imposta l'ambiente di servizio Engage su produzione nel file AndroidManifest.xml. Per prestazioni ottimali e compatibilità futura, pubblica i dati solo quando l'app è in primo piano e l'utente interagisce attivamente con essa, ad esempio al momento dell'avvio dell'app, dopo l'accesso o durante l'utilizzo attivo. La pubblicazione da processi in background è sconsigliata.
Pubblica le informazioni sull'abbonamento per i seguenti eventi:
- L'utente accede alla tua app.
- L'utente passa da un profilo all'altro (se i profili sono supportati).
- L'utente acquista un nuovo abbonamento.
- L'utente esegue l'upgrade di un abbonamento esistente.
- L'abbonamento dell'utente scade.
Integrazione
Questa sezione fornisce gli esempi di codice e le istruzioni necessarie per implementare AccountProfile
e SubscriptionEntity
per gestire vari tipi di abbonamenti.
Account e profilo utente
Per consentire le funzionalità personalizzate su Google TV, fornisci le informazioni sull'account. Utilizza AccountProfile
per fornire:
- ID account: un identificatore univoco che rappresenta l'account dell'utente. Può essere l'ID account effettivo o una versione offuscata in modo appropriato.
// Set the account ID to which the subscription applies.
// Don't set the profile ID because subscription applies to account level.
val accountProfile = AccountProfile.Builder()
.setAccountId("user_account_id")
.setProfileId("user_profile id")
.build();
Abbonamento di livello comune
Per gli utenti con abbonamenti di base ai servizi di fornitori di contenuti multimediali, ad esempio un servizio con un livello di abbonamento che consente l'accesso a tutti i contenuti a pagamento, fornisci i seguenti dettagli essenziali:
Tipo di abbonamento: indica chiaramente il piano di abbonamento specifico di cui dispone l'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 non ha un abbonamento o una prova attivi.
Scadenza:tempo facoltativo in millisecondi. Specifica quando scade l'abbonamento.
Nome del pacchetto del fornitore:specifica il nome del pacchetto dell'app che gestisce l'abbonamento.
Esempio per il feed del provider di contenuti multimediali di Sample.
"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
}
Nell'esempio seguente viene creato 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'app offre pacchetti di abbonamenti premium a più livelli, che includono contenuti o funzionalità espansi oltre il livello comune, indicalo aggiungendo uno o più diritti ad Abbonamento.
Questo diritto ha i seguenti campi:
- Identificatore:stringa dell'identificatore obbligatoria per questo diritto. Deve corrispondere a uno degli identificatori dei diritti (tieni presente che non si tratta del campo ID) fornito nel feed del fornitore di contenuti multimediali pubblicato su Google TV.
- Nome: si tratta di informazioni ausiliarie utilizzate per la corrispondenza dei diritti. Sebbene facoltativo, fornire un nome leggibile per i diritti consente di comprendere meglio i diritti utente sia per gli sviluppatori sia per i team di assistenza. Ad esempio: Sling Orange.
- Expiration TimeMillis: se vuoi, specifica la scadenza in millisecondi per questo diritto, se è diversa dalla scadenza dell'abbonamento. Per impostazione predefinita, il diritto scade con la scadenza dell'abbonamento.
Per il seguente snippet di 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 iscritto:
// 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 in genere gli abbonamenti appartengano al provider multimediale dell'app di origine, un abbonamento può essere attribuito a un pacchetto di servizi collegato specificandone il nome all'interno dell'abbonamento.
Il seguente esempio di codice mostra come creare l'abbonamento dell'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 secondario, aggiungi un altro abbonamento e imposta di conseguenza il nome del pacchetto del servizio collegato.
// 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, aggiungi anche i diritti 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
.
Utilizza isServiceAvailable
per verificare se il servizio è disponibile per l'integrazione.
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.
Mantenere aggiornato l'abbonamento
- Per fornire aggiornamenti immediati in caso di modifiche, chiama
publishSubscriptionCluster()
ogni volta che cambia lo stato dell'abbonamento di un utente, come attivazione, disattivazione, upgrade e downgrade. Per garantire una convalida regolare della precisione continua, chiama
publishSubscriptionCluster()
almeno una volta al mese.Per eliminare i dati di scoperta video, elimina manualmente i dati di un utente dal server Google TV prima del periodo di conservazione standard di 60 giorni, utilizzando il metodo
client.deleteClusters()
. Verranno eliminati tutti i dati esistenti sulla scoperta dei video per il profilo dell'account o per l'intero account, a seconda del valore specificato perDeleteReason
.Snippet di codice per rimuovere l'abbonamento dell'utente
// If the user logs out from your media app, you must make the following call // to remove subscription and other video discovery data from the current // google TV device. client.deleteClusters( new DeleteClustersRequest.Builder() .setAccountProfile( AccountProfile .Builder() .setAccountId() .setProfileId() .build() ) .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT) .build() ) ``` Following code snippet demonstrates removal of user subscription when user revokes the consent. ```Kotlin // If the user revokes the consent to share across device, make the call // to remove subscription and other video discovery data from all google // TV devices. client.deleteClusters( new DeleteClustersRequest.Builder() .setAccountProfile( AccountProfile .Builder() .setAccountId() .setProfileId() .build() ) .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT) .build() ) ``` Following code demonstrates how to remove subscription data on user profile deletion. ```Kotlin // If the user delete a specific profile, you must make the following call // to remove subscription data and other video discovery data. client.deleteClusters( new DeleteClustersRequest.Builder() .setAccountProfile( AccountProfile .Builder() .setAccountId() .setProfileId() .build() ) .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
La pubblicazione deve avvenire quando l'app è in primo piano e l'utente interagisce attivamente con essa.
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.
Controlla se l'app chiama correttamente le API
isServiceAvailable()
epublishClusters()
in logcat, negli eventi di pubblicazione.Verifica che i dati siano visibili nell'app di verifica. L'app di verifica dovrebbe mostrare l'abbonamento come riga separata. Quando viene invocata l'API di pubblicazione, i dati dovrebbero essere visualizzati nell'app di verifica.
- Verifica che il flag del servizio Engage NON sia impostato su produzione nel file Android Manifest dell'app.
- Installa e apri l'app Engage Verification.
- Se il valore di
isServiceAvailable
èfalse
nell'app di verifica, fai clic sul pulsanteToggle
all'interno dell'app di verifica per impostarlo sutrue
. - Inserisci il nome del pacchetto dell'app. Verranno visualizzati automaticamente i dati pubblicati.
Vai all'app ed esegui ciascuna delle seguenti azioni:
- Accedi.
- Passare da un profilo all'altro (se supportato).
- Acquista un nuovo abbonamento.
- Esegui l'upgrade di un abbonamento esistente.
- Far scadere l'abbonamento.
Verificare l'integrazione
Per testare l'integrazione, utilizza l'app di verifica.
L'app di verifica è un'applicazione per Android che gli sviluppatori possono utilizzare per verificare che l'integrazione funzioni. L'app include funzionalità per aiutare gli sviluppatori a verificare i dati e trasmettere le intenzioni. Consente di verificare l'accuratezza dei dati e la funzionalità corretta prima del lancio.
- Per ciascuno degli eventi, controlla se l'app ha invocato l'API
publishSubscription
. Verifica i dati pubblicati nell'app di verifica. Verifica che tutto sia verde nell'app di verifica Se tutte le informazioni dell'entità sono corrette, viene visualizzato un segno di spunta verde "Tutto a posto" in tutte le entità.
Figura 1. Abbonamento riuscito I problemi vengono evidenziati anche nell'app di verifica
Figura 2.Abbonamento non riuscito Per visualizzare i problemi dell'abbonamento in bundle, usa il telecomando della TV per concentrarti su quell'abbonamento specifico in bundle e fai clic per visualizzare i problemi. Potresti dover prima mettere in primo piano la riga e spostarti verso destra per trovare la scheda Abbonamento combinato. I problemi vengono evidenziati in rosso, come mostrato nella Fig. 3. Inoltre, utilizza il telecomando per spostarti verso il basso per visualizzare i problemi relativi ai diritti all'interno dell'abbonamento in bundle
Figura 3.Errori di abbonamento 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 sono evidenziati in rosso.
Figura 4.Dettagli errore relativo all'abbonamento