إضافة عناصر التحكّم في التشغيل إلى تطبيقك

يتطلب التطبيق الذي يشغّل الوسائط مكوّنات لواجهة المستخدم لعرض الوسائط والتحكّم في التشغيل. تتضمّن مكتبة Media3 وحدة واجهة مستخدم تحتوي على عدد من مكونات واجهة المستخدم. للاعتماد على وحدة واجهة المستخدم، أضِف التبعية التالية:

Kotlin

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

Groovy

implementation "androidx.media3:media3-ui:1.5.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 يوفّر عدة سمات. يمكن استخدام هذه السمات لتخصيص سلوك العرض، بالإضافة إلى مظهره وأسلوبه. تحتوي معظم هذه السمات على طرق ضبط مقابلة، والتي يمكن استخدامها لتخصيص طريقة العرض أثناء التشغيل. يسرد مستند PlayerView هذه السمات وطُرق الإعدادات بمزيد من التفصيل.

بعد الإعلان عن طريقة العرض في ملف التنسيق، يمكن البحث عنها في 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 في ما يتعلّق بتشغيل الفيديو:

  • انخفاض استهلاك الطاقة بشكل كبير على العديد من الأجهزة
  • توقيت أكثر دقة للّقطات، ما يؤدي إلى تشغيل الفيديو بسلاسة أكبر
  • إتاحة إخراج فيديو بنطاق عالي الديناميكية بجودة أعلى على الأجهزة المتوافقة
  • إتاحة إخراج آمن عند تشغيل محتوى محمي بموجب إدارة الحقوق الرقمية
  • إمكانية عرض محتوى الفيديو بالدقة الكاملة للشاشة على أجهزة Android TV التي تُحسِّن طبقة واجهة المستخدم

لذلك، يجب تفضيل SurfaceView على TextureView كلما أمكن. يجب عدم استخدام TextureView إلا إذا لم تكن SurfaceView تستوفي احتياجاتك. أحد مثالي هذه الحالات هو عندما تكون الرسومات المتحركة أو الانتقال السلس لسطح الفيديو مطلوبًا قبل Android 7.0 (مستوى واجهة برمجة التطبيقات 24)، كما هو موضّح في الملاحظات التالية. في هذه الحالة، يُفضَّل استخدام TextureView فقط عندما يكون SDK_INT أقل من 24 (Android 7.0) وSurfaceView في الحالات الأخرى.

التنقّل باستخدام لوحة التوجيه على Android TV

يحتوي جهاز التحكّم عن بُعد في Android TV على وحدة تحكّم باتجاهات D تُرسِل أوامر تُرسَل على أنّها حدث رئيسي في 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();
    // ...
}

إذا كنت تستخدم ميزة "الإنشاء" على Android TV، عليك جعل AndroidView قابلاً للتركيز وتفويض الحدث من خلال تمرير مَعلمة المُعدِّل إلى AndroidView وفقًا لما يلي:

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