Это руководство содержит инструкции для разработчиков по обмену данными о подписках и правах доступа к приложениям с 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
, чтобы указать:
- Идентификатор учётной записи: уникальный идентификатор, представляющий учётную запись пользователя. Это может быть фактический идентификатор учётной записи или его соответствующим образом замаскированная версия.
// 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()
. Это удалит все существующие данные обнаружения видео для профиля учётной записи или для всей учётной записи в зависимости от заданного значения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. Подробности ошибки подписки
Скачать
Перед загрузкой вы должны согласиться со следующими условиями.