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.engageao 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 do- DeleteReasonespecificado.- 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()e- publishClusters()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 isServiceAvailableforfalseno app de verificação, clique no botãoToggleno 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.
