คู่มือการผสานรวม Engage SDK สําหรับทีวี

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

ขั้นตอนที่ 1: เตรียมการ

ก่อนเริ่มต้น ให้ทำตามขั้นตอนต่อไปนี้

ตรวจสอบว่าแอปกำหนดเป้าหมายเป็น API ระดับ 19 ขึ้นไปสำหรับการผสานรวมนี้

  1. วิธีเพิ่มคลัง 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
      }
    
  2. ตั้งค่าสภาพแวดล้อมบริการ Engage เป็นเวอร์ชันที่ใช้งานจริงในไฟล์ AndroidManifest.xml

    อุปกรณ์เคลื่อนที่

    
    <meta-data
          android:name="com.google.android.engage.service.ENV"
          android:value="PRODUCTION">
    </meta-data>
    

    ทีวี

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. เพิ่มสิทธิ์สำหรับ WRITE_EPG_DATA สำหรับ tv apk

      <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
    
  4. ตรวจสอบการเผยแพร่เนื้อหาที่เชื่อถือได้โดยใช้บริการที่ทำงานอยู่เบื้องหลัง เช่น androidx.work เพื่อกำหนดเวลา

  5. เผยแพร่ข้อมูลการดูต่อเมื่อเกิดเหตุการณ์ต่อไปนี้เพื่อให้ผู้ใช้ได้รับประสบการณ์การรับชมที่ราบรื่น

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

การรวมระบบ

AccountProfile

ระบุข้อมูลบัญชีและโปรไฟล์เพื่อรับประสบการณ์ "รับชมต่อ" ที่ปรับเปลี่ยนในแบบของคุณบน Google TV ใช้ AccountProfile เพื่อระบุข้อมูลต่อไปนี้

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

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

// If your app only supports account
val accountProfile = AccountProfile.Builder()
      .setAccountId("your_users_account_id")
      .build()
// If your app supports both account and profile
val accountProfile = AccountProfile.Builder()
      .setAccountId("your_users_account_id")
      .setProfileId("your_users_profile_id")
.build()

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

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 พิกเซลเพื่อให้การแสดงเอนทิตี "รับชมต่อ" ถูกต้อง โดยเฉพาะในพื้นที่บันเทิงของ Google รูปภาพที่มีความสูงน้อยกว่า 200 พิกเซลอาจไม่แสดง


Image image1 = new Image.Builder()
            .setImageUri(Uri.parse("http://www.example.com/entity_image1.png");)
            .setImageHeightInPixel(300)
            .setImageWidthInPixel(169)
            .build()
Image image2 = new Image.Builder()
            .setImageUri(Uri.parse("http://www.example.com/entity_image2.png");)
            .setImageHeightInPixel(640)
            .setImageWidthInPixel(360)
            .build()
// And other images for different form factors.
val images = Arrays.asList(image1, image2)
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 = new 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 มีหน้าที่รับผิดชอบในการเผยแพร่คลัสเตอร์การดําเนินการต่อ คุณใช้เมธอด publishContinuationCluster() เพื่อเผยแพร่ออบเจ็กต์ ContinuationCluster

ก่อนอื่น คุณควรใช้ isServiceAvailable() เพื่อตรวจสอบว่าบริการพร้อมสำหรับการผสานรวมหรือไม่

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 การเพิ่มรายการใหม่ ซึ่งจะแทนที่เนื้อหาที่มีอยู่ หากต้องการอัปเดตเอนทิตีที่เฉพาะเจาะจงใน ContinuationCluster คุณจะต้องเผยแพร่เอนทิตีทั้งหมดอีกครั้ง

คุณควรระบุข้อมูล ContinuationCluster สำหรับบัญชีผู้ใหญ่เท่านั้น เผยแพร่เฉพาะเมื่อ AccountProfile เป็นของผู้ใหญ่

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

Flag SyncAcrossDevices

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

ค่า:

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

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

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

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

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

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

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


// 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(
  new DeleteClustersRequest.Builder()
        .setAccountProfile(AccountProfile())
        .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
        .setSyncAcrossDevices(true)
        .build()
)

การทดสอบ

ใช้แอปการยืนยันเพื่อให้แน่ใจว่าการผสานรวม Engage SDK ทํางานอย่างถูกต้อง แอปพลิเคชัน Android นี้มีเครื่องมือที่จะช่วยคุณยืนยันข้อมูลและยืนยันว่ามีการจัดการ Intent ของประกาศอย่างถูกต้อง

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

  • ตรวจสอบว่าFlag บริการ Engage ไม่ได้ตั้งค่าเป็นเวอร์ชันที่ใช้งานจริงในไฟล์ Android Manifest ของแอป
  • ติดตั้งและเปิดแอป Engage Verify
  • หาก isServiceAvailable คือ false ให้คลิกปุ่ม "เปิด/ปิด" เพื่อเปิดใช้
  • ป้อนชื่อแพ็กเกจของแอปเพื่อดูข้อมูลที่เผยแพร่โดยอัตโนมัติเมื่อคุณเริ่มเผยแพร่
  • ทดสอบการดําเนินการต่อไปนี้ในแอป
    • ลงชื่อเข้าใช้
    • สลับระหว่างโปรไฟล์(หากมี)
    • เริ่มเล่นวิดีโอแล้วหยุดชั่วคราว หรือกลับไปที่หน้าแรก
    • ปิดแอประหว่างที่เล่นวิดีโอ
    • นำรายการออกจากแถว "รับชมต่อ" (หากรองรับ)
  • หลังจากดำเนินการแต่ละครั้ง ให้ตรวจสอบว่าแอปเรียกใช้ API ของ publishContinuationClusters และข้อมูลแสดงในแอปการยืนยันอย่างถูกต้อง
  • แอปการยืนยันจะแสดงเครื่องหมายถูกสีเขียว "เรียบร้อยดี" สำหรับเอนทิตีที่ติดตั้งใช้งานอย่างถูกต้อง

    ภาพหน้าจอแสดงการยืนยันแอปสำเร็จ
    รูปที่ 1 การตรวจสอบแอปเพื่อความสำเร็จ
  • แอปการยืนยันจะแจ้งให้ทราบถึงรายการที่มีปัญหา

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

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