Это руководство содержит инструкции для разработчиков по обмену данными о подписке и правах на приложения с Google TV с помощью Engage SDK . Пользователи могут найти контент, на который они имеют право, и включить Google TV для предоставления пользователям высокорелевантных рекомендаций по контенту непосредственно в интерфейсе Google TV на телевизоре, мобильном телефоне и планшете.
Предпосылки
Перед использованием API-интерфейса прав на устройства требуется подключение ленты действий мультимедиа. Если вы еще этого не сделали, завершите процесс подключения ленты действий мультимедиа .
Предварительная работа
Прежде чем начать, выполните следующие шаги. Убедитесь, что ваше приложение предназначено для API уровня 19 или выше для этой интеграции.
Добавьте библиотеку
com.google.android.engage
в свое приложение:Для интеграции используются отдельные SDK: один для мобильных приложений и один для ТВ-приложений.
Для мобильных устройств
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
для ТВ
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
Настройте среду службы Engage на работу в файле
AndroidManifest.xml
.Для мобильного apk
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Для ТВ apk
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
Перед отправкой APK в Google установите среду службы Engage в режим production в файле AndroidManifest.xml. Для оптимальной производительности и будущей совместимости публикуйте данные только тогда, когда приложение находится на переднем плане и пользователь активно взаимодействует с ним, например, при запуске приложения, после входа в систему или во время активного использования. Публикация из фоновых процессов не рекомендуется.
Опубликовать информацию о подписке на следующие мероприятия:
- Пользователь входит в ваше приложение.
- Пользователь переключается между профилями (если профили поддерживаются).
- Пользователь приобретает новую подписку.
- Пользователь обновляет существующую подписку.
- Срок действия подписки пользователя истекает.
Интеграция
В этом разделе приведены необходимые примеры кода и инструкции по реализации AccountProfile
и SubscriptionEntity
для управления различными типами подписок.
Учетная запись и профиль пользователя
Чтобы разрешить персонализированные функции на Google TV, предоставьте данные учетной записи. Используйте AccountProfile
, чтобы предоставить:
- ID учетной записи: уникальный идентификатор, представляющий учетную запись пользователя. Это может быть фактический ID учетной записи или его соответствующим образом замаскированная версия.
// 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();
Подписка на общий уровень
Для пользователей с базовыми подписками на услуги медиа-провайдера, например, на услугу с одним уровнем подписки, предоставляющим доступ ко всему платному контенту, предоставьте следующие основные данные:
Тип подписки: четко укажите конкретный план подписки, имеющийся у пользователя.
-
SUBSCRIPTION_TYPE_ACTIVE
: У пользователя есть активная платная подписка. -
SUBSCRIPTION_TYPE_ACTIVE_TRIAL
: У пользователя есть пробная подписка. -
SUBSCRIPTION_TYPE_INACTIVE
: у пользователя есть учетная запись, но нет активной подписки или пробной версии.
-
Время истечения: Необязательное время в миллисекундах. Укажите, когда подписка должна истечь.
Имя пакета поставщика: укажите имя пакета приложения, которое обрабатывает подписку.
Пример фида поставщика медиаданных.
"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
}
В следующем примере создается SubscriptionEntity
для пользователя:
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();
Премиум подписка
Если приложение предлагает многоуровневые премиум-пакеты подписки, включающие расширенный контент или функции, выходящие за рамки обычного уровня, отразите это, добавив одно или несколько прав в Подписку.
Это право имеет следующие поля:
- Идентификатор: Требуемая строка идентификатора для этого права. Она должна соответствовать одному из идентификаторов права (обратите внимание, что это не поле идентификатора), предоставленных в фиде поставщика медиа, опубликованном в Google TV.
- Имя: Это вспомогательная информация, которая используется для сопоставления прав. Хотя это необязательно, предоставление понятного человеку имени права улучшает понимание прав пользователя как для разработчиков, так и для групп поддержки. Например: Sling Orange.
- Expiration TimeMillis: Необязательно укажите время истечения в миллисекундах для этого права, если оно отличается от времени истечения подписки. По умолчанию право истекает с истечением подписки.
Для следующего примера фрагмента фида поставщика медиа:
"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"
}
В следующем примере создается SubscriptionEntity
для подписанного пользователя:
// 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();
Подписка на связанный пакет услуг
Хотя подписки обычно принадлежат поставщику медиаданных исходного приложения, подписку можно отнести к связанному пакету услуг, указав имя связанного пакета услуг в подписке.
Следующий пример кода демонстрирует, как создать подписку пользователя.
// 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();
Кроме того, если у пользователя есть другая подписка на дополнительную услугу, добавьте еще одну подписку и соответствующим образом задайте имя связанного пакета услуг.
// 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();
При желании вы также можете добавить права на подписку на связанную услугу.
Предоставить набор подписок
Запустите задание по публикации контента, пока приложение находится на переднем плане.
Используйте метод publishSubscriptionCluster()
из класса AppEngagePublishClient
для публикации объекта SubscriptionCluster
.
Используйте isServiceAvailable
, чтобы проверить, доступна ли служба для интеграции.
client.publishSubscription(
PublishSubscriptionRequest.Builder()
.setAccountProfile(accountProfile)
.setSubscription(subscription)
.build();
)
Используйте setSubscription()
чтобы убедиться, что у пользователя должна быть только одна подписка на услугу.
Используйте addLinkedSubscription()
или addLinkedSubscriptions()
, которые принимают список связанных подписок, чтобы позволить пользователю иметь ноль или более связанных подписок.
Когда служба получает запрос, создается новая запись, а старая запись автоматически удаляется через 60 дней. Система всегда использует последнюю запись. В случае ошибки весь запрос отклоняется и существующее состояние сохраняется.
Поддерживайте актуальность подписки
- Чтобы предоставлять немедленные обновления при изменениях, вызывайте
publishSubscriptionCluster()
всякий раз, когда изменяется состояние подписки пользователя, например, активация, деактивация, повышение или понижение уровня подписки. Чтобы обеспечить регулярную проверку точности данных, вызывайте
publishSubscriptionCluster()
не реже одного раза в месяц.Чтобы удалить данные Video discovery, вручную удалите данные пользователя с сервера Google TV до истечения стандартного 60-дневного срока хранения, используйте метод
client.deleteClusters()
. Это удалит все существующие данные video discovery для профиля учетной записи или для всей учетной записи в зависимости от заданногоDeleteReason
.Фрагмент кода для удаления подписки пользователя
// 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() )
Тестирование
В этом разделе представлено пошаговое руководство по тестированию реализации подписки. Проверьте точность данных и надлежащую функциональность перед запуском.
Опубликовать контрольный список интеграции
Публикация должна происходить, когда приложение находится на переднем плане и пользователь активно с ним взаимодействует.
Опубликовать когда:
- Пользователь входит в систему впервые.
- Пользователь меняет профиль (если профили поддерживаются).
- Пользователь приобретает новую подписку.
- Подписка на обновления для пользователей.
- Срок действия подписки пользователя истекает.
Проверьте, правильно ли приложение вызывает API
isServiceAvailable()
иpublishClusters()
в logcat при публикации событий.Проверьте, что данные видны в приложении проверки. Приложение проверки должно отображать подписку в виде отдельной строки. При вызове API публикации данные должны отображаться в приложении проверки.
- Убедитесь, что флаг Engage Service не установлен на производство в файле манифеста Android приложения.
- Установите и откройте приложение Engage Verification.
- Если в приложении проверки значение
isServiceAvailable
равноfalse
, нажмите кнопкуToggle
в приложении проверки, чтобы установить его вtrue
. - Введите имя пакета приложения. Оно автоматически покажет опубликованные данные.
Перейдите в приложение и выполните каждое из следующих действий:
- Войти.
- переключение между профилями (если поддерживается).
- Приобретите новую подписку.
- Обновите существующую подписку.
- Истечение срока действия подписки.
Проверить интеграцию
Чтобы проверить интеграцию, воспользуйтесь приложением для проверки .
Приложение для проверки — это приложение Android, которое разработчики могут использовать для проверки работоспособности интеграции. Приложение включает возможности, помогающие разработчикам проверять данные и транслировать намерения. Оно помогает проверить точность данных и надлежащую функциональность перед запуском.
- Для каждого из событий проверьте, вызвало ли приложение API
publishSubscription
. Проверьте опубликованные данные в приложении проверки. Убедитесь, что в приложении проверки все зеленое Если вся информация об объекте верна, во всех объектах отображается зеленая галочка «Все хорошо».
Рисунок 1. Успешная подписка Проблемы также отображаются в приложении проверки.
Рисунок 2. Подписка не удалась Чтобы увидеть проблемы в пакетной подписке, используйте пульт ДУ телевизора, чтобы сфокусироваться на этой конкретной пакетной подписке и щелкните, чтобы увидеть проблемы. Возможно, вам придется сначала сфокусироваться на строке и переместиться вправо, чтобы найти карточку пакетной подписки. Проблемы выделены красным, как показано на рис. 3. Также используйте пульт ДУ, чтобы переместиться вниз, чтобы увидеть проблемы в правах в пакетной подписке
Рисунок 3. Ошибки подписки Чтобы увидеть проблемы в праве, используйте пульт ДУ телевизора, чтобы сфокусироваться на этом конкретном праве, и щелкните, чтобы увидеть проблемы. Проблемы выделены красным.
Рисунок 4. Подробности ошибки подписки