ผสานรวมฟีเจอร์ดูต่อใน Android TV

book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml

คู่มือนี้ครอบคลุมวิธีผสานรวมฟีเจอร์ "ดูต่อ" เข้ากับแอป Android TV โดยใช้ Engage SDK

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

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

การรวมระบบ

สร้างเอนทิตี

SDK ได้กำหนดเอนทิตีต่างๆ เพื่อแสดงรายการแต่ละประเภท คลัสเตอร์ความต่อเนื่องจะรองรับเอนทิตีต่อไปนี้

  1. MovieEntity
  2. TvEpisodeEntity
  3. LiveStreamingVideoEntity
  4. VideoClipEntity

ระบุ URI เฉพาะแพลตฟอร์มและภาพโปสเตอร์สำหรับเอนทิตีเหล่านี้

นอกจากนี้หากยังไม่ได้สร้าง ก็ให้สร้าง URI การเล่นสําหรับแต่ละแพลตฟอร์ม เช่น Android TV, Android หรือ iOS เพื่อให้เมื่อผู้ใช้รับชมต่อในแต่ละแพลตฟอร์ม แอปจะได้ใช้ URI การเล่นที่กำหนดเป้าหมายในการเล่นเนื้อหาวิดีโอ

// Required. Set this when you want continue watching entities to show up on
// Google TV
val playbackUriTv = PlatformSpecificUri.Builder()
    .setPlatformType(PlatformType.TYPE_ANDROID_TV)
    .setActionUri(Uri.parse("https://www.example.com/entity_uri_for_tv"))
    .build()

// Required. Set this when you want continue watching entities to show up on
// Google TV Android app, Entertainment Space, Playstore Widget
val playbackUriAndroid = PlatformSpecificUri.Builder()
    .setPlatformType(PlatformType.TYPE_ANDROID_MOBILE)
    .setActionUri(Uri.parse("https://www.example.com/entity_uri_for_android"))
    .build()

// Optional. Set this when you want continue watching entities to show up on
// Google TV iOS app
val playbackUriIos = PlatformSpecificUri.Builder()
    .setPlatformType(PlatformType.TYPE_IOS)
    .setActionUri(Uri.parse("https://www.example.com/entity_uri_for_ios"))
    .build()

val platformSpecificPlaybackUris =
    Arrays.asList(playbackUriTv, playbackUriAndroid, playbackUriIos)

ภาพโปสเตอร์ต้องมี URI และขนาดพิกเซล (ความสูงและความกว้าง) โปรดกำหนดเป้าหมายรูปแบบของอุปกรณ์หลายๆ แบบ โดยจัดให้มีภาพโปสเตอร์หลายภาพ และตรวจสอบว่าภาพทั้งหมดมีสัดส่วนการแสดงผล 16:9 และมีความสูงอย่างน้อย 200 พิกเซล เพื่อให้แสดงผลเอนทิตี "รับชมต่อ" ได้อย่างถูกต้องโดยเฉพาะภายใน Entertainment Space ของ Google ทั้งนี้ระบบอาจไม่แสดงรูปภาพที่มีความสูงน้อยกว่า 200 พิกเซล

val images = Arrays.asList(
    Image.Builder()
        .setImageUri(Uri.parse("http://www.example.com/entity_image1.png"))
        .setImageHeightInPixel(300)
        .setImageWidthInPixel(169)
        .build(),
    Image.Builder()
        .setImageUri(Uri.parse("http://www.example.com/entity_image2.png"))
        .setImageHeightInPixel(640)
        .setImageWidthInPixel(360)
        .build()
    // Consider adding other images for different form factors
)

MovieEntity

ตัวอย่างนี้แสดงวิธีสร้าง MovieEntity โดยมีฟิลด์ที่ต้องระบุทั้งหมด

val movieEntity = MovieEntity.Builder()
   .setWatchNextType(WatchNextType.TYPE_CONTINUE)
   .setName("Movie name")
   .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
   .addPosterImages(images)
   // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
   .setLastEngagementTimeMillis(1701388800000)
   // Suppose the duration is 2 hours, it is 72000000 in milliseconds
   .setDurationMills(72000000)
   // Suppose last playback offset is 1 hour, 36000000 in milliseconds
   .setLastPlayBackPositionTimeMillis(36000000)
   .build()

การระบุรายละเอียด เช่น ประเภทและการจัดประเภทเนื้อหา จะช่วยให้ Google TV สามารถแสดงเนื้อหาของคุณในรูปแบบที่ไดนามิกมากขึ้นและเชื่อมต่อเนื้อหากับผู้ชมที่เหมาะสม

val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val movieEntity = MovieEntity.Builder()
    ...
    .addGenres(genres)
    .addContentRatings(contentRatings)
    .build()

เอนทิตีจะยังคงพร้อมใช้งานโดยอัตโนมัติเป็นเวลา 60 วัน เว้นแต่คุณจะระบุเวลาหมดอายุที่สั้นกว่า โดยให้ตั้งค่าการหมดอายุที่กำหนดเองเฉพาะในกรณีที่คุณต้องการนำเอนทิตีออกก่อนระยะเวลาเริ่มต้นนี้

// Set the expiration time to be now plus 30 days in milliseconds
val expirationTime = DisplayTimeWindow.Builder()
    .setEndTimestampMillis(now().toMillis()+2592000000).build()
val movieEntity = MovieEntity.Builder()
    ...
    .addAvailabilityTimeWindow(expirationTime)
    .build()

TvEpisodeEntity

ตัวอย่างนี้แสดงวิธีสร้าง TvEpisodeEntity โดยมีฟิลด์ที่ต้องระบุทั้งหมด

val tvEpisodeEntity = TvEpisodeEntity.Builder()
    .setWatchNextType(WatchNextType.TYPE_CONTINUE)
    .setName("Episode name")
    .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
    .addPosterImages(images)
    // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
    .setLastEngagementTimeMillis(1701388800000)
    .setDurationMills(72000000) // 2 hours in milliseconds
    // 45 minutes and 15 seconds in milliseconds is 2715000
    .setLastPlayBackPositionTimeMillis(2715000)
    .setEpisodeNumber("2")
    .setSeasonNumber("1")
    .setShowTitle("Title of the show")
    .build()

ระบบจะขยายสตริงหมายเลขตอน (เช่น "2") และสตริงหมายเลขซีซัน (เช่น "1") เป็นรูปแบบที่เหมาะสมก่อนที่จะแสดงบนการ์ดรับชมต่อ โปรดทราบว่าสตริงควรเป็นตัวเลข อย่าใส่ "e2" หรือ "episode 2" หรือ "s1" หรือ "season 1"

หากรายการทีวีมีเพียงซีซันเดียว ให้ตั้งหมายเลขซีซันเป็น 1

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

val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val tvEpisodeEntity = TvEpisodeEntity.Builder()
    ...
    .addGenres(genres)
    .addContentRatings(contentRatings)
    .setSeasonTitle("Season Title")
    .setShowTitle("Show Title")
    .build()

VideoClipEntity

ต่อไปนี้เป็นตัวอย่างการสร้าง VideoClipEntity โดยมีฟิลด์ที่ต้องระบุทั้งหมด

VideoClipEntity แสดงถึงคลิปที่ผู้ใช้สร้างขึ้น เช่น วิดีโอ YouTube

val videoClipEntity = VideoClipEntity.Builder()
    .setPlaybackUri(Uri.parse("https://www.example.com/uri_for_current_platform"))
    .setWatchNextType(WatchNextType.TYPE_CONTINUE)
    .setName("Video clip name")
    .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
    .addPosterImages(images)
    // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
    .setLastEngagementTimeMillis(1701388800000)
    .setDurationMills(600000) //10 minutes in milliseconds
    .setLastPlayBackPositionTimeMillis(300000) //5 minutes in milliseconds
    .addContentRating(contentRating)
    .build()

คุณเลือกตั้งค่าครีเอเตอร์ รูปของครีเอเตอร์ เวลาที่สร้างเป็นมิลลิวินาที หรือกรอบเวลาที่พร้อมให้บริการได้

LiveStreamingVideoEntity

ต่อไปนี้เป็นตัวอย่างการสร้าง LiveStreamingVideoEntity โดยมีฟิลด์ที่ต้องระบุทั้งหมด

val liveStreamingVideoEntity = LiveStreamingVideoEntity.Builder()
    .setPlaybackUri(Uri.parse("https://www.example.com/uri_for_current_platform"))
    .setWatchNextType(WatchNextType.TYPE_CONTINUE)
    .setName("Live streaming name")
    .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
    .addPosterImages(images)
    // Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
    .setLastEngagementTimeMillis(1701388800000)
    .setDurationMills(72000000) //2 hours in milliseconds
    .setLastPlayBackPositionTimeMillis(36000000) //1 hour in milliseconds
    .addContentRating(contentRating)
    .build()

คุณเลือกตั้งเวลาเริ่มต้น ผู้ออกอากาศ ไอคอนผู้ออกอากาศ หรือกรอบเวลาที่พร้อมให้บริการสำหรับเอนทิตีการไลฟ์สดได้

ดูข้อมูลโดยละเอียดเกี่ยวกับแอตทริบิวต์และข้อกำหนดได้ที่ข้อมูลอ้างอิง API

ระบุข้อมูลคลัสเตอร์ความต่อเนื่อง

AppEngagePublishClient มีหน้าที่เผยแพร่คลัสเตอร์ความต่อเนื่อง คุณจะใช้เมธอด publishContinuationCluste เพื่อเผยแพร่ออบเจ็กต์ ContinuationCluster

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

client.publishContinuationCluster(
    PublishContinuationClusterRequest
        .Builder()
        .setContinuationCluster(
            ContinuationCluster.Builder()
                .setAccountProfile(accountProfile)
                .addEntity(movieEntity1)
                .addEntity(movieEntity2)
                .addEntity(tvEpisodeEntity1)
                .addEntity(tvEpisodeEntity2)
                .setSyncAcrossDevices(true)
                .build()
        )
        .build()
)

เมื่อบริการได้รับคำขอ ระบบจะดำเนินการต่อไปนี้ภายในธุรกรรมเดียว

  • ระบบจะนำข้อมูล ContinuationCluster ที่มีอยู่จากพาร์ทเนอร์นักพัฒนาออก
  • ระบบจะแยกวิเคราะห์และจัดเก็บข้อมูลจากคำขอใน ContinuationCluster ที่อัปเดต

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

API การเผยแพร่เป็น API การแทรก/อัปเดต ซึ่งจะแทนที่เนื้อหาที่มีอยู่ หากต้องการอัปเดตเอนทิตีที่เฉพาะเจาะจงในคลัสเตอร์การติดตาม คุณจะต้องเผยแพร่เอนทิตีทั้งหมดอีกครั้ง

ควรระบุข้อมูลคลัสเตอร์ความต่อเนื่องสำหรับบัญชีของผู้ใหญ่เท่านั้น เผยแพร่ เมื่อโปรไฟล์บัญชีเป็นของผู้ใหญ่เท่านั้น

การซิงค์ข้ามอุปกรณ์

SyncAcrossDevices Flag ควบคุมว่าระบบจะซิงค์ข้อมูล ContinuationCluster ของผู้ใช้ในอุปกรณ์ต่างๆ เช่น ทีวี โทรศัพท์ แท็บเล็ต ฯลฯ หรือไม่ การซิงค์ข้ามอุปกรณ์จะปิดใช้โดยค่าเริ่มต้น

ค่า:

  • true: ระบบจะแชร์ข้อมูลคลัสเตอร์การดูต่อเนื่องในอุปกรณ์ทั้งหมดของผู้ใช้เพื่อให้ประสบการณ์การรับชมราบรื่น เราขอแนะนำให้ใช้ตัวเลือกนี้เพื่อประสบการณ์การใช้งานข้ามอุปกรณ์ที่ดีที่สุด
  • false: ข้อมูลคลัสเตอร์ความต่อเนื่องจะจำกัดไว้ในอุปกรณ์ปัจจุบัน

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

// Example to allow cross device syncing.
client.publishContinuationCluster(
    PublishContinuationClusterRequest
        .Builder()
        .setContinuationCluster(
            ContinuationCluster.Builder()
                .setAccountProfile(accountProfile)
                .setSyncAcrossDevices(true)
                .build()
        )
        .build()
)

หากต้องการใช้ฟีเจอร์ข้ามอุปกรณ์ให้เกิดประโยชน์สูงสุด โปรดยืนยันว่าแอปได้รับความยินยอมจากผู้ใช้และเปิดใช้ SyncAcrossDevices เป็น true ซึ่งจะช่วยให้เนื้อหาสามารถซิงค์ในอุปกรณ์ต่างๆ ได้อย่างราบรื่น ส่งผลให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีขึ้นและมีส่วนร่วมมากขึ้น ตัวอย่างเช่น พาร์ทเนอร์ที่ใช้ฟีเจอร์นี้มีการคลิก "รับชมต่อ" เพิ่มขึ้น 40% เนื่องจากระบบแสดงเนื้อหาในอุปกรณ์หลายเครื่อง

ลบข้อมูลการค้นพบวิดีโอ

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

DeleteReason Enum จะกำหนดเหตุผลในการลบข้อมูล โค้ดต่อไปนี้จะนำข้อมูลการรับชมต่อออกเมื่อออกจากระบบ


// If the user logs out from your media app, you must make the following call
// to remove continue watching data from the current google TV device,
// otherwise, the continue watching data will persist on the current
// google TV device until 60 days later.
client.deleteClusters(
    DeleteClustersRequest.Builder()
        .setAccountProfile(AccountProfile())
        .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
        .setSyncAcrossDevices(true)
        .build()
)

การทดสอบ

ใช้แอปยืนยันเพื่อยืนยันว่าการผสานรวม Engage SDK ทำงานอย่างถูกต้อง

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

  • ทดสอบการดำเนินการต่อไปนี้ในแอป
    • ลงชื่อเข้าใช้
    • สลับระหว่างโปรไฟล์ (หากมี)
    • เริ่มเล่น จากนั้นหยุดวิดีโอชั่วคราว หรือกลับไปที่หน้าแรก
    • ปิดแอปขณะเล่นวิดีโอ
    • นำรายการออกจากแถว "รับชมต่อ" (หากระบบรองรับ)
  • หลังจากดำเนินการแต่ละอย่างแล้ว ให้ยืนยันว่าแอปของคุณเรียกใช้ publishContinuationClusters API และข้อมูลแสดงอย่างถูกต้อง ในแอปยืนยัน
  • แอปยืนยันจะแสดงเครื่องหมายถูกสีเขียว "เรียบร้อย" สำหรับเอนทิตีที่ติดตั้งใช้งานอย่างถูกต้อง

    ภาพหน้าจอแสดงแอปยืนยันสำเร็จ
    รูปที่ 1 แอปยืนยันสำเร็จ
  • แอปยืนยันจะแจ้งเอนทิตีที่มีปัญหา

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

    รายละเอียดข้อผิดพลาดของแอปยืนยัน
    รูปที่ 3 รายละเอียดข้อผิดพลาดของแอปยืนยัน