ערוצים במסך הבית

מסך הבית של Android TV, או פשוט מסך הבית, מספקים ממשק משתמש מציג תוכן מומלץ כטבלה של ערוצים ותוכניות. כל שורה היא ערוץ. ערוץ מכיל כרטיסים לכל תוכנית שזמינה בערוץ:

מסך הבית של הטלוויזיה

במסמך הזה מוסבר איך להוסיף ערוצים ותוכניות למסך הבית, לעדכן תוכן, לטפל בפעולות של משתמשים ולספק את החוויה הטובה ביותר למשתמשים. (כדי להתעמק יותר ב-API, כדאי לנסות את Codelab במסך הבית וצפו בסשן של Android TV בגרסת I/O 2017).

הערה: ערוצי ההמלצות זמינים רק במדינות. Android בגרסה 8.0 (רמת API 26) ואילך. צריך להשתמש בהם כדי לספק המלצות לאפליקציות שפועלות בגרסת Android 8.0 (רמת API 26) ואילך. שפת תרגום לספק המלצות לאפליקציות שפועלות בגרסאות קודמות של Android, האפליקציה שלכם חייב להשתמש שורת ההמלצות במקום זאת.

ממשק המשתמש של מסך הבית

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

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

הערוץ 'במה לצפות עכשיו'

הערוץ 'במה לצפות עכשיו' הוא השורה השנייה שמופיעה במסך הבית, לאחר בשורת האפליקציות. המערכת יוצרת ומתחזקת את הערוץ הזה. האפליקציה שלך יכולה להוסיף בתוכניות 'במה לצפות עכשיו'. מידע נוסף זמין במאמר הוספת תוכניות אל הערוץ 'במה לצפות עכשיו'.

ערוצי אפליקציות

כל הערוצים שהאפליקציה שלכם יוצרת מבוססים על מחזור החיים הבא:

  1. המשתמש מגלה ערוץ באפליקציה ומבקש להוסיף אותו למסך הבית.
  2. האפליקציה יוצרת את הערוץ ומוסיפה אותו ל-TvProvider (בשלב הזה הערוץ לא גלוי).
  3. האפליקציה מבקשת מהמערכת להציג את הערוץ.
  4. המערכת מבקשת מהמשתמש לאשר את הערוץ החדש.
  5. הערוץ החדש יופיע בשורה האחרונה של מסך הבית.

ערוץ ברירת המחדל

האפליקציה יכולה להציע כמה ערוצים שהמשתמש יכול להוסיף למסך הבית. בדרך כלל המשתמש צריך בוחרים ומאשרים כל ערוץ לפני שהוא מופיע במסך הבית. בכל אפליקציה אפשר ליצור ערוץ ברירת מחדל אחד בלבד. ערוץ ברירת המחדל הוא מיוחד כי הוא מופיע באופן אוטומטי במסך הבית. המשתמש לא חייב לבקש את זה במפורש.

דרישות מוקדמות

במסך הבית של Android TV נעשה שימוש בממשקי ה-API מסוג TvProvider של Android כדי לנהל את הערוצים והתוכניות שהאפליקציה יוצרת. כדי לגשת לנתונים של הספק, צריך להוסיף את ההרשאה הבאה למניפסט של האפליקציה:

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />

בעזרת ספריית התמיכה של TvProvider קל יותר להשתמש בספק. מוסיפים אותו ליחסי התלות בקובץ build.gradle:

מגניב

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

implementation("androidx.tvprovider:tvprovider:1.0.0")

כדי לעבוד עם ערוצים ותוכניות, הקפידו לכלול בתוכנית את פעולות הייבוא הבאות של ספריות תמיכה:

Kotlin

import android.support.media.tv.Channel
import android.support.media.tv.TvContractCompat
import android.support.media.tv.ChannelLogoUtils
import android.support.media.tv.PreviewProgram
import android.support.media.tv.WatchNextProgram

Java

import android.support.media.tv.Channel;
import android.support.media.tv.TvContractCompat;
import android.support.media.tv.ChannelLogoUtils;
import android.support.media.tv.PreviewProgram;
import android.support.media.tv.WatchNextProgram;

ערוצים

הערוץ הראשון שהאפליקציה יוצרת הופך לערוץ ברירת המחדל שלה. ערוץ ברירת המחדל יופיע אוטומטית במסך הבית. כל הערוצים האחרים שאתם יוצרים צריכים להיבחר ולאשר למשתמשים לפני שהם יוכלו להופיע במסך הבית.

יצירת ערוץ

האפליקציה צריכה לבקש מהמערכת להציג ערוצים חדשים שנוספו רק כאשר היא פועלת בחזית. הפעולה הזו מונעת מהאפליקציה להציג תיבת דו-שיח עם בקשה לאישור הוספת הערוץ בזמן שהמשתמש מפעיל אפליקציה אחרת. אם תנסו להוסיף ערוץ בזמן שאתם פועלים ברקע, השיטה onActivityResult() של הפעילות תחזיר את קוד הסטטוס RESULT_CANCELED.

כדי ליצור ערוץ, פועלים לפי השלבים הבאים:

  1. יוצרים כלי ליצירת ערוצים ומגדירים את המאפיינים שלו. שימו לב סוג הערוץ חייב להיות TYPE_PREVIEW. הוספת פריטים מאפיינים כנדרש.

    Kotlin

    val builder = Channel.Builder()
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri)
    

    Java

    Channel.Builder builder = new Channel.Builder();
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri);
    
  2. מוסיפים את הערוץ לספק:

    Kotlin

    var channelUri = context.contentResolver.insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues())
    

    Java

    Uri channelUri = context.getContentResolver().insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues());
    
  3. כדי להוסיף תוכניות לערוץ, עליך לשמור את מזהה הערוץ מאוחר יותר. מחלצים את מזהה הערוץ מה-URI המוחזר:

    Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    Java

    long channelId = ContentUris.parseId(channelUri);
    
  4. חובה להוסיף לוגו לערוץ. משתמשים ב-Uri או ב-Bitmap. הלוגו הסמל צריך להיות 80dp x 80dp והוא אטום. מוצגת תחת מסכה מעגלית:

    מסכה של סמל מסך הבית של הטלוויזיה

    Kotlin

    // Choose one or the other
    storeChannelLogo(context: Context, channelId: Long, logoUri: Uri) // also works if logoUri is a URL
    storeChannelLogo(context: Context, channelId: Long, logo: Bitmap)
    

    Java

    // Choose one or the other
    storeChannelLogo(Context context, long channelId, Uri logoUri); // also works if logoUri is a URL
    storeChannelLogo(Context context, long channelId, Bitmap logo);
    
  5. יצירה של ערוץ ברירת המחדל (אופציונלי): בפעם הראשונה שהאפליקציה יוצרת את ערוץ הערוץ, אפשר להפוך אותו ערוץ ברירת המחדל כדי שהוא יופיע בדף הבית. מסך מיד, ללא פעולה מצד המשתמש. ערוצים אחרים שיצרתם. אינן גלויות עד שהמשתמש בוחרת אותן.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    

  6. מגדירים את ערוץ ברירת המחדל לפני פתיחת האפליקציה. אפשר כדי לגרום להתנהגות הזו, מוסיפים BroadcastReceiver שמאזינים הפעולה android.media.tv.action.INITIALIZE_PROGRAMS, שמופיעה במסך הבית שולח לאחר התקנת האפליקציה:
    <receiver
      android:name=".RunOnInstallReceiver"
      android:exported="true">
        <intent-filter>
          <action android:name="android.media.tv.action.INITIALIZE_PROGRAMS" />
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    
    כשמתקינים את האפליקציה ממקור לא ידוע במהלך הפיתוח, אפשר לבדוק את השלב הזה שמפעילה את הכוונה דרך adb, your.package.name מתוך .YourReceiverName הוא האפליקציה שלך BroadcastReceiver:

    adb shell am broadcast -a android.media.tv.action.INITIALIZE_PROGRAMS -n \
        your.package.name/.YourReceiverName
    

    במקרים נדירים, האפליקציה עשויה לקבל את השידור באותו הזמן מפעיל את האפליקציה. מוודאים שהקוד לא מנסה להוסיף את ערוץ ברירת המחדל יותר מפעם אחת.

עדכון ערוץ

עדכון ערוצים דומה מאוד ליצירתם.

כדי להגדיר את המאפיינים שצריך לשנות, צריך להשתמש בפונקציה Channel.Builder אחרת.

משתמשים בContentResolver כדי לעדכן את הערוץ. מזינים את מזהה הערוץ ששמרתם כשהערוץ נוסף לערוץ במקור:

Kotlin

context.contentResolver.update(
        TvContractCompat.buildChannelUri(channelId),
        builder.build().toContentValues(),
        null,
        null
)

Java

context.getContentResolver().update(TvContractCompat.buildChannelUri(channelId),
    builder.build().toContentValues(), null, null);

כדי לעדכן את הלוגו של הערוץ, יש להשתמש ב-storeChannelLogo().

מחיקת ערוץ

Kotlin

context.contentResolver.delete(TvContractCompat.buildChannelUri(channelId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildChannelUri(channelId), null, null);

תוכניות

הוספת תוכניות לערוץ של אפליקציה

יוצרים PreviewProgram.Builder ומגדירים את המאפיינים שלו:

Kotlin

val builder = PreviewProgram.Builder()
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId)

Java

PreviewProgram.Builder builder = new PreviewProgram.Builder();
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId);

אפשר להוסיף עוד מאפיינים בהתאם לסוג התוכנית. (כדי לראות את המאפיינים שזמינות לכל סוג תוכנית, עיינו בטבלאות שבהמשך.)

מכניסים את התוכנה לספק:

Kotlin

var programUri = context.contentResolver.insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
        builder.build().toContentValues())

Java

Uri programUri = context.getContentResolver().insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
      builder.build().toContentValues());

מאחזרים את מזהה התוכנית לשימוש מאוחר יותר:

Kotlin

val programId = ContentUris.parseId(programUri)

Java

long programId = ContentUris.parseId(programUri);

הוספת תוכניות לערוץ 'במה לצפות עכשיו'

כדי להוסיף תוכניות לערוץ 'במה לצפות עכשיו', ראו הוספת תוכניות לצפייה 'הערוץ הבא'.

עדכון תוכנית

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

משתמשים ב-PreviewProgram.Builder כדי להגדיר את המאפיינים שצריך לשנות, לאחר מכן, צריך להתקשר למספר getContentResolver().update כדי לעדכן את התוכנית. ציון מזהה התוכנית ששמרתם כשהתוכנית נוספה במקור:

Kotlin

context.contentResolver.update(
        TvContractCompat.buildPreviewProgramUri(programId),
                builder.build().toContentValues(), null, null
)

Java

context.getContentResolver().update(TvContractCompat.buildPreviewProgramUri(programId),
    builder.build().toContentValues(), null, null);

מחיקת תוכנית

Kotlin

context.contentResolver
        .delete(TvContractCompat.buildPreviewProgramUri(programId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildPreviewProgramUri(programId), null, null);

טיפול בפעולות של משתמשים

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

גילוי ערוצים והוספה שלהם

האפליקציה יכולה לספק רכיב בממשק המשתמש שמאפשר למשתמש לבחור ולהוסיף ערוצים (לדוגמה, לחצן שמבקש להוסיף את הערוץ).

אחרי שהמשתמש מבקש ערוץ ספציפי, מריצים את הקוד הבא כדי לקבל את הרשאת המשתמש להוסיף אותו לממשק המשתמש של מסך הבית:

Kotlin

val intent = Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE)
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId)
try {
  activity.startActivityForResult(intent, 0)
} catch (e: ActivityNotFoundException) {
  // handle error
}

Java

Intent intent = new Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE);
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
try {
   activity.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
  // handle error
}

המערכת מציגה תיבת דו-שיח שמבקשת מהמשתמש לאשר את הערוץ. מטפלים בתוצאה של הבקשה בשיטת onActivityResult של הפעילות (Activity.RESULT_CANCELED או Activity.RESULT_OK).

אירועים במסך הבית של Android TV

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

  • מסך הבית שולח לאפליקציה את נתוני Uri השמורים במאפיין APP_LINK_INTENT_URI של הערוץ כשהמשתמש בוחר את הלוגו של הערוץ. האפליקציה צריכה להפעיל את ממשק המשתמש הראשי שלה או תצוגה שקשורה לערוץ שנבחר.
  • מסך הבית שולח לאפליקציה את נתוני Uri השמורים במאפיין INTENT_URI של התוכנית כשהמשתמש בוחר תוכנית. האפליקציה צריכה להפעיל את התוכן שנבחר.
  • המשתמש יכול לציין שהוא לא מעוניין יותר בתוכנית שרוצים להסיר מממשק המשתמש של מסך הבית. המערכת מסירה את התוכנית מממשק המשתמש ושולחת לאפליקציה שהיא הבעלים של התוכנית Intent (android.media.tv.ACTION_PREVIEW_תוכנית_BROWSABLE_DISABLED או android.media.tv.ACTION_Watch_NEXT_PLAN_BROWSABLE_DISABLED) עם מזהה התוכנית. האפליקציה צריכה להסיר את התוכנה מהספק ולא להכניס אותה שוב.

חשוב ליצור מסנני Intent לכל Uris שמסך הבית שולח עבור אינטראקציות של משתמשים. לדוגמה:

<receiver
   android:name=".WatchNextProgramRemoved"
   android:enabled="true"
   android:exported="true">
   <intent-filter>
       <action android:name="android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
   </intent-filter>
</receiver>

שיטות מומלצות

  • אפליקציות רבות לטלוויזיה מחייבות את המשתמשים להתחבר. במקרה הזה, BroadcastReceiver שמאזינים ל-android.media.tv.action.INITIALIZE_PROGRAMS צריכים להציע תוכן של משתמשים לא מאומתים.לדוגמה, בשלב הראשון האפליקציה יכולה להציג את התוכן הטוב ביותר או את התוכן הפופולרי הנוכחי. אחרי שהמשתמש יתחבר, יכולים להציג תוכן בהתאמה אישית. זאת הזדמנות מצוינת להגדיל את המכירות של האפליקציות לפני שהם מתחברים.
  • כשהאפליקציה לא פועלת בחזית, וצריך לעדכן ערוץ או משתמשים ברכיב JobScheduler כדי לתזמן את העבודה (ראו: תזמון משימות ו-JobService).
  • המערכת יכולה לבטל את הרשאות הספק של האפליקציה אם האפליקציה לא תפעל כהלכה (לדוגמה: שליחת נתונים בלתי פעילים לספק). ודאו אריזת הקוד שניגשים לספק באמצעות תנאי Try-catch שבהם תוכלו לטפל חריגות באבטחה.
  • לפני עדכון תוכניות וערוצים, שליחת שאילתות לספק לגבי הנתונים צריך לעדכן ולהתאים את הנתונים. לדוגמה, אין צורך לעדכן תוכנית שהמשתמש רוצה להסיר מממשק המשתמש. להשתמש במשימה ברקע מוסיפה/מעדכנת את הנתונים לספק אחרי שליחת שאילתה על ולאחר מכן לבקש אישור עבור הערוצים שלך. אפשר להריץ את המשימה הזו מתי האפליקציה מופעלת ובכל זמן שבו האפליקציה צריכה לעדכן את הנתונים שלה.

    Kotlin

    context.contentResolver
      .query(
          TvContractCompat.buildChannelUri(channelId),
              null, null, null, null).use({
                  cursor-> if (cursor != null and cursor.moveToNext()) {
                               val channel = Channel.fromCursor(cursor)
                               if (channel.isBrowsable()) {
                                   //update channel's programs
                               }
                           }
              })
    

    Java

    try (Cursor cursor = context.getContentResolver()
          .query(
              TvContractCompat.buildChannelUri(channelId),
              null,
              null,
              null,
              null)) {
                  if (cursor != null && cursor.moveToNext()) {
                      Channel channel = Channel.fromCursor(cursor);
                      if (channel.isBrowsable()) {
                          //update channel's programs
                      }
                  }
              }
    
  • יש להשתמש ב-Uris ייחודי בכל התמונות (סמלי לוגו, סמלים, תמונות תוכן). חשוב להשתמש ב-URI אחר כשמעדכנים תמונה. כל התמונות נשמרות במטמון. אם לא תשנו את ה-URI כשמשנים את התמונה, התמונה הישנה תמשיך להופיע.

  • חשוב לזכור שתנאי WHERE אינם מותרים, וקריאות לספקים עם תנאי WHERE יגרמו לחריגה באבטחה.

מאפיינים

בקטע הזה מתוארים מאפייני הערוץ והתוכנית בנפרד.

מאפייני הערוץ

צריך לציין את המאפיינים הבאים לכל ערוץ:

מאפיין הערות
סוג מוגדר ל-TYPE_PREVIEW.
DISPLAY_NAME מוגדר לשם הערוץ.
APP_LINK_INTENT_URI כשהמשתמש לוחץ על הלוגו של הערוץ, המערכת שולחת כוונה להתחיל פעילות שכוללת תוכן שרלוונטי לערוץ. מגדירים את המאפיין הזה כ-URI שמשמש במסנן Intent עבור הפעילות הזו.

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

  • INTERNAL_Vendor_ID
  • INTERNAL_provider_DATA
  • INTERNAL_MERCHANT_FLAG1
  • INTERNAL_MERCHANT_FLAG2
  • INTERNAL_MERCHANT_FLAG3
  • INTERNAL_MERCHANT_FLAG4

מאפייני התוכנית

אפשר לעיין בדפים הנפרדים של המאפיינים של כל סוג של תוכנית:

קוד לדוגמה

למידע נוסף על יצירת אפליקציות שמקיימות אינטראקציה עם מסך הבית והוספת ערוצים ותוכניות למסך הבית של Android TV, ראו Codelab של מסך הבית.