Este guia contém instruções para desenvolvedores compartilharem dados de assinatura e direitos do app com o Google TV usando o SDK Engage. Os usuários podem encontrar conteúdo a que têm direito e permitir que o Google TV ofereça recomendações de conteúdo altamente relevantes diretamente nas experiências do Google TV em TVs, dispositivos móveis e tablets.
Pré-requisitos
É necessário integrar o feed de ações de mídia antes de usar a API de direitos do dispositivo. Se ainda não tiver feito isso, conclua o processo de integração do feed de ações de mídia.
Pré-trabalho
Antes de começar, siga estas etapas: Verifique se o app é direcionado à API de nível 19 ou mais recente para essa integração.
Adicione a biblioteca
com.google.android.engage
ao app:Há SDKs separados para usar na integração: um para apps para dispositivos móveis e outro para apps de TV.
Para dispositivos móveis
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
para TV
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
Defina o ambiente de serviço do Engage como produção no arquivo
AndroidManifest.xml
.Para APKs de dispositivos móveis
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
APK para TV
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Antes de enviar o APK ao Google, defina o ambiente de serviço de engajamento como produção no arquivo AndroidManifest.xml. Para ter um desempenho ideal e compatibilidade futura, publique dados somente quando o app estiver em primeiro plano e o usuário estiver interagindo ativamente com ele, como no lançamento do app, após o login ou durante o uso ativo. Não é recomendável publicar de processos em segundo plano.
Publicar informações de assinatura nos seguintes eventos:
- O usuário faz login no app.
- O usuário alterna entre perfis (se eles forem compatíveis).
- O usuário compra uma nova assinatura.
- O usuário faz upgrade de uma assinatura.
- A assinatura do usuário expira.
Integração
Esta seção fornece os exemplos de código e as instruções necessárias para implementar AccountProfile
e SubscriptionEntity
e gerenciar vários tipos de assinatura.
Conta e perfil do usuário
Para permitir recursos personalizados no Google TV, forneça informações da conta. Use o AccountProfile
para fornecer:
- ID da conta: um identificador exclusivo que representa a conta do usuário. Pode ser o ID da conta real ou uma versão adequadamente ofuscada.
// 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();
Assinatura de nível comum
Para usuários com assinaturas básicas de serviços de provedores de mídia, por exemplo, um serviço que tem um nível de assinatura que concede acesso a todo o conteúdo pago, forneça estes detalhes essenciais:
Tipo de assinatura:indique claramente o plano de assinatura específico que o usuário tem.
SUBSCRIPTION_TYPE_ACTIVE
: o usuário tem uma assinatura paga ativa.SUBSCRIPTION_TYPE_ACTIVE_TRIAL
: o usuário tem uma assinatura de teste.SUBSCRIPTION_TYPE_INACTIVE
: o usuário tem uma conta, mas não tem uma assinatura ou um teste ativo.
Prazo de validade:tempo opcional em milissegundos. Especifique quando a assinatura vai expirar.
Nome do pacote do provedor:especifique o nome do pacote do app que processa a assinatura.
Exemplo para o feed do provedor de mídia de amostra.
"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
}
O exemplo a seguir cria um SubscriptionEntity
para um usuário:
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();
Assinatura Premium
Se o app oferecer pacotes de assinatura premium de vários níveis, incluindo conteúdo ou recursos expandidos além do nível comum, represente isso adicionando um ou mais direitos à assinatura.
Esse direito tem os seguintes campos:
- Identificador:string de identificador obrigatória para esse direito. Ele precisa corresponder a um dos identificadores de direitos (não é o campo "ID") fornecidos no feed do provedor de mídia publicado no Google TV.
- Nome:são informações auxiliares usadas para correspondência de direitos. Embora seja opcional, fornecer um nome de direito legível para humanos melhora a compreensão dos direitos do usuário para desenvolvedores e equipes de suporte. Por exemplo: Sling Orange.
- Expiration TimeMillis: especifique opcionalmente o prazo de validade em milissegundos para esse direito, se ele for diferente do prazo de validade da assinatura. Por padrão, o direito expira com a assinatura.
Para o snippet de feed de provedor de mídia de exemplo a seguir:
"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"
}
O exemplo a seguir cria um SubscriptionEntity
para um usuário inscrito:
// 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();
Assinatura do pacote de serviços vinculados
Embora as assinaturas normalmente pertençam ao provedor de mídia do app de origem, é possível atribuir uma assinatura a um pacote de serviços vinculados especificando o nome do pacote de serviços vinculados na assinatura.
O exemplo de código a seguir demonstra como criar uma assinatura de usuário.
// 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();
Além disso, se o usuário tiver outra assinatura de um serviço subsidiário, adicione outra assinatura e defina o nome do pacote do serviço vinculado de acordo.
// 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 quiser, adicione direitos a uma assinatura de serviço vinculada também.
Fornecer conjunto de assinaturas
Execute o trabalho de publicação de conteúdo enquanto o app estiver em primeiro plano.
Use o método publishSubscriptionCluster()
da classe AppEngagePublishClient
para publicar um objeto SubscriptionCluster
.
Use isServiceAvailable
para verificar se o serviço está
disponível para integração.
client.publishSubscription(
PublishSubscriptionRequest.Builder()
.setAccountProfile(accountProfile)
.setSubscription(subscription)
.build();
)
Use setSubscription()
para verificar se o usuário tem apenas uma assinatura do serviço.
Use addLinkedSubscription()
ou addLinkedSubscriptions()
, que aceitam uma lista
de assinaturas vinculadas, para permitir que o usuário tenha zero ou mais assinaturas
vinculadas.
Quando o serviço recebe a solicitação, uma nova entrada é criada e a antiga é excluída automaticamente após 60 dias. O sistema sempre usa a entrada mais recente. Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
Manter a assinatura atualizada
- Para fornecer atualizações imediatas após as mudanças, chame
publishSubscriptionCluster()
sempre que o estado da assinatura de um usuário mudar como ativação, desativação, upgrades e downgrades. Para fornecer validação regular da acurácia contínua, chame
publishSubscriptionCluster()
pelo menos uma vez por mês.Para excluir os dados de descoberta de vídeo, exclua manualmente os dados de um usuário do servidor do Google TV antes do período padrão de retenção de 60 dias usando o método
client.deleteClusters()
. Isso exclui todos os dados de descoberta de vídeo existentes para o perfil da conta ou para a conta inteira, dependendo doDeleteReason
especificado.Snippet de código para remover a assinatura do usuário
// 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() )
Teste
Esta seção fornece um guia detalhado para testar a implementação de assinaturas. Verifique a precisão dos dados e a funcionalidade adequada antes do lançamento.
Lista de verificação de publicação da integração
A publicação deve acontecer quando o app está em primeiro plano e o usuário interage ativamente com ele.
Publicar quando:
- O usuário faz login pela primeira vez.
- O usuário muda de perfil (se houver suporte para perfis).
- O usuário compra uma nova assinatura.
- O usuário faz upgrade da assinatura.
- A assinatura do usuário expira.
Verifique se o app está chamando corretamente as APIs
isServiceAvailable()
epublishClusters()
no logcat, nos eventos de publicação.Confira se os dados estão visíveis no app de verificação. O app de verificação mostra a assinatura como uma linha separada. Quando a API de publicação é invocada, os dados aparecem no app de verificação.
- Verifique se a flag do serviço Engage NÃO está definida como produção no arquivo de manifesto do Android do app.
- Instale e abra o app Engage Verification.
- Se o valor de
isServiceAvailable
forfalse
no app de verificação, clique no botãoToggle
no app de verificação para definir comotrue
. - Insira o nome do pacote do app. Os dados publicados vão aparecer automaticamente.
Acesse o app e faça cada uma das seguintes ações:
- Faça login.
- alternar entre perfis (se compatível).
- Compre uma nova assinatura.
- Fazer upgrade de uma assinatura.
- Expirar a assinatura.
Verificar a integração
Para testar sua integração, use o app de verificação.
O app de verificação é um app Android que os desenvolvedores podem usar para conferir se a integração está funcionando. O app inclui funcionalidades para ajudar os desenvolvedores a verificar dados e transmitir intents. Isso ajuda a verificar a precisão dos dados e a funcionalidade adequada antes do lançamento.
- Para cada um dos eventos, verifique se o app invocou a API
publishSubscription
. Verifique os dados publicados no app de verificação. Confira se tudo está verde no app de verificação Se todas as informações da entidade estiverem corretas, um ícone de marca de seleção verde "Tudo certo" vai aparecer em todas as entidades.
Figura 1. Assinatura feita com sucesso Os problemas também são destacados no app de verificação
Figura 2.Assinatura sem sucesso Para ver os problemas na assinatura do pacote, use o controle remoto da TV para focar na assinatura específica e clique para conferir os problemas. Talvez seja necessário primeiro focar na linha e mover para a direita para encontrar o card "Assinatura agrupada". Os problemas são destacados em vermelho, conforme mostrado na Figura 3. Use também o controle remoto para rolar para baixo e ver problemas nos direitos na assinatura agrupada.
Figura 3.Erros de assinatura Para ver os problemas no direito, use o controle remoto da TV para focar nesse direito específico e clique para ver os problemas. Os problemas são destacados em vermelho.
Figura 4.Detalhes do erro de assinatura
Fazer o download
Antes de fazer o download, é necessário concordar com os Termos e Condições a seguir.