ما هو ExoPlayer?
هي مكتبة مشغل وسائط مفتوحة المصدر بديل ل MediaPlayer
, يوفر بديل لتشغل ملفات الفيديو والصوتيات المحلية والمتوفرة عبر الانترنت .
على عكس الMediaPlayer
الذي هو مكتبة على مستوى النظام الامر الذي يجعل التحديثات الجديدة تتطلب تحديث كامل لنسخة النظام, فان ExoPlayer
هو مكتبة منفصلة يمكن تحميل التحديثات عن طريق المتجر.
وامر اخر يجعلك تريد ان تستخدم ExoPlayer
هو انه يدعم مجموعة كبيرة الاجهزة بمختلف النسخ على عكس MediaPlayer
حيث يمكن لاي شخص تعديل السورس كود واضافتها للهاتف مما يزيد من مشاكل التطبيق المستقبلية وصعوبة حلها
يوفر ExoPlayer
خواص اضافة ايضا ليست موجود في MediaPlayer
مثل:
- قوائم التشغيل playlist
- دعم الكثير من الهواتف
- دعم ادارة الحقوق الرقمية DRM
- DASH
- RTSP
- استرجاع معلومات عن ملف الوسائط Metadata
- SmoothStreaming
- اضافة ملف ترجمة
- HLS
- اضافة اعلانات , مثل اعلانات يوتيوب في نسخة الهواتف
-
تحويل الوسائط مثل:
- تغير صيغة ملف الوسائط مثل من mp3 الى wav
- مسح المسارات: مثل مسح الصوت من فيديو او العكس
بعد هذه المقدمة البسيط يمكن ان نبدا استخدام المكتبة في مثال.
كيف اضيف المكتبة الى مشروعي؟
يمكن اضافة المكتبة بطريقتين:
- اضافة المكتبة كاملة بجميع الخواص كمكتبة كاملة
- اضافة المكتبة التى الدوال الاساسية core ثم بعد ذلك اضافة الخواص كل على حدة
لتبسيط الامر سوف نستخدم الطريق ١ , يمكنك قراءة المزيد من هنا
قم باضافة هذا السطر الى build.gradle
implementation 'com.google.android.exoplayer:exoplayer:2٫+'
قم بالتاكد من استخدام اخر نسخة.
مثال
سوف اقوم ببناء تطبيق صغير يعمل على تشغيل عدة سور من القران
البيانات موجودة على وسور القران موجودة على
لن اقوم باظهار اي كود ليس له علاقة ب exoplayer, الكود متوفر على github اذا اردت المزيد من التفاصيل
نبدا بتعريف متغيرالمشغل
private lateinit var player: ExoPlayer
بعدها نقوم بتعريف المتغير
player = createExoPlayerInstance()
private fun createExoPlayerInstance(): SimpleExoPlayer {
return SimpleExoPlayer.Builder(this)
.build()
}
باستخدام SimpleExoPlayer
فاننا لن نحتاج الى تعريف عدة خواص لانه هذا الكلاس مصمم لاغلب انواع الاستخدامات وكل الخواص تاتي بشكل افتراضي
الان سوف نقوم باضافة قائمة التشغيل
private fun createPlaylist() {
val playlist = surahList.map { surah ->
MediaItem.Builder()
.setUri(surah.audio)
.setTag(surah)
.build()
}
player.addMediaItems(playlist)
player.prepare()
}
سوف اشرح هذا الجزء بالتفصيل:
اول نقوم بعمل map
للبيانات وتحويلها الى كائن من نوع MediaItem
val playlist = surahList.map { surah ->
MediaItem.Builder()
.setUri(surah.audio)
.setTag(surah)
.build()
}
نقوم باضافتها الى المشغل
player.addMediaItems(playlist)
بعدها ننادي الدالة
player.prepare()
هذه الدالة تقوم بتجهز وقائمة التشغيل والبدء في معالجة الصوتيات
لمعرفة حالة المشغل ما اذا كان حصل خطأ او انتهى من التحميل او انتهى من الملف الاول وسوف ينتقل الى الثاني او غيره نحتاج الى الاستماع الى عده احداث
player.addListener(listener)
نقوم بمنادة Player.Listener
الدالة ونمرر المتغير وهو Interface
يتيح لنا عدة دوال :
مثل
onIsPlayingChanged
يتم منادتها اذا توقف او بدء التشغيل-
onMediaItemTransition
يتم المنادة اذا انتهى المسار الصوتي وانتقل الى المسار التاليonPlaybackStateChanged
تتم المناداة اذا تغير حالة المشغل وهي واحد من اربع حالات:Player.STATE_BUFFERING
تحدث هذه الحالة عادةً عند الحاجة إلى تحميل المزيد من البيانات.Player.STATE_ENDED
انتهى من تشغيل الوسائطPlayer.STATE_IDLE
المشغل ليس لديه أي وسائطPlayer.STATE_READY
المشغل جاهز للبدء
- وغيرها الكثير
البدء في التشغيل وباقي التحكمات
يمكن بدء التشغيل بطريقتين
الاولى:
منادة الدالة
player.playWhenReady = true
التي بدورها تعطي امرا للمشغل بالبدء من تلقاء من نفسه اذا توفرت البيانات
player.release()
يستخدم لايقاف المشغل وتحرير اي كائن له علاقة بالمشغل
player.pause()
يستخدم لايقاف التشغيل ويمكن استئناف التشغل بمنادة الامر play
player.stop()
يوقف التشغيل بدون إعادة ضبط المشغل. استخدم pause()
بدلاً من هذه الطريقة إذا كانت النية هي إيقاف التشغيل مؤقتًا.
seekTo(int windowIndex, long positionMs)
تستخدم للانتقال بين المسارات مع تحديد الزمن, يجب استخدامها بحذر لان المشغل سوف يرسل خطأ اذا تم تمرير رقم مسار خاطئ او غير موجود
seekTo(long positionMs)
تستخدم للانتقال الى زمن معين في نفس المسار الحالي
كانت هذه هي التحكمات الاساسية
نقوم الان بشتغيل المثال:
كانت هذه مقدمة بسيطة للمكتبة , في مواضيع مستقبلية سوف اقوم بشرح مواضيع اضافة. الكود متوفر على github اذا اردت المزيد من التفاصيل