Compartilhar direitos de acesso do app com o Google TV usando o SDK Engage

Este guia contém instruções para que os desenvolvedores compartilhem dados de assinatura de app e direitos 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

  1. 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
      }
    
  2. Defina o ambiente do serviço Engage como produção no arquivo AndroidManifest.xml.

    Para o APK para dispositivos móveis

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

    Para o APK da TV

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. Antes de enviar o APK ao Google, defina o ambiente do serviço Engage como produção no arquivo AndroidManifest.xml. Para ter o melhor desempenho 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 usando processos em segundo plano.

  4. Publique informações de assinatura nos seguintes eventos:

    1. O usuário faz login no app.
    2. O usuário alterna entre perfis (se houver suporte para isso).
    3. O usuário compra uma nova assinatura.
    4. O usuário faz upgrade de uma assinatura.
    5. 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:

  1. ID da conta: um identificador exclusivo que representa a conta do usuário. Pode ser o ID real da conta ou uma versão ofuscada adequadamente.
// 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 com um nível de assinatura que concede acesso a todo o conteúdo pago, forneça estes detalhes essenciais:

  1. Tipo de assinatura:indique claramente o plano de assinatura específico do usuário.

    1. SUBSCRIPTION_TYPE_ACTIVE: o usuário tem uma assinatura paga ativa.
    2. SUBSCRIPTION_TYPE_ACTIVE_TRIAL: o usuário tem uma assinatura de teste.
    3. SUBSCRIPTION_TYPE_INACTIVE: o usuário tem uma conta, mas não tem uma assinatura ativa ou um teste.
  2. Prazo de validade:tempo opcional em milissegundos. Especifique quando a assinatura vai expirar.

  3. Nome do pacote do provedor:especifique o nome do pacote do app que processa a assinatura.

Exemplo do feed de amostra do provedor de mídia.

"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 em 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:

  1. Identificador:string de identificador obrigatório para esse direito. Ele precisa corresponder a um dos identificadores de direito de acesso (não é o campo de ID) fornecido no feed do provedor de mídia publicado no Google TV.
  2. Nome:são informações auxiliares usadas para a correspondência de direitos. Embora opcional, fornecer um nome de direito legível por humanos melhora a compreensão dos direitos do usuário para desenvolvedores e equipes de suporte. Por exemplo: Sling Orange.
  3. Expiration TimeMillis: especifique, opcionalmente, o tempo de expiração em milissegundos para esse direito, se ele for diferente do tempo de expiração da assinatura. Por padrão, o direito expira com o término da assinatura.

Para o snippet de exemplo de feed do provedor de mídia 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ço vinculado

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ço vinculado especificando o nome do pacote de serviço vinculado 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 de 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();

Opcionalmente, adicione direitos a uma assinatura de serviço vinculada.

Fornecer conjunto de assinaturas

Execute o job de publicação de conteúdo enquanto o app está 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

  1. Para fornecer atualizações imediatas após mudanças, chame publishSubscriptionCluster() sempre que o estado de assinatura de um usuário mudar, como ativação, desativação, upgrades e downgrades.
  2. Para fornecer uma validação regular de precisão contínua, chame publishSubscriptionCluster() pelo menos uma vez por mês.

  3. 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ídeos do perfil da conta ou de toda a conta, dependendo do DeleteReason fornecido.

    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 oferece 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 integração de publicação

  1. A publicação precisa acontecer quando o app está em primeiro plano e o usuário interage ativamente com ele.

  2. Publicar quando:

    • O usuário faz login pela primeira vez.
    • O usuário muda o 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.
  3. Verifique se o app está chamando corretamente as APIs isServiceAvailable() e publishClusters() no Logcat, nos eventos de publicação.

  4. Verifique se os dados estão visíveis no app de verificação. O app de verificação precisa mostrar 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 de engajamento 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 for false no app de verificação, clique no botão Toggle no app de verificação para definir como true.
    • Insira o nome do pacote do app. Os dados publicados vão aparecer automaticamente.
  5. Acesse o app e realize as seguintes ações:

    • Faça login.
    • alternar entre perfis (se houver suporte).
    • Compre uma nova assinatura.
    • Fazer upgrade de uma assinatura.
    • Fazer a assinatura expirar.

Verificar a integração

Para testar a 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. Ele ajuda a verificar a precisão dos dados e a funcionalidade adequada antes do lançamento.

  1. Para cada um dos eventos, verifique se o app invocou a API publishSubscription. Verifique os dados publicados no app de verificação. Verifique se tudo está verde no app de verificação
  2. Se todas as informações da entidade estiverem corretas, uma marca de seleção verde "Tudo certo" vai aparecer em todas as entidades.

    Captura de tela de sucesso do app de verificação
    Figura 1. Assinatura concluída
  3. Os problemas também são destacados no app de verificação

    Captura de tela de erro do app de verificação
    Figura 2.Falha na assinatura
  4. Para conferir os problemas na assinatura do pacote, use o controle remoto da TV para focar nesta assinatura específica e clique para conferir os problemas. Talvez seja necessário focar primeiro na linha e mover para a direita para encontrar o card de assinatura agrupada. Os problemas são destacados em vermelho, conforme mostrado na Figura 3. Além disso, use o controle remoto para rolar para baixo e conferir problemas nos direitos na assinatura do pacote.

    Captura de tela com detalhes do erro do app de verificação
    Figura 3.Erros de assinatura
  5. Para conferir os problemas no direito, use o controle remoto da TV para focar nesse direito específico e clique para conferir os problemas. Os problemas são realçados em vermelho.

    Captura de tela de erro do app de verificação
    Figura 4.Detalhes do erro de assinatura