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 incorporar el 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
Antes de comenzar, completa los siguientes pasos: Verifica que tu app esté orientada al nivel de API 19 o superior para esta integración.
Agrega la biblioteca
com.google.android.engage
a tu app:Hay SDKs separados para usar en la integración: uno para apps para dispositivos móviles y otro para apps para TVs.
Para dispositivos móviles
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
para TV
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
Establece el entorno del servicio de Engage como producción en el archivo
AndroidManifest.xml
.Para APK de dispositivos móviles
<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 el APK a Google, configura el entorno del servicio de participación como producción en tu archivo AndroidManifest.xml. Para un rendimiento óptimo y compatibilidad futura, publica datos solo cuando la app esté en primer plano y el usuario interactúe con ella de forma activa, por ejemplo, cuando se inicie la app, después de acceder o durante el uso activo. No se recomienda publicar desde procesos en segundo plano.
Publica información de suscripción en los siguientes eventos:
- El usuario accede a tu app.
- El usuario cambia de perfil (si se admiten perfiles).
- El usuario compra una suscripción nueva.
- El usuario actualiza una suscripción existente.
- 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 AccountProfile
y SubscriptionEntity
para administrar varios tipos de suscripciones.
Cuenta y perfil de usuario
Para permitir funciones personalizadas en Google TV, proporciona información de la cuenta. Usa AccountProfile
para proporcionar lo siguiente:
- ID de la cuenta: Es un identificador único que representa la cuenta del usuario. Puede ser el ID de la cuenta real o una versión ofuscada de forma adecuada.
// 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();
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:
Tipo de suscripción: 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.
Hora de vencimiento: Es un horario opcional en milisegundos. Especifica cuándo vencerá la suscripción.
Nombre del paquete del proveedor: Especifica el nombre del paquete de la app que controla la suscripción.
Ejemplo para el feed de muestra del proveedor de contenido multimedia.
"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, agrega uno o más derechos a Subscription para representarlo.
Este derecho tiene los siguientes campos:
- Identifier: Cadena de identificador obligatoria para este derecho. Debe coincidir con uno de los identificadores de derechos (ten en cuenta que no es el campo ID) que se proporcionan en el feed del proveedor de contenido multimedia publicado en Google TV.
- Nombre: Esta es información auxiliar y 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.
- Expiration TimeMillis: De manera opcional, especifica la hora de vencimiento en milisegundos para este derecho, si difiere de la 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
.
Usa isServiceAvailable
para verificar si el servicio está disponible para la integració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
- 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. Para proporcionar una validación periódica de la precisión continua, llama a
publishSubscriptionCluster()
al menos una vez al mes.Para borrar los datos del 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 del descubrimiento de videos para el perfil de la cuenta o para toda la cuenta, según elDeleteReason
proporcionado.Fragmento de código para quitar la suscripción del 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 .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() )
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 para publicar la integración
La publicación debe ocurrir cuando la app esté en primer plano y el usuario interactúe con ella de forma activa.
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.
Comprueba si la app llama correctamente a las APIs de
isServiceAvailable()
ypublishClusters()
en logcat, en los eventos de publicación.Verifica que los datos sean visibles en la app de verificación. La app de verificación 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.
- Verifica que la marca de servicio Engage NO esté configurada como de producción en el archivo de manifiesto de Android de la app.
- Instala y abre la app de Engage Verification.
- Si el valor de
isServiceAvailable
esfalse
en la app de verificación, haz clic en el botónToggle
dentro de la app de verificación para establecerlo entrue
. - Ingresa el nombre del paquete de la app. Los datos publicados se mostrarán automáticamente.
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.
La app de verificación es una aplicación para Android que los desarrolladores pueden usar para verificar que la integración funcione. La app incluye capabilities que ayudan a los desarrolladores a verificar los datos y los intents de transmisión. Ayuda a verificar la precisión de los datos y el funcionamiento adecuado antes del lanzamiento.
- 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 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.
Figura 1: Suscripción exitosa Los problemas también se destacan en la app de verificación.
Figura 2:No se pudo realizar la suscripción 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 combinada. 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 en los derechos de la suscripción agrupada.
Figura 3:Errores de suscripción Para ver los problemas relacionados con 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.
Figura 4:Detalles del error de suscripción
Descargar
Antes de la descarga, debes aceptar los Términos y Condiciones.