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

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

Kotlin

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

رائع

implementation "androidx.media3:media3-ui:1.3.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 هذه السمات وطرق الإعداد بمزيد من التفاصيل.

بعد تعريف العرض في ملف التنسيق، يمكن البحث عنه في طريقة 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 بجودة أعلى على الأجهزة المتوافقة.
  • إتاحة إخراج آمن عند تشغيل محتوى محمي بموجب إدارة الحقوق الرقمية
  • إمكانية عرض محتوى الفيديو بالدقة الكاملة للشاشة على أجهزة Android TV التي تعمل على تحسين طبقة واجهة المستخدم

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

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

يتضمّن جهاز التحكّم عن بُعد في Android TV لوحة تحكّم في لوحة التحكّم ترسل الأوامر التي تصل كحدث رئيسي في 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 }
)

تجاهُل العناصر القابلة للرسم

يستخدم PlayerView PlayerControlView لعرض عناصر التحكّم في التشغيل وشريط التقدم. يمكن استبدال العناصر القابلة للرسم التي يستخدمها PlayerControlView بعناصر قابلة للرسم تحمل الأسماء نفسها المحددة في تطبيقك. راجِع Javadoc PlayerControlView للحصول على قائمة بعناصر التحكّم القابلة للرسم التي يمكن تجاوزها.

المزيد من التخصيص

عندما يكون التخصيص الذي يتخطى ذلك المذكور أعلاه مطلوبًا، نتوقّع أن ينفّذ مطوّري التطبيقات مكونات واجهة المستخدم الخاصة بهم بدلاً من استخدام تلك التي توفّرها وحدة واجهة المستخدم في Media3.