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

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

Kotlin

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

Groovy

implementation "androidx.media3:media3-ui:1.4.1"

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

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

PlayerView

אפשר להשתמש ב-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 תואמות, שאפשר להשתמש בהן כדי להתאים אישית את התצוגה בזמן הריצה. המאפיינים ושיטות ההגדרה (setter) האלה מפורטים בפירוט רב יותר ב-Javadoc של PlayerView.

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

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // ...
  playerView = findViewById(R.id.player_view)
}

Java

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

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

Kotlin

// 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()

Java

// 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 ב-Android TV

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

Kotlin

override fun dispatchKeyEvent(event: KeyEvent?): Boolean{
  return playerView.dispatchKeyEvent(event!!) || super.dispatchKeyEvent(event)
}

Java

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
  return playerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}

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

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  // ...
  playerView.requestFocus()
  // ...
}

Java

@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 מופיעה רשימה של רכיבי 'control drawable' שאפשר לשנות.

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

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