คำแนะนำในคู่มือนี้จะช่วยให้นักพัฒนาแอปแชร์ข้อมูลการสมัครใช้บริการและการให้สิทธิ์ของแอปกับ Google TV ได้โดยใช้ Engage SDK ผู้ใช้สามารถค้นหาเนื้อหาที่มีสิทธิ์รับชมและช่วยให้ Google TV แสดงคําแนะนําเนื้อหาที่เกี่ยวข้องสูงแก่ผู้ใช้ได้โดยตรงภายในประสบการณ์การใช้งาน Google TV บนทีวี อุปกรณ์เคลื่อนที่ และแท็บเล็ต
สิ่งที่ต้องมีก่อน
คุณต้องเริ่มต้นใช้งานฟีดการดําเนินการกับสื่อก่อนจึงจะใช้ Device Entitlement API ได้ หากยังไม่ได้ดำเนินการ ให้ทําตามกระบวนการเริ่มต้นใช้งานฟีดการกระทํากับสื่อให้เสร็จสมบูรณ์
งานก่อนเริ่มเวิร์กช็อป
ก่อนเริ่มต้น ให้ทำตามขั้นตอนต่อไปนี้ ยืนยันว่าแอปกำหนดเป้าหมายเป็น API ระดับ 19 ขึ้นไปสำหรับการผสานรวมนี้
วิธีเพิ่มคลัง
com.google.android.engage
ลงในแอปมี SDK แยกต่างหากสําหรับการผสานรวม 1 รายการสําหรับแอปบนอุปกรณ์เคลื่อนที่และ 1 รายการสําหรับแอปทีวี
สำหรับอุปกรณ์เคลื่อนที่
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 เป็น "เวอร์ชันที่ใช้งานจริง" ในไฟล์ 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();
การสมัครใช้บริการระดับทั่วไป
สำหรับผู้ใช้ที่สมัครใช้บริการพื้นฐานของผู้ให้บริการสื่อ เช่น บริการที่มีระดับการสมัครใช้บริการ 1 ระดับที่ให้สิทธิ์เข้าถึงเนื้อหาทั้งหมดแบบชำระเงิน ให้ระบุรายละเอียดที่สำคัญต่อไปนี้
ประเภทการสมัครใช้บริการ: ระบุแพ็กเกจการสมัครใช้บริการที่ผู้ใช้มีอยู่อย่างชัดเจน
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();
การสมัครใช้บริการ Premium
หากแอปเสนอแพ็กเกจการสมัครใช้บริการพรีเมียมแบบหลายระดับ ซึ่งรวมถึงเนื้อหาหรือฟีเจอร์ที่ขยายการให้บริการนอกเหนือจากระดับทั่วไป ให้แสดงข้อมูลนี้โดยการเพิ่มการให้สิทธิ์อย่างน้อย 1 รายการในการสมัครใช้บริการ
การให้สิทธิ์นี้มีช่องต่อไปนี้
- ตัวระบุ: สตริงตัวระบุที่ต้องระบุสำหรับการให้สิทธิ์นี้ ข้อมูลนี้ต้องตรงกับตัวระบุการให้สิทธิ์รายการใดรายการหนึ่ง (โปรดทราบว่านี่ไม่ใช่ช่องรหัส) ที่ระบุไว้ในฟีดของผู้ให้บริการสื่อที่เผยแพร่ไปยัง 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()
ซึ่งยอมรับรายการการสมัครใช้บริการที่ลิงก์ไว้ เพื่อให้ผู้ใช้มีการสมัครใช้บริการที่ลิงก์ไว้ตั้งแต่ 0 รายการขึ้นไป
เมื่อบริการได้รับคําขอ ระบบจะสร้างรายการใหม่และลบรายการเก่าโดยอัตโนมัติหลังจากผ่านไป 60 วัน ระบบจะใช้รายการล่าสุดเสมอ ในกรณีที่เกิดข้อผิดพลาด ระบบจะปฏิเสธคำขอทั้งหมดและคงสถานะที่มีอยู่ไว้
อัปเดตการสมัครใช้บริการให้เป็นปัจจุบันอยู่เสมอ
- หากต้องการอัปเดตทันทีเมื่อมีการเปลี่ยนแปลง ให้เรียกใช้
publishSubscriptionCluster()
ทุกครั้งที่สถานะการสมัครใช้บริการของผู้ใช้มีการเปลี่ยนแปลง เช่น การเปิดใช้งาน การปิดใช้งาน การอัปเกรด การดาวน์เกรด โปรดเรียกใช้
publishSubscriptionCluster()
อย่างน้อยเดือนละครั้งเพื่อให้การตรวจสอบความถูกต้องอย่างต่อเนื่องหากต้องการลบข้อมูลการค้นพบวิดีโอ ให้ลบข้อมูลของผู้ใช้ออกจากเซิร์ฟเวอร์ 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() )
การทดสอบ
ส่วนนี้จะแสดงคําแนะนําแบบทีละขั้นตอนสําหรับการทดสอบการติดตั้งใช้งานการติดตาม ตรวจสอบความถูกต้องของข้อมูลและฟังก์ชันการทํางานที่เหมาะสมก่อนเปิดตัว
รายการตรวจสอบการเผยแพร่การผสานรวม
การเผยแพร่ควรเกิดขึ้นเมื่อแอปอยู่ในเบื้องหน้าและผู้ใช้โต้ตอบกับแอปอยู่
เผยแพร่เมื่อ
- ผู้ใช้เข้าสู่ระบบเป็นครั้งแรก
- ผู้ใช้เปลี่ยนโปรไฟล์ (หากระบบรองรับโปรไฟล์)
- ผู้ใช้สมัครใช้บริการใหม่
- ผู้ใช้อัปเกรดการสมัครใช้บริการ
- การสมัครใช้บริการของผู้ใช้หมดอายุ
ตรวจสอบว่าแอปเรียกใช้
isServiceAvailable()
และpublishClusters()
API ใน logcat ของเหตุการณ์การเผยแพร่อย่างถูกต้องหรือไม่ตรวจสอบว่าข้อมูลแสดงอยู่ในแอปการยืนยัน แอปการยืนยันควรแสดงการสมัครใช้บริการเป็นแถวแยกต่างหาก เมื่อเรียกใช้ API เผยแพร่ ข้อมูลควรแสดงในแอปการยืนยัน
- ตรวจสอบว่าFlag บริการ Engage ไม่ได้ตั้งค่าเป็นเวอร์ชันที่ใช้งานจริงในไฟล์ Manifest ของ Android ของแอป
- ติดตั้งและเปิดแอปการยืนยัน Engage
- หากค่าของ
isServiceAvailable
คือfalse
ในแอปการยืนยัน ให้คลิกปุ่มToggle
ภายในแอปการยืนยันเพื่อตั้งค่าเป็นtrue
- ป้อนชื่อแพ็กเกจของแอป ระบบจะแสดงข้อมูลที่เผยแพร่โดยอัตโนมัติ
ไปที่แอปและดำเนินการต่อไปนี้ทีละรายการ
- ลงชื่อเข้าใช้
- สลับระหว่างโปรไฟล์ (หากรองรับ)
- ซื้อการสมัครใช้บริการใหม่
- อัปเกรดการสมัครใช้บริการที่มีอยู่
- การสมัครใช้บริการหมดอายุ
ยืนยันการผสานรวม
หากต้องการทดสอบการผสานรวม ให้ใช้แอปการยืนยัน
แอปการยืนยันเป็นแอปพลิเคชัน Android ที่นักพัฒนาแอปสามารถใช้เพื่อยืนยันว่าการผสานรวมทํางาน แอปมีความสามารถในการช่วยนักพัฒนาแอปยืนยันข้อมูลและเจตนาออกอากาศ ซึ่งช่วยยืนยันความถูกต้องของข้อมูลและฟังก์ชันการทำงานที่เหมาะสมก่อนการเปิดตัว
- สําหรับแต่ละเหตุการณ์ ให้ตรวจสอบว่าแอปเรียกใช้
publishSubscription
API หรือไม่ ยืนยันข้อมูลที่เผยแพร่ในแอปการยืนยัน ตรวจสอบว่าทุกอย่างเป็นสีเขียวในแอปการยืนยัน หากข้อมูลทั้งหมดของเอนทิตีถูกต้อง ระบบจะแสดงเครื่องหมายถูกสีเขียว "เรียบร้อยดี" ในทุกเอนทิตี
รูปที่ 1 สมัครใช้บริการสำเร็จ ระบบจะไฮไลต์ปัญหาในแอปการยืนยันด้วย
รูปที่ 2. การสมัครใช้บริการไม่สำเร็จ หากต้องการดูปัญหาในการสมัครใช้บริการแบบแพ็กเกจ ให้ใช้รีโมตทีวีเพื่อโฟกัสไปที่การสมัครใช้บริการแบบแพ็กเกจที่ต้องการ แล้วคลิกเพื่อดูปัญหา คุณอาจต้องโฟกัสที่แถวแล้วเลื่อนไปทางขวาเพื่อค้นหาการ์ดการสมัครใช้บริการแบบแพ็กเกจ ระบบจะไฮไลต์ปัญหาเป็นสีแดงดังที่แสดงในรูปที่ 3 นอกจากนี้ ให้ใช้รีโมตเลื่อนลงเพื่อดูปัญหาเกี่ยวกับสิทธิ์ในการรับชมภายในการสมัครใช้บริการแบบแพ็กเกจ
รูปที่ 3. ข้อผิดพลาดในการสมัครใช้บริการ หากต้องการดูปัญหาในการให้สิทธิ์ ให้ใช้รีโมตทีวีเพื่อโฟกัสที่การให้สิทธิ์ที่เฉพาะเจาะจงนั้น แล้วคลิกเพื่อดูปัญหา ระบบจะไฮไลต์ปัญหาเป็นสีแดง
รูปที่ 4.รายละเอียดข้อผิดพลาดในการสมัครใช้บริการ