הוספה של רכיבי ה-UI להפעלה לאפליקציה

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

implementation("androidx.media3:media3-ui:1.5.1")
implementation "androidx.media3:media3-ui:1.5.1"

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

ל-PlayerView יש שיטה setPlayer להצמדה ולניתוק (על ידי העברת null) של מכשירי הנגן.

תצוגת נגן

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

<androidx.media3.ui.PlayerView
    android:id="@+id/player_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:show_buffering="when_playing"
    app:show_shuffle_button="true"/>

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

אחרי שמצהירים על התצוגה בקובץ הפריסה, אפשר לחפש אותה ב-method‏ onCreate של הפעילות:

KotlinJava
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // ...
  playerView = findViewById(R.id.player_view)
}
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ...
  playerView = findViewById(R.id.player_view);
}

אחרי שמפעילים את הנגן, אפשר לצרף אותו לתצוגה באמצעות קריאה ל-setPlayer:

KotlinJava
// Instantiate the player.
val player = ExoPlayer.Builder(context).build()
// Attach player to the view.
playerView.player = player
// Set the media item to be played.
player.setMediaItem(mediaItem)
// Prepare the player.
player.prepare()
// Instantiate the player.
player = new ExoPlayer.Builder(context).build();
// Attach player to the view.
playerView.setPlayer(player);
// Set the media item to be played.
player.setMediaItem(mediaItem);
// Prepare the player.
player.prepare();

בחירת סוג הפלטפורמה

המאפיין surface_type של PlayerView מאפשר להגדיר את סוג הפלטפורמה משמש להפעלת וידאו. בנוסף לערכים spherical_gl_surface_view (שזהו ערך מיוחד להפעלת סרטונים גלובאליים) ו-video_decoder_gl_surface_view (שזהו ערך לעיבוד וידאו באמצעות מעבדי גרפיקה של תוספים), הערכים המותרים הם surface_view,‏ texture_view ו-none. אם התצוגה מיועדת להפעלת אודיו בלבד, כדאי להשתמש ב-none כדי להימנע מהצורך ליצור משטח, כי הפעולה הזו עשויה להיות יקרה.

אם הצפייה היא להפעלה רגילה של סרטון, surface_view או texture_view . ל-SurfaceView יש כמה יתרונות על פני TextureView למשך הפעלת סרטון:

  • הספק נמוך יותר באופן משמעותי צריכה מכשירים.
  • תזמון מדויק יותר של הפריימים, וכתוצאה מכך הפעלה חלקה יותר של הסרטון.
  • תמיכה בפלט וידאו HDR באיכות גבוהה יותר במכשירים מתאימים.
  • תמיכה בפלט מאובטח כשמפעילים תוכן מוגן DRM.
  • היכולת ליצור עיבוד (רנדור) של תוכן וידאו ברזולוציה המלאה של המסך במכשירי Android TV שמגדילים את הרזולוציה של שכבת ממשק המשתמש.

לכן, צריך לתת עדיפות ל-SurfaceView על פני TextureView כשהדבר אפשרי. צריך להשתמש באמצעי התשלום TextureView רק אם SurfaceView לא מתאים לצרכים שלך. אחת למשל, יש צורך באנימציות חלקות או בגלילה של פני השטח של הסרטון לפני Android 7.0 (רמת API 24), כפי שמתואר בהערות הבאות. עבור במקרה כזה, עדיף להשתמש במאפיין TextureView רק כאשר הערך של SDK_INT נמוך יותר מ-24 (Android 7.0) ו-SurfaceView אחרת.

ניווט באמצעות D-pad ב-Android TV

בשלט הרחוק של Android TV יש שלט רחוק בלחצני החיצים (D-pad) ששולח פקודות הגעה כאירוע מרכזי ב-dispatchKeyEvent(KeyEvent) מתוך Activity. האלה צריך לקבל גישה לתצוגת הנגן:

KotlinJava
override fun dispatchKeyEvent(event: KeyEvent?): Boolean{
  return playerView.dispatchKeyEvent(event!!) || super.dispatchKeyEvent(event)
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
  return playerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}

כדי לנווט בהפעלה חשוב לבקש מיקוד בתצוגת הנגן שמדלגים על מודעות ומדלגים על מודעות. כדאי לבקש להתמקד ב-onCreate של ה-Activity:

KotlinJava
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // ...
  playerView.requestFocus()
  // ...
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    playerView.requestFocus();
    // ...
}

אם אתם משתמשים ב-Compose ב-Android TV, תצטרכו להפוך את AndroidView לניתנת לבחירה ולהעביר את האירוע על ידי העברת פרמטר המשתנה ל-AndroidView בהתאם:

AndroidView(
  modifier = modifier
    .focusable()
    .onKeyEvent { playerView.dispatchKeyEvent(it.nativeKeyEvent) },
  factory = { playerView }
)

שינוי של פריטים שניתן להזזה

PlayerView משתמש ב-PlayerControlView כדי להציג את פקדי ההפעלה ואת סרגל ההתקדמות. אפשר לשנות את הגדרות ה-drawables שבהם PlayerControlView משתמש באמצעות drawables עם אותם שמות שהוגדרו באפליקציה. צפייה במסמך Javadoc PlayerControlView לרשימה של פריטים שניתן לצייר עליהם ניתן לשינוי.

התאמה אישית נוספת

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