Engage SDK を使用してアプリの利用資格を Google TV と共有する

このガイドでは、デベロッパーが Engage SDK を使用してアプリの定期購入と利用資格のデータを Google TV と共有する手順について説明します。ユーザーは、利用資格のあるコンテンツを見つけ、Google TV でテレビ、スマートフォン、タブレットの Google TV エクスペリエンス内で、ユーザーに最も関連性の高いコンテンツの推奨事項を直接提供できるようにすることができます。

前提条件

デバイス利用資格 API を使用するには、メディア アクション フィードのオンボーディングが必要です。まだ完了していない場合は、メディア アクション フィードのオンボーディング プロセスを完了します。

事前作業

スタートガイドの事前準備の手順を完了していること。

  1. 次のイベントでサブスクリプション情報を公開します。
    1. ユーザーがアプリにログインします。
    2. ユーザーがプロファイルを切り替える(プロファイルがサポートされている場合)。
    3. ユーザーが新しい定期購入を購入する。
    4. ユーザーが既存の定期購入をアップグレードする。
    5. ユーザーの定期購入の有効期限が切れます。

統合

このセクションでは、さまざまなサブスクリプション タイプを管理するために SubscriptionEntity を実装するために必要なコードサンプルと手順について説明します。

一般的な階層の定期購入

メディア プロバイダ サービスの基本サブスクリプション(すべての有料コンテンツへのアクセス権を付与する 1 つのサブスクリプション ティアがあるサービスなど)をご利用のユーザー向けに、次の重要な詳細情報を提供します。

  1. SubscriptionType: ユーザーが利用している特定のサブスクリプション プランを明確に示します。

    • SUBSCRIPTION_TYPE_ACTIVE: ユーザーは有効な有料サブスクリプションを利用しています。
    • SUBSCRIPTION_TYPE_ACTIVE_TRIAL: ユーザーがトライアル サブスクリプションを利用している。
    • SUBSCRIPTION_TYPE_INACTIVE: ユーザーはアカウントを持っていますが、有効な定期購入やトライアルはありません。
  2. ExpirationTimeMillis: 省略可能な時間(ミリ秒単位)。サブスクリプションの有効期限を指定します。

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

プレミアム定期購入

アプリで、一般的な階層を超えるコンテンツや機能を含む、複数階層のプレミアム サブスクリプション パッケージを提供している場合は、Subscription に 1 つ以上の利用資格を追加して、これを表します。

この利用資格には次のフィールドがあります。

  1. Identifier: この利用資格の必須の識別子文字列。これは、Google TV に公開されたメディア プロバイダのフィードで提供される利用資格 ID のいずれかと一致している必要があります(ID フィールドではないことに注意してください)。
  2. Name: 補助情報で、利用資格の照合に使用されます。省略可能ですが、人間が読める利用資格名を提供すると、デベロッパーとサポートチームの両方がユーザーの利用資格を理解しやすくなります。例: Sling Orange。
  3. ExpirationTimeMillis: サブスクリプションの有効期限と異なる場合は、この利用資格の有効期限をミリ秒単位で指定します(省略可)。デフォルトでは、利用資格はサブスクリプションの有効期限とともに期限切れになります。

次のサンプル メディア プロバイダ フィード スニペットの場合:

"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() を使用して、ユーザーがサービスへのサブスクリプションを 1 つだけ持つようにします。

リンクされた定期購入のリストを受け入れる addLinkedSubscription() または addLinkedSubscriptions() を使用して、ユーザーが 0 個以上のリンクされた定期購入を利用できるようにします。

サービスがリクエストを受信すると、新しいエントリが作成され、古いエントリは 60 日後に自動的に削除されます。システムは常に最新のエントリを使用します。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

サブスクリプションを最新の状態に保つ

  1. 変更時に即座に更新を提供するには、ユーザーの定期購入の状態(有効化、無効化、アップグレード、ダウングレードなど)が変更されるたびに publishSubscriptionCluster を呼び出します。

  2. 継続的な精度を定期的に検証するには、少なくとも月に 1 回 publishSubscriptionCluster を呼び出します。

  3. Engage データを削除するには、標準の 60 日間の保持期間が経過する前に、client.deleteClusters メソッドを使用して Google TV サーバーからユーザーのデータを手動で削除します。これにより、指定された DeleteReason に応じて、アカウント プロファイルまたはアカウント全体の既存の Engage データがすべて削除されます。

    次のコード スニペットは、ユーザーの定期購入を削除する方法を示しています。

    // If the user logs out from your media app, you must make the following call
    // to remove subscription and other Engage 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 Engage 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 Engage data.
    client.deleteClusters(
      new DeleteClustersRequest.Builder()
      .setAccountProfile(accountProfile)
      .setReason(DeleteReason.DELETE_REASON_ACCOUNT_PROFILE_DELETION)
      .build()
    )
    

テスト

このセクションでは、定期購入の実装をテストする手順について説明します。リリース前にデータの正確性と適切な機能を確認します。

統合の公開チェックリスト

  1. 公開は、アプリがフォアグラウンドにあり、ユーザーがアプリを操作しているときに行う必要があります。

  2. 公開するタイミング:

    • ユーザーが初めてログインします。
    • ユーザーがプロフィールを変更する(プロフィールがサポートされている場合)。
    • ユーザーが新しい定期購入を購入します。
    • ユーザーがサブスクリプションをアップグレードします。
    • ユーザーの定期購入の有効期限が切れます。
  3. ログキャットで、アプリが公開イベントで isServiceAvailable() API と publishClusters() API を正しく呼び出しているかどうかを確認します。

  4. 検証用アプリにデータが表示されていることを確認します。検証用アプリには、サブスクリプションが別の行として表示されます。パブリッシュ API が呼び出されると、検証用アプリにデータが表示されます。

  5. アプリに移動し、次の各操作を行います。

    • ログインします。
    • プロファイルを切り替えます(サポートされている場合)。
    • 新しい定期購入を購入します。
    • 既存の定期購入をアップグレードします。
    • サブスクリプションの有効期限が切れます。

統合を検証する

統合をテストするには、検証アプリを使用します。

  1. 各イベントについて、アプリが publishSubscription API を呼び出したかどうかを確認します。検証用アプリで公開されたデータを確認します。 検証用アプリですべてが緑色になっていることを確認する
  2. エンティティの情報がすべて正しい場合は、すべてのエンティティに緑色の「All Good」チェックマークが表示されます。

    Verification App Success Screenshot
    図 1. サブスクリプションの登録が完了しました
  3. 問題は確認アプリでもハイライト表示されます

    確認アプリのエラーのスクリーンショット
    図 2.登録に失敗しました
  4. バンドルされた定期購入の問題を確認するには、テレビのリモコンを使用してそのバンドルされた定期購入にフォーカスし、クリックして問題を表示します。まず行にフォーカスを合わせてから、右に移動してバンドルされた定期購入カードを見つける必要がある場合があります。図 3 に示すように、問題は赤色でハイライト表示されます。また、リモコンを使用して下に移動し、バンドルされた定期購入の利用資格に関する問題を確認します。

    Verification App Error Details のスクリーンショット
    図 3.サブスクリプション エラー
  5. 利用資格の問題を確認するには、テレビのリモコンを使用してその利用資格にフォーカスし、クリックして問題を表示します。問題は赤色でハイライト表示されます。

    確認アプリのエラーのスクリーンショット
    図 4.定期購入エラーの詳細