Cómo compartir derechos de apps con Google TV con el SDK de Engage

book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml

En esta guía, se incluyen instrucciones para que los desarrolladores compartan datos de suscripciones y derechos de apps con Google TV a través del SDK de Engage. Los usuarios pueden encontrar el contenido al que tienen derecho y habilitar Google TV para que les proporcione recomendaciones de contenido altamente relevantes directamente en las experiencias de Google TV en TVs, dispositivos móviles y tablets.

Requisitos previos

Debes completar la incorporación del feed de acciones multimedia antes de poder usar la API de derechos del dispositivo. Si aún no lo hiciste, completa el proceso de incorporación del feed de acciones multimedia.

Trabajo previo

Completa las instrucciones de Trabajo previo en la guía de introducción.

  1. Publica información de suscripción en los siguientes eventos:
    1. El usuario accede a tu app.
    2. El usuario cambia de perfil (si se admiten perfiles).
    3. El usuario compra una suscripción nueva.
    4. El usuario actualiza una suscripción existente.
    5. Vence la suscripción del usuario.

Integración

En esta sección, se proporcionan los ejemplos de código y las instrucciones necesarios para implementar SubscriptionEntity y administrar varios tipos de suscripciones.

Suscripción de nivel común

En el caso de los usuarios con suscripciones básicas a los servicios de proveedores de contenido multimedia, por ejemplo, un servicio que tiene un nivel de suscripción que otorga acceso a todo el contenido pagado, proporciona estos detalles esenciales:

  1. SubscriptionType: Indica claramente el plan de suscripción específico que tiene el usuario.

    • SUBSCRIPTION_TYPE_ACTIVE: El usuario tiene una suscripción pagada activa.
    • SUBSCRIPTION_TYPE_ACTIVE_TRIAL: El usuario tiene una suscripción de prueba.
    • SUBSCRIPTION_TYPE_INACTIVE: El usuario tiene una cuenta, pero no tiene una suscripción o prueba activa.
  2. ExpirationTimeMillis: Es el tiempo opcional en milisegundos. Especifica cuándo vencerá la suscripción.

  3. ProviderPackageName: Especifica el nombre del paquete de la app que controla la suscripción.

Ejemplo del feed del proveedor de contenido multimedia de muestra.

"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
  }

En el siguiente ejemplo, se crea un objeto SubscriptionEntity para un usuario:

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()

Suscripción a Premium

Si la oferta de la app incluye paquetes de suscripción premium de varios niveles, que incluyen contenido o funciones expandidos más allá del nivel común, representa esto agregando uno o más derechos a Subscription.

Este derecho tiene los siguientes campos:

  1. Identifier: Es la cadena de identificador obligatoria para este derecho. Debe coincidir con uno de los identificadores de derechos (ten en cuenta que no es el campo de ID) que se proporcionan en el feed del proveedor de contenido multimedia publicado en Google TV.
  2. Name: Es información auxiliar que se usa para la coincidencia de derechos. Si bien es opcional, proporcionar un nombre legible para el derecho mejora la comprensión de los derechos del usuario tanto para los desarrolladores como para los equipos de asistencia al cliente. Por ejemplo, Sling Orange.
  3. ExpirationTimeMillis: De forma opcional, especifica la fecha y hora de vencimiento en milisegundos para este derecho, si difiere de la fecha y hora de vencimiento de la suscripción. De forma predeterminada, el derecho vencerá cuando venza la suscripción.

Para el siguiente fragmento de feed de proveedor de contenido multimedia de ejemplo:

"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"
  }

En el siguiente ejemplo, se crea un objeto SubscriptionEntity para un usuario suscrito:

// 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()

Suscripción al paquete de servicios vinculados

Si bien las suscripciones suelen pertenecer al proveedor de contenido multimedia de la app de origen, se puede atribuir una suscripción a un paquete de servicio vinculado si se especifica el nombre del paquete de servicio vinculado dentro de la suscripción.

En el siguiente ejemplo de código, se muestra cómo crear una suscripción del usuario.

// 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()

Además, si el usuario tiene otra suscripción a un servicio subsidiario, agrega otra suscripción y configura el nombre del paquete de servicio vinculado según corresponda.

// 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()

También puedes agregar derechos a una suscripción de servicio vinculada.

Proporciona un conjunto de suscripciones

Ejecuta el trabajo de publicación de contenido mientras la app está en primer plano.

Usa el método publishSubscriptionCluster() de la clase AppEngagePublishClient para publicar un objeto SubscriptionCluster.

Asegúrate de inicializar el cliente y verificar la disponibilidad del servicio como se describe en la guía de introducción.

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

Usa setSubscription() para verificar que el usuario solo debe tener una suscripción al servicio.

Usa addLinkedSubscription() o addLinkedSubscriptions(), que aceptan una lista de suscripciones vinculadas, para permitir que el usuario tenga cero o más suscripciones vinculadas.

Cuando el servicio recibe la solicitud, se crea una entrada nueva y la entrada anterior se borra automáticamente después de 60 días. El sistema siempre usa la entrada más reciente. En caso de error, se rechaza la solicitud completa y se mantiene el estado existente.

Mantén la suscripción actualizada

  1. Para proporcionar actualizaciones inmediatas cuando se produzcan cambios, llama a publishSubscriptionCluster cada vez que cambie el estado de la suscripción de un usuario, como activaciones, desactivaciones, actualizaciones o cambios a una versión inferior.

  2. Para proporcionar una validación periódica de la precisión continua, llama a publishSubscriptionCluster al menos una vez al mes.

  3. Para borrar los datos de Descubrimiento de videos de forma manual antes del período de retención estándar de 60 días, usa el método client.deleteClusters. Esta acción borra todos los datos existentes de las campañas de descubrimiento de video del perfil de la cuenta o de toda la cuenta, según el DeleteReason proporcionado.

    En el siguiente fragmento de código, se muestra cómo quitar la suscripción de un usuario:

    // 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)
      .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
      .build()
      )
    

    En el siguiente fragmento de código, se muestra la eliminación de la suscripción del usuario cuando este revoca el consentimiento:

    // 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)
        .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
        .build()
    )
    

    En el siguiente código, se muestra cómo quitar los datos de suscripción cuando se borra el perfil del usuario.

    // 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)
      .setReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION)
      .build()
    )
    

Prueba

En esta sección, se proporciona una guía paso a paso para probar la implementación de suscripciones. Verifica la precisión de los datos y el funcionamiento correcto antes del lanzamiento.

Lista de tareas de publicación de la integración

  1. La publicación debe ocurrir cuando la app esté en primer plano y el usuario interactúe con ella de forma activa.

  2. Publicar cuando:

    • El usuario accede por primera vez.
    • El usuario cambia de perfil (si se admiten perfiles).
    • El usuario compra una suscripción nueva.
    • El usuario actualiza la suscripción.
    • Vence la suscripción del usuario.
  3. Verifica si la app llama correctamente a las APIs de isServiceAvailable() y publishClusters() en logcat, en los eventos de publicación.

  4. Verifica que los datos sean visibles en la app de verificación, que debe mostrar la suscripción como una fila independiente. Cuando se invoca la API de publicación, los datos deberían aparecer en la app de verificación.

  5. Ve a la app y realiza cada una de las siguientes acciones:

    • Accede.
    • Cambiar entre perfiles (si se admite)
    • Compra una suscripción nueva.
    • Actualiza una suscripción existente.
    • Vence la suscripción.

Verifica la integración

Para probar tu integración, usa la app de verificación.

  1. Para cada uno de los eventos, verifica si la app invocó la API de publishSubscription. Verifica los datos publicados en la app de verificación. Verifica que todo esté en verde en la app de verificación
  2. Si toda la información de la entidad es correcta, se mostrará una marca de verificación verde de "Todo bien" en todas las entidades.

    Captura de pantalla de la verificación correcta de la app
    Figura 1: Suscripción correcta
  3. Los problemas también se destacan en la app de verificación.

    Captura de pantalla del error de la app de verificación
    Figura 2:Suscripción sin éxito
  4. Para ver los problemas de la suscripción combinada, usa el control remoto de la TV para enfocarte en esa suscripción específica y haz clic para ver los problemas. Es posible que primero debas enfocarte en la fila y moverte hacia la derecha para encontrar la tarjeta de suscripción agrupada. Los problemas se resaltan en rojo, como se muestra en la figura 3. Además, usa el control remoto para desplazarte hacia abajo y ver los problemas relacionados con los derechos de la suscripción agrupada.

    Captura de pantalla de los detalles del error de la app de verificación
    Figura 3:Errores de suscripción
  5. Para ver los problemas en el derecho, usa el control remoto de la TV para enfocarte en ese derecho específico y haz clic para ver los problemas. Los problemas se destacan en rojo.

    Captura de pantalla del error de la app de verificación
    Figura 4:Detalles del error de suscripción