מדריך לשילוב של Engage SDK בטלוויזיה

התכונה 'המשך צפייה' משתמשת באשכול ההמשכות כדי להציג סרטונים שלא הושלמו ואת הפרקים הבאים לצפייה מאותה עונת טלוויזיה, ממספר אפליקציות, בקיבוץ אחד בממשק המשתמש. תוכלו להציג את הישויות שלהם באשכול ההמשך הזה. במדריך הזה מוסבר איך לשפר את התעניינות המשתמשים באמצעות התכונה 'המשך הצפייה' באמצעות Engage SDK.

שלב 1: עבודת הכנה

לפני שמתחילים, צריך לבצע את השלבים הבאים:

מוודאים שהאפליקציה מטרגטת לרמת API 19 ואילך בשילוב הזה

  1. מוסיפים את הספרייה com.google.android.engage לאפליקציה:

    יש ערכות SDK נפרדות לשימוש בשילוב: אחת לאפליקציות לנייד ואחת לאפליקציות לטלוויזיה.

    נייד

    
      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 ל-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',‏ 'פרק 2',‏ 's1' או 'עונה 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 אחראי לפרסם את אשכול ההמשך. משתמשים ב-method‏ 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 מסוג upsert, והם מחליפים את התוכן הקיים. אם צריך לעדכן ישות ספציפית ב-ContinuationCluster, צריך לפרסם מחדש את כל הישויות.

צריך לספק נתונים של ContinuationCluster רק לחשבונות למבוגרים. פרסום רק כאשר החשבון שייך למבוגר.

סנכרון בין מכשירים

הדגל SyncAcrossDevices

הדגל הזה קובע אם נתוני ContinuationCluster של המשתמש מסתנכרנים בין המכשירים שלו (טלוויזיה, טלפון, טאבלט וכו'). ברירת המחדל היא false, כלומר הסנכרון בין מכשירים מושבת כברירת מחדל.

ערכים:

  • true: נתוני ContinuationCluster משותפים בין כל המכשירים של המשתמש כדי לספק חוויית צפייה חלקה. אנחנו ממליצים מאוד על האפשרות הזו כדי ליהנות מחוויית השימוש הטובה ביותר במכשירים שונים.
  • false: הנתונים של ContinuationCluster מוגבלים למכשיר הנוכחי.

באפליקציית המדיה צריכה להיות הגדרה ברורה להפעלה או להשבתה של סנכרון בין מכשירים. הסבירו למשתמש את היתרונות, שמרו את ההעדפה של המשתמש פעם אחת והחילו אותה בהתאם ב-publishContinuationCluster.

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

כדי להפיק את המקסימום מהתכונה שלנו לשימוש במכשירים שונים, חשוב לוודא שהאפליקציה מקבלת את הסכמת המשתמשים ולהגדיר את SyncAcrossDevices כ-true. כך אפשר לסנכרן תוכן בצורה חלקה בין מכשירים, וכך לשפר את חוויית המשתמש ולהגדיל את ההתעניינות. לדוגמה, שותף שהטמיע את התכונה הזו ראה עלייה של 40% בקליקים על 'המשך הצפייה', כי התוכן שלו הוצג במספר מכשירים.

מחיקת הנתונים של מודעות וידאו Discovery

כדי למחוק ידנית את נתוני המשתמש מהשרת של Google TV לפני תקופת השמירה הרגילה של 60 יום, משתמשים ב-method‏ 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()
)

בדיקה

אפשר להשתמש באפליקציית האימות כדי לוודא ששילוב ה-SDK של Engage פועל כמו שצריך. האפליקציה ל-Android מספקת כלים שיעזרו לכם לאמת את הנתונים שלכם ולוודא שהטיפול בכוונות השידור מתבצע בצורה תקינה.

אחרי שמפעילים את ה-API לפרסום, צריך לבדוק באפליקציית האימות שהנתונים מתפרסמים בצורה תקינה. אשכולות ההמשך אמורים להופיע בשורה נפרדת בממשק של האפליקציה.

  • מוודאים שהדגל של שירות Engage לא מוגדר לסביבת הייצור בקובץ Android Manifest של האפליקציה.
  • מתקינים את אפליקציית Engage Verify ופותחים אותה.
  • אם הערך של isServiceAvailable הוא false, לוחצים על הלחצן 'החלפת מצב' כדי להפעיל את האפשרות.
  • כדי להציג באופן אוטומטי את הנתונים שפורסמו אחרי שתתחילו לפרסם, מזינים את שם החבילה של האפליקציה.
  • כדאי לבדוק את הפעולות הבאות באפליקציה:
    • מתחברים לחשבון.
    • עוברים בין הפרופילים(אם רלוונטי).
    • להפעיל סרטון ואז להשהות אותו, או לחזור לדף הבית.
    • סוגרים את האפליקציה במהלך הפעלת הסרטון.
    • להסיר פריט מהשורה 'המשך צפייה' (אם התכונה נתמכת).
  • אחרי כל פעולה, צריך לוודא שהאפליקציה הפעילה את ה-API של publishContinuationClusters ושהנתונים מוצגים בצורה נכונה באפליקציית האימות.
  • באפליקציית האימות יוצג סימן וי ירוק לצד ישויות שהוגדרו בצורה תקינה.

    צילום מסך של הצלחה באפליקציית האימות
    איור 1. אישור האימות של האפליקציה הושלם
  • אפליקציית האימות תסמן ישויות בעייתיות.

    צילום מסך של שגיאה באפליקציית האימות
    איור 2. שגיאה באפליקציית האימות
  • כדי לפתור בעיות בישות עם שגיאות, משתמשים בשלט הרחוק של הטלוויזיה כדי לבחור את הישות וללחוץ עליה באפליקציית האימות. הבעיות הספציפיות יוצגו ומודגשות באדום לבדיקה (ראו דוגמה בהמשך).

    פרטי השגיאה באפליקציית האימות
    איור 3. פרטי השגיאה באפליקציית האימות