تحدّد Jetpack Media3 واجهة Player
التي تحدّد الوظائف الأساسية.
لتشغيل ملفات الفيديو والملفات الصوتية. ExoPlayer
هو طريقة التنفيذ التلقائية.
هذه الواجهة في Media3. ننصح باستخدام ExoPlayer، لأنّه يوفّر
شاملة من الميزات التي تغطي معظم حالات استخدام التشغيل
قابل للتخصيص للتعامل مع أي حالات استخدام إضافية قد تكون لديك. ExoPlayer أيضًا
تجريد تجزئة الأجهزة ونظام التشغيل بحيث تعمل التعليمات البرمجية بشكل متسق
على منظومة Android المتكاملة يشمل ExoPlayer ما يلي:
- دعم قوائم التشغيل
- إتاحة مجموعة متنوعة من البث التدريجي والتكيّفي التنسيقات
- دعم ميزة إدراج الإعلانات من جهة العميل والخادم
- إتاحة التشغيل المحمي بموجب إدارة الحقوق الرقمية (DRM)
تقدّم لك هذه الصفحة بعض الخطوات الأساسية لإنشاء فيديو للحصول على مزيد من التفاصيل، يمكنك التوجه إلى الأدلّة الكاملة حول Media3 ExoPlayer:
الخطوات الأولى
للبدء، أضف تبعية على ExoPlayer وواجهة المستخدم والوحدات الشائعة Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.4.1" implementation "androidx.media3:media3-ui:1.4.1" implementation "androidx.media3:media3-common:1.4.1"
حسب حالة الاستخدام، قد تحتاج أيضًا إلى وحدات إضافية من Media3
مثل exoplayer-dash
لتشغيل مجموعات البث بتنسيق DASH.
تأكَّد من استبدال 1.4.1
بالإصدار الذي تفضّله من
المكتبة. يمكنك الرجوع إلى ملاحظات الإصدار
لرؤية أحدث إصدار.
إنشاء مشغّل وسائط
من خلال Media3، يمكنك إما استخدام التنفيذ المضمّن في Player
الخاصة بك، ExoPlayer
، أو يمكنك إنشاء عملية تنفيذ مخصّصة لك.
إنشاء ExoPlayer
في ما يلي أبسط طريقة لإنشاء مثيل ExoPlayer
:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
يمكنك إنشاء مشغّل الوسائط في طريقة دورة حياة onCreate()
من
Activity
أو Fragment
أو Service
مكان الإقامة
تشمل Builder
مجموعة من خيارات التخصيص التي قد تهمّك، مثل:
setAudioAttributes()
لضبط إمكانية معالجة التركيز على الصوتsetHandleAudioBecomingNoisy()
لضبط سلوك التشغيل عندما يكون جهاز إخراج الصوت غير متصلsetTrackSelector()
لضبط اختيار المقطع الصوتي
يوفر Media3 مكوّن واجهة المستخدم PlayerView
الذي يمكنك تضمينه في
ملف التخطيط. يغلف هذا المكوِّن PlayerControlView
للتشغيل
عناصر التحكّم، وSubtitleView
لعرض الترجمة، وSurface
لعرض الترجمة
الفيديو القادم.
جارٍ تحضير المشغّل
إضافة عناصر الوسائط إلى قائمة تشغيل لـ
التشغيل باستخدام طرق مثل
setMediaItem()
وaddMediaItem()
بعد ذلك، يمكنك الاتصال بالرقم prepare()
وبدء تحميل الوسائط والحصول على الموارد اللازمة.
يجب عدم تنفيذ هذه الخطوات قبل تشغيل التطبيق في المقدّمة. إذا كان
اللاعب في Activity
أو Fragment
، ما يعني أنّ اللاعب في وضع
onStart()
في المستوى 24 من واجهة برمجة التطبيقات والمستويات الأعلى أو onResume()
على مستوى واجهة برمجة التطبيقات 23 والأقل. بالنسبة إلى لاعب في Service
،
يمكنك إعدادها في onCreate()
.
التحكم في المشغّل
بعد تجهيز المشغّل، يمكنك التحكّم في تشغيله من خلال طُرق الاتصال. على المشغِّل، مثل:
play()
وpause()
لبدء التشغيل وإيقافه مؤقتًاseekTo()
لتقديم طلب موضع داخل عنصر الوسائط الحاليseekToNextMediaItem()
وseekToPreviousMediaItem()
للتنقّل في قائمة التشغيل
سيتم تحديث مكونات واجهة المستخدم مثل PlayerView
أو PlayerControlView
وفقًا لذلك عندما تكون مرتبطة بلاعب
حرر المشغّل
قد يتطلّب التشغيل موارد محدودة العرض، مثل فيديو
برامج فك الترميز، لذا من المهم استدعاء الدالة release()
على المشغّل لإخلاء بعض الموارد عند عدم الحاجة إليه.
إذا كان المشغّل في Activity
أو Fragment
، ارفع إصبعك عن المشغّل في
onStop()
في المستوى 24 من واجهة برمجة التطبيقات والمستويات الأعلى أو onPause()
على مستوى واجهة برمجة التطبيقات 23 والأقل. إذا كنت لاعبًا في Service
، يمكنك:
وطرحه في onDestroy()
.
إدارة التشغيل باستخدام جلسة وسائط
على Android، توفّر جلسات الوسائط طريقة موحّدة للتفاعل مع الوسائط واللاعبين خارج حدود العملية. جارٍ ربط جلسة وسائط بالمشغّل تتيح لك الإعلان عن المحتوى الذي تشغّله خارجيًا وإتاحة تشغيله والأوامر من مصادر خارجية، مثل الدمج مع عناصر التحكم في وسائط النظام على الأجهزة الجوّالة والأجهزة الكبيرة أجهزة الشاشة.
لاستخدام جلسات الوسائط، أضف تبعية على وحدة جلسة Media3:
implementation "androidx.media3:media3-session:1.4.1"
إنشاء جلسة وسائط
يمكنك إنشاء MediaSession
بعد إعداد المشغِّل على النحو التالي:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
يزامن Media3 تلقائيًا حالة Player
مع حالة
MediaSession
تعمل هذه الميزة مع أي عملية تنفيذ Player
، بما في ذلك
ExoPlayer
أو CastPlayer
أو
والتنفيذ المخصص.
منح إمكانية التحكم لعملاء آخرين
يمكن لتطبيقات العميل تنفيذ وحدة تحكّم في الوسائط.
للتحكّم في تشغيل جلسة الوسائط. لتلقّي هذه الطلبات، يجب ضبط
الكائن callback عند
في إنشاء MediaSession
.
عندما تكون وحدة التحكم على وشك الاتصال بجلسة الوسائط،
onConnect()
المريض. يمكنك استخدام ControllerInfo
المتوفرة.
لاتخاذ قرار بشأن قبول
أو رفض
الطلب. يمكنك الاطّلاع على مثال على ذلك في تطبيق العرض التوضيحي لجلسة Media3.
بعد اكتمال الاتصال، يمكن لوحدة التحكّم إرسال أوامر التشغيل إلى الجلسة. تشير رسالة الأشكال البيانية
الجلسة ثم يفوض هذه الأوامر إلى اللاعب. التشغيل وقائمة التشغيل
يتم التعامل مع الأوامر المحددة في واجهة Player
تلقائيًا من خلال
جلسة المراجعة.
تتيح لك طرق معاودة الاتصال الأخرى معالجة طلبات
طلبات تشغيل مخصّصة
وتعديل قائمة التشغيل تتضمن عمليات الاستدعاء هذه أيضًا كائن ControllerInfo
، لذا يمكنك
تحديد التحكم في الوصول لكل طلب على حدة.
تشغيل الوسائط في الخلفية
لمواصلة تشغيل الوسائط عندما لا يكون تطبيقك في المقدّمة، مثلاً
لتشغيل الموسيقى أو الكتب المسموعة أو ملفات البودكاست حتى إذا لم يكن التطبيق مثبّتًا على جهاز المستخدم
مفتوح، يجب أن يتم غلاف Player
وMediaSession
في
الخدمة التي تعمل في المقدّمة: توفّر منصة Media3
MediaSessionService
لهذا الغرض.
تنفيذ MediaSessionService
أنشِئ صفًا يمتد إلى MediaSessionService
وأنشِئ مثيلاً لصفك.
MediaSession
في طريقة دورة حياة onCreate()
.
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
في ملف البيان، صف Service
بغرض MediaSessionService
فلترة وطلب إذن "FOREGROUND_SERVICE
" لتشغيل واجهة برمجة تطبيقات
الخدمة:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
وأخيرًا، في الصف الذي أنشأته، عليك إلغاء طريقة onGetSession()
للتحكّم في
وصول العميل إلى جلسة الوسائط. إرجاع MediaSession
لقبول
طلب الربط، أو إرجاع null
لرفض الطلب.
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
جارٍ الاتصال بواجهة المستخدم
بعد أن أصبحت جلسة الوسائط في Service
منفصلة عن Activity
أو
Fragment
حيث تظهر واجهة مستخدم اللاعب، يمكنك استخدام MediaController
للربط
معًا. في طريقة onStart()
من Activity
أو Fragment
مع
واجهة المستخدم، أنشئ SessionToken
لـ MediaSession
، ثم استخدِم SessionToken
.
لإنشاء MediaController
. يتم إنشاء MediaController
بشكل غير متزامن.
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
تنفِّذ MediaController
الواجهة Player
، لذا يمكنك استخدام الواجهة
طرق مثل play()
وpause()
للتحكم في التشغيل. مشابه لعناصر أخرى
المكونات، فتذكر إصدار MediaController
إذا لم تعد
المطلوبة، مثل طريقة دورة حياة onStop()
في Activity
، من خلال استدعاء
MediaController.releaseFuture()
نشر إشعار
يجب السماح للخدمات التي تعمل في المقدّمة لنشر إشعار عندما تكون نشطة. حاسمة
سيقوم MediaSessionService
تلقائيًا بإنشاء
إشعار واحد (MediaStyle
) لـ
في شكل MediaNotification
.
لتقديم إشعار مخصّص، يمكنك إنشاء
MediaNotification.Provider
مع DefaultMediaNotificationProvider.Builder
أو عن طريق إنشاء تنفيذ مخصص لواجهة الموفر. إضافة
مقدِّم الخدمة إلى MediaSession
من خلال
setMediaNotificationProvider
الترويج لمكتبة المحتوى الخاصة بك
تعتمد MediaLibraryService
على MediaSessionService
من خلال السماح للعميل
التطبيقات لتصفّح محتوى الوسائط الذي يوفّره تطبيقك. تنفِّذ تطبيقات العميل
MediaBrowser
للتفاعل
مع MediaLibraryService
.
إنّ تنفيذ MediaLibraryService
يشبه تنفيذ
MediaSessionService
، باستثناء أنّه في onGetSession()
، يجب عرض
MediaLibrarySession
بدلاً من MediaSession
مقارنةً بـ
MediaSession.Callback
، تشتمل السمة MediaLibrarySession.Callback
على
التي تسمح لعميل المتصفح بالتنقل عبر المحتوى الذي يقدمه
خدمة المكتبة.
على غرار MediaSessionService
، يجب الإفصاح عن السمة MediaLibraryService
في
البيان وطلب إذن "FOREGROUND_SERVICE
" لتشغيل واجهة برمجة تطبيقات
الخدمة:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
يتضمّن المثال أعلاه فلتر أهداف لكلٍّ من MediaLibraryService
وللتوافق مع الأنظمة القديمة، يوفّر الإصدار MediaBrowserService
القديم. تشير رسالة الأشكال البيانية
يسمح فلتر الأهداف الإضافي لتطبيقات العميل باستخدام واجهة برمجة التطبيقات MediaBrowserCompat
.
للتعرّف على Service
.
تتيح لك MediaLibrarySession
عرض مكتبة المحتوى بشكل تدرّجي.
بنية ذات جذر واحد MediaItem
. يمكن أن يكون لكل MediaItem
في الشجرة
أي عدد من عُقد MediaItem
الثانوية. يمكنك استخدام جذر مختلف أو
شجرة مختلفة بناءً على طلب التطبيق العميل. على سبيل المثال، الشجرة التي
العودة إلى عميل يبحث عن قائمة بعناصر الوسائط الموصى بها قد يكون
تحتوي على الجذر MediaItem
ومستوى واحد من عُقد MediaItem
الثانوية،
في حين أن الشجرة التي ترجع إليها إلى تطبيق عميل مختلف قد تمثل
مكتبة كاملة من المحتوى.
جارٍ إنشاء MediaLibrarySession
MediaLibrarySession
توسيع واجهة برمجة تطبيقات MediaSession
لإضافة واجهات برمجة تطبيقات لتصفّح المحتوى. بالمقارنة مع
MediaSession
معاودة الاتصال،
معاودة الاتصال MediaLibrarySession
تضيف طرق مثل:
onGetLibraryRoot()
عندما يطلب العميل الجذرMediaItem
من شجرة محتوىonGetChildren()
عندما يطلب العميل العناصر الثانوية لـMediaItem
في شجرة المحتوىonGetSearchResult()
عندما يطلب عميل نتائج بحث من شجرة المحتوى لمحتوى طلب
وستتضمّن طرق معاودة الاتصال ذات الصلة السمة LibraryParams
.
عنصر بإشارات إضافية حول نوع شجرة المحتوى الذي يستخدم تطبيق عميل
المعنية.