แชร์การให้สิทธิ์ของแอปกับ Google TV โดยใช้ Engage SDK

คู่มือนี้มีวิธีการสำหรับนักพัฒนาแอปในการแชร์ข้อมูลการสมัครใช้บริการและ การให้สิทธิ์ของแอปกับ Google TV โดยใช้ Engage SDK ผู้ใช้สามารถค้นหาเนื้อหาที่ตนมีสิทธิ์เข้าถึงและเปิดใช้ Google TV เพื่อแสดงคำแนะนำเนื้อหาที่เกี่ยวข้องกับผู้ใช้เป็นอย่างยิ่งภายในประสบการณ์การใช้งาน Google TV บนทีวี อุปกรณ์เคลื่อนที่ และแท็บเล็ต

สิ่งที่ต้องมีก่อน

คุณต้องเริ่มต้นใช้งานฟีดการดำเนินการกับสื่อก่อนจึงจะใช้ Device Entitlement API ได้ หากยังไม่ได้ดำเนินการ ให้ทำตามขั้นตอนการเริ่มต้นใช้งานฟีดการดำเนินการกับสื่อmedia actions feedให้เสร็จสมบูรณ์

สิ่งที่ต้องเตรียมก่อนดำเนินการ

ทำตามวิธีการในส่วนสิ่งที่ต้องเตรียมก่อนดำเนินการในคู่มือเริ่มต้นใช้งาน

  1. เผยแพร่ข้อมูลการสมัครใช้บริการในเหตุการณ์ต่อไปนี้
    1. ผู้ใช้เข้าสู่ระบบแอป
    2. ผู้ใช้สลับระหว่างโปรไฟล์ (หากระบบรองรับโปรไฟล์)
    3. ผู้ใช้ซื้อการสมัครใช้บริการใหม่
    4. ผู้ใช้อัปเกรดการสมัครใช้บริการที่มีอยู่
    5. การสมัครใช้บริการของผู้ใช้หมดอายุ

การผสานรวม

ส่วนนี้มีตัวอย่างโค้ดและวิธีการที่จำเป็นสำหรับการใช้ SubscriptionEntity เพื่อจัดการการสมัครใช้บริการประเภทต่างๆ

การสมัครใช้บริการระดับทั่วไป

สำหรับผู้ใช้ที่สมัครใช้บริการพื้นฐานของผู้ให้บริการสื่อ เช่น บริการที่มีการสมัครใช้บริการระดับเดียวซึ่งให้สิทธิ์เข้าถึงเนื้อหาแบบชำระเงินทั้งหมด ให้ระบุรายละเอียดที่จำเป็นต่อไปนี้

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

การสมัครใช้บริการ Premium

หากแอปมีแพ็กเกจการสมัครใช้บริการแบบพรีเมียมหลายระดับ ซึ่งรวมถึงเนื้อหาหรือฟีเจอร์ที่ขยายเพิ่มเติมนอกเหนือจากระดับทั่วไป ให้แสดงสิ่งนี้โดยการเพิ่มการให้สิทธิ์อย่างน้อย 1 รายการในการสมัครใช้บริการ

การให้สิทธิ์นี้มีช่องต่อไปนี้

  1. Identifier: สตริงตัวระบุที่จำเป็นสำหรับการให้สิทธิ์นี้ ซึ่งต้อง ตรงกับตัวระบุการให้สิทธิ์อย่างน้อย 1 รายการ (โปรดทราบ ว่าไม่ใช่ช่องรหัส) ที่ระบุไว้ในฟีดของผู้ให้บริการสื่อ ที่เผยแพร่ไปยัง Google TV
  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()

คุณจะเพิ่มการให้สิทธิ์ในการสมัครใช้บริการสำหรับบริการที่ลิงก์ด้วยก็ได้ (ไม่บังคับ)

ระบุชุดการสมัครใช้บริการ

เรียกใช้ฟังก์ชันการเผยแพร่เนื้อหาขณะที่แอปอยู่ที่ส่วนหน้า

ใช้เมธอด publishSubscriptionCluster() จากคลาส AppEngagePublishClient เพื่อเผยแพร่ออบเจ็กต์ SubscriptionCluster

ตรวจสอบว่าได้เริ่มต้นใช้งานไคลเอ็นต์และตรวจสอบความพร้อมให้บริการตามที่ อธิบายไว้ใน คู่มือเริ่มต้นใช้งาน

client.publishSubscription(
  PublishSubscriptionRequest.Builder()
    .setAccountProfile(accountProfile)
    .setSubscription(subscription)
    .build()
  )

ใช้ setSubscription() เพื่อยืนยันว่าผู้ใช้ควรมีการสมัครใช้บริการสำหรับบริการเพียงรายการเดียว

ใช้ addLinkedSubscription() หรือ addLinkedSubscriptions() ซึ่งยอมรับรายการการสมัครใช้บริการที่ลิงก์ เพื่อให้ผู้ใช้มีการสมัครใช้บริการที่ลิงก์ 0 รายการขึ้นไป

เมื่อบริการได้รับคำขอ ระบบจะสร้างรายการใหม่และลบรายการเก่าออกโดยอัตโนมัติหลังจากผ่านไป 60 วัน ระบบจะใช้รายการล่าสุดเสมอ ในกรณีที่เกิดข้อผิดพลาด ระบบจะปฏิเสธคำขอทั้งหมดและคงสถานะเดิมไว้

อัปเดตการสมัครใช้บริการให้เป็นปัจจุบัน

  1. หากต้องการอัปเดตทันทีเมื่อมีการเปลี่ยนแปลง ให้เรียกใช้ publishSubscriptionCluster ทุกครั้งที่สถานะการสมัครใช้บริการของผู้ใช้เปลี่ยนแปลง เช่น การเปิดใช้งาน การปิดใช้งาน การอัปเกรด การดาวน์เกรด

  2. หากต้องการตรวจสอบความถูกต้องอย่างสม่ำเสมอ ให้เรียกใช้ publishSubscriptionCluster อย่างน้อยเดือนละครั้ง

  3. หากต้องการลบข้อมูล Engage ให้ลบข้อมูลของผู้ใช้จากเซิร์ฟเวอร์ Google TV ด้วยตนเองก่อนระยะเวลาเก็บรักษามาตรฐาน 60 วัน โดยใช้เมธอด client.deleteClusters ซึ่งจะลบข้อมูล Engage ที่มีอยู่ทั้งหมดสำหรับโปรไฟล์บัญชีหรือทั้งบัญชี ทั้งนี้ขึ้นอยู่กับ DeleteReason ที่ระบุ

    ข้อมูลโค้ดต่อไปนี้แสดงวิธีนำการสมัครใช้บริการของผู้ใช้ออก

    // 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. ตรวจสอบว่าแอปเรียกใช้ API ของ isServiceAvailable() และ publishClusters() อย่างถูกต้องใน Logcat ในเหตุการณ์การเผยแพร่

  4. ตรวจสอบว่าข้อมูลปรากฏในแอปยืนยัน โดยแอปยืนยันควรแสดงการสมัครใช้บริการเป็นแถวแยกต่างหาก เมื่อเรียกใช้ API การเผยแพร่ ข้อมูลควรปรากฏในแอปยืนยัน

  5. ไปที่แอปและดำเนินการต่อไปนี้

    • ลงชื่อเข้าใช้
    • สลับระหว่างโปรไฟล์ (หากระบบรองรับ)
    • ซื้อการสมัครใช้บริการใหม่
    • อัปเกรดการสมัครใช้บริการที่มีอยู่
    • ทำให้การสมัครใช้บริการหมดอายุ

ยืนยันการผสานรวม

หากต้องการทดสอบการผสานรวม ให้ใช้แอปยืนยัน

  1. ตรวจสอบว่าแอปได้เรียกใช้ publishSubscription API สำหรับแต่ละเหตุการณ์ ยืนยันข้อมูลที่เผยแพร่ในแอปยืนยัน ตรวจสอบว่าทุกอย่างเป็นสีเขียวในแอปยืนยัน
  2. หากข้อมูลทั้งหมดของเอนทิตีถูกต้อง ระบบจะแสดงเครื่องหมายถูกสีเขียว "เรียบร้อย" ในเอนทิตีทั้งหมด

    ภาพหน้าจอแสดงแอปยืนยันสำเร็จ
    รูปที่ 1 การสมัครใช้บริการสำเร็จ
  3. แอปยืนยันจะไฮไลต์ปัญหาด้วย

    ภาพหน้าจอแสดงข้อผิดพลาดของแอปยืนยัน
    รูปที่ 2การสมัครใช้บริการไม่สำเร็จ
  4. หากต้องการดูปัญหาในการสมัครใช้บริการแบบรวม ให้ใช้รีโมตทีวีเพื่อโฟกัสที่การสมัครใช้บริการแบบรวมที่เฉพาะเจาะจงนั้น แล้วคลิกเพื่อดูปัญหา คุณอาจต้องโฟกัสที่แถวก่อน แล้วเลื่อนไปทางขวาเพื่อค้นหาการ์ดการสมัครใช้บริการแบบรวม ปัญหาจะไฮไลต์เป็นสีแดงตามที่แสดงในรูปที่ 3 นอกจากนี้ ให้ใช้รีโมตเพื่อเลื่อนลงเพื่อดูปัญหาในการให้สิทธิ์ภายในการสมัครใช้บริการแบบรวม

    ภาพหน้าจอแสดงรายละเอียดข้อผิดพลาดของแอปยืนยัน
    รูปที่ 3ข้อผิดพลาดในการสมัครใช้บริการ
  5. หากต้องการดูปัญหาในการให้สิทธิ์ ให้ใช้รีโมตทีวีเพื่อโฟกัสที่การให้สิทธิ์ที่เฉพาะเจาะจงนั้น แล้วคลิกเพื่อดูปัญหา ปัญหาจะไฮไลต์เป็นสีแดง

    ภาพหน้าจอแสดงข้อผิดพลาดของแอปยืนยัน
    รูปที่ 4รายละเอียดข้อผิดพลาดในการสมัครใช้บริการ