book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml
이 가이드에는 개발자가 Engage SDK를 사용하여 앱 정기 결제 및 권한 데이터를 Google TV와 공유하는 방법에 관한 안내가 포함되어 있습니다. 사용자는 자신이 이용할 수 있는 콘텐츠를 찾고 Google TV가 TV, 모바일, 태블릿의 Google TV 환경 내에서 사용자에게 매우 관련성 높은 콘텐츠 추천을 제공하도록 설정할 수 있습니다.
기본 요건
기기 권한 API를 사용하려면 미디어 작업 피드를 온보딩해야 합니다. 아직 완료하지 않았다면 미디어 작업 피드 온보딩 프로세스를 완료합니다.
사전 작업
시작하기 가이드의 사전 작업 안내를 완료합니다.
- 다음 이벤트에 관한 정기 결제 정보를 게시합니다.
- 사용자가 앱에 로그인합니다.
- 사용자가 프로필 간에 전환합니다 (프로필이 지원되는 경우).
- 사용자가 새 정기 결제를 구매합니다.
- 사용자가 기존 정기 결제를 업그레이드합니다.
- 사용자 구독이 만료됩니다.
통합
이 섹션에서는 다양한 구독 유형을 관리하기 위해 SubscriptionEntity를 구현하는 데 필요한 코드 예시와 안내를 제공합니다.
일반 등급 구독
미디어 제공업체 서비스의 기본 구독이 있는 사용자(예: 모든 유료 콘텐츠에 대한 액세스 권한을 부여하는 구독 등급이 하나인 서비스)의 경우 다음 필수 세부정보를 제공하세요.
SubscriptionType: 사용자가 보유한 특정 구독 요금제를 명확하게 표시합니다.SUBSCRIPTION_TYPE_ACTIVE: 사용자에게 활성 유료 구독이 있습니다.SUBSCRIPTION_TYPE_ACTIVE_TRIAL: 사용자에게 무료 체험 구독이 있습니다.SUBSCRIPTION_TYPE_INACTIVE: 사용자에게 계정은 있지만 활성 구독 또는 무료 체험이 없습니다.
ExpirationTimeMillis: 선택적 시간(밀리초)입니다. 정기 결제가 만료되는 시점을 지정합니다.ProviderPackageName: 정기 결제를 처리하는 앱의 패키지 이름을 지정합니다.
샘플 미디어 제공업체 피드의 예
"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()
프리미엄 구독
앱에서 일반 등급을 넘어 확장된 콘텐츠나 기능이 포함된 다단계 프리미엄 정기 결제 패키지를 제공하는 경우 정기 결제에 권한을 하나 이상 추가하여 이를 나타냅니다.
이 권한에는 다음 필드가 있습니다.
Identifier: 이 사용 권한의 필수 식별자 문자열입니다. 이는 Google TV에 게시된 미디어 제공업체의 피드에 제공된 권한 식별자 중 하나와 일치해야 합니다 (ID 필드가 아님).Name: 보조 정보이며 사용 권한 일치에 사용됩니다. 선택사항이지만 사람이 읽을 수 있는 권한 이름을 제공하면 개발자와 지원팀 모두 사용자 권한을 더 잘 이해할 수 있습니다. 예: Sling OrangeExpirationTimeMillis: 정기 결제 만료 시간과 다른 경우 이 혜택의 만료 시간을 밀리초 단위로 선택적으로 지정합니다. 기본적으로 혜택은 구독 만료와 함께 만료됩니다.
다음 샘플 미디어 제공업체 피드 스니펫의 경우
"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()
원하는 경우 연결된 서비스 구독에 권한을 추가할 수도 있습니다.
정기 결제 세트 제공
앱이 포그라운드에 있는 동안 콘텐츠 게시 작업을 실행합니다.
AppEngagePublishClient 클래스의 publishSubscriptionCluster() 메서드를 사용하여 SubscriptionCluster 객체를 게시합니다.
시작 가이드에 설명된 대로 클라이언트를 초기화하고 서비스 사용 가능 여부를 확인해야 합니다.
client.publishSubscription(
PublishSubscriptionRequest.Builder()
.setAccountProfile(accountProfile)
.setSubscription(subscription)
.build()
)
setSubscription()을 사용하여 사용자에게 서비스 구독이 하나만 있어야 하는지 확인합니다.
연결된 정기 결제 목록을 허용하는 addLinkedSubscription() 또는 addLinkedSubscriptions()를 사용하여 사용자가 연결된 정기 결제를 0개 이상 보유할 수 있도록 합니다.
서비스가 요청을 수신하면 새 항목이 생성되고 60일 후에 이전 항목이 자동으로 삭제됩니다. 시스템은 항상 최신 항목을 사용합니다. 오류가 발생하면 전체 요청이 거부되고 기존 상태가 유지됩니다.
구독을 최신 상태로 유지
변경사항이 발생하면 즉시 업데이트를 제공하려면 활성화, 비활성화, 업그레이드, 다운그레이드와 같이 사용자의 정기 결제 상태가 변경될 때마다
publishSubscriptionCluster를 호출하세요.지속적인 정확성을 위해 정기적으로 검증하려면 한 달에 한 번 이상
publishSubscriptionCluster를 호출하세요.동영상 탐색 데이터를 삭제하려면 표준 60일 보관 기간 전에 Google TV 서버에서 사용자의 데이터를 수동으로 삭제하세요.
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) .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT) .build() )다음 코드 스니펫은 사용자가 동의를 취소할 때 사용자 정기 결제를 삭제하는 방법을 보여줍니다.
// 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() )다음 코드는 사용자 프로필 삭제 시 정기 결제 데이터를 삭제하는 방법을 보여줍니다.
// 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() )
테스트
이 섹션에서는 정기 결제 구현을 테스트하는 단계별 가이드를 제공합니다. 출시 전에 데이터 정확성과 적절한 기능을 확인하세요.
통합 게시 체크리스트
앱이 포그라운드에 있고 사용자가 앱과 적극적으로 상호작용할 때 게시가 이루어져야 합니다.
다음과 같은 경우 게시
- 사용자가 처음으로 로그인합니다.
- 사용자가 프로필을 변경합니다 (프로필이 지원되는 경우).
- 사용자가 새 정기 결제를 구매합니다.
- 사용자가 구독을 업그레이드합니다.
- 사용자 구독이 만료됩니다.
앱이 게시 이벤트에서 Logcat의
isServiceAvailable()및publishClusters()API를 올바르게 호출하는지 확인합니다.데이터가 인증 앱에 표시되는지 확인합니다. 인증 앱에는 구독이 별도의 행으로 표시되어야 합니다. 게시 API를 호출하면 데이터가 인증 앱에 표시됩니다.
앱으로 이동하여 다음 각 작업을 수행합니다.
- 로그인합니다.
- 프로필 간에 전환합니다 (지원되는 경우).
- 새 정기 결제를 구매합니다.
- 기존 정기 결제를 업그레이드합니다.
- 구독을 만료합니다.
통합 확인
통합을 테스트하려면 인증 앱을 사용하세요.
- 각 이벤트에 대해 앱이
publishSubscriptionAPI를 호출했는지 확인합니다. 인증 앱에서 게시된 데이터를 확인합니다. 인증 앱에서 모든 항목이 녹색인지 확인 엔티티의 모든 정보가 올바르면 모든 엔티티에 'All Good'(모두 양호) 녹색 체크가 표시됩니다.

그림 1. 구독 성공 인증 앱에서도 문제가 강조 표시됨
그림 2.구독 실패 번들 구독의 문제를 확인하려면 TV 리모컨을 사용하여 해당 번들 구독에 포커스를 맞추고 클릭하여 문제를 확인합니다. 먼저 행에 초점을 맞추고 오른쪽으로 이동하여 번들 구독 카드를 찾아야 할 수도 있습니다. 그림 3과 같이 문제가 빨간색으로 강조 표시됩니다. 또한 리모컨을 사용하여 아래로 이동하여 번들 구독 내 권한 문제를 확인합니다.
그림 3.구독 오류 권한의 문제를 확인하려면 TV 리모컨을 사용하여 해당 권한에 포커스를 맞추고 클릭하여 문제를 확인합니다. 문제는 빨간색으로 강조 표시됩니다.
그림 4.구독 오류 세부정보