التحكّم في الوسائط من خلال MediaSession

1. مقدمة

تاريخ آخر تعديل: 2020-09-09

ما هي مزايا إضافة جلسة MediaSession حول تشغيل الفيديو؟

تعد جلسات الوسائط رابطًا لا يتجزأ بين نظام Android الأساسي وتطبيقات الوسائط. ولا يقتصر دورها على إعلام Android بأنّه يتم تشغيل الوسائط لكي يتمكّن من إعادة توجيه إجراءات الوسائط إلى الجلسة الصحيحة، بل يتم أيضًا إعلام النظام الأساسي بما يتم تشغيله وكيفية التحكّم فيه.

يؤدي عرض جلسة MediaSession من خلال تطبيقك إلى مزايا مختلفة سيستمتع بها المستخدمون. إليك بعض الأمثلة الرائعة.

مساعد Google

يمكن للمستخدمين التفاعل بسهولة مع الوسائط في تطبيقك من خلال الطلبات الصوتية مثل "إيقاف مؤقت". و"Resume" و"التالي". يمكنك أيضًا استخدام البيانات الوصفية من الوسائط للحصول على إجابات حول ما يتم تشغيله حاليًا.

Android TV

في تجارب الشاشة الكبيرة، يمكن لتطبيق Android TV الاستفادة من أدوات التحكم عن بُعد التقليدية لمستخدمي أجهزة التلفزيون التي تتوافق مع HDMI-CEC. يتم نقل الأوامر الصادرة عن أزرار التشغيل/الإيقاف المؤقت، والإيقاف، والتالي، والسابق إلى تطبيقك.

عناصر التحكّم في الوسائط على الشاشة

بدءًا من الإصدار Android 4.0 (المستوى 14 من واجهة برمجة التطبيقات)، يمكن للنظام الوصول إلى حالة تشغيل جلسة الوسائط والبيانات الوصفية. تتيح هذه الوظيفة لشاشة القفل عرض عناصر التحكّم في الوسائط والأعمال الفنية. ويختلف هذا السلوك باختلاف إصدار Android.

وسائط الخلفية

يمكن التحكّم في الوسائط في أي من هذه الحالات حتى إذا كان التطبيق الذي يشغِّل الوسائط يعمل في الخلفية.

الحوسبة المؤثرة

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

ما الذي ستنشئه

في هذا الدرس التطبيقي حول الترميز، سيتم تمديد نموذج Exoplayer الحالي لإضافة دعم لجلسات الوسائط. سينفّذ تطبيقك ما يلي:

  • تعكس الحالة النشطة لجلسة الوسائط بشكل صحيح
  • إرسال عناصر التحكّم في الوسائط إلى ExoPlayer
  • تمرير البيانات الوصفية للعناصر في قائمة الانتظار إلى جلسة تشغيل الوسائط

المعلومات التي ستطّلع عليها

  • لماذا تقدّم الجلسات الإعلامية للمستخدمين تجربة أغنى
  • كيفية إنشاء جلسة وسائط وإدارة حالتها
  • كيفية ربط جلسة وسائط بـ ExoPlayer
  • كيفية تضمين البيانات الوصفية للعناصر في قائمة انتظار التشغيل في جلسة تشغيل الوسائط
  • كيفية إضافة إجراءات إضافية (مخصّصة)

يركّز هذا الدرس التطبيقي حول الترميز على حزمة تطوير البرامج MediaSession SDK. ولا تتم مناقشة المفاهيم غير ذات الصلة وكتل الرموز، بما في ذلك تفاصيل حول تنفيذ ExoPlayer، ولكن يتم توفير هذه المفاهيم لك لنسخها ولصقها ببساطة.

المتطلبات

  • استخدام إصدار حديث من "استوديو Android" (الإصدار 3.5 أو إصدار أحدث)
  • معرفة أساسية بتطوير تطبيقات Android

2. بدء الإعداد

ما هي نقطة البداية؟

نقطة البداية هي العرض التوضيحي الرئيسي من ExoPlayer. يشتمل هذا العرض التوضيحي على فيديوهات تتضمّن عناصر تحكّم في التشغيل على الشاشة، ولكنّه لا يستخدم جلسات وسائط بطريقة غير تقليدية. إنه مكان رائع بالنسبة لنا التعمق فيه وإضافته!

الحصول على عينة ExoPlayer

لنبدأ بمثال توضيحي لـ ExoPlayer. استنساخ مستودع جيت هب عن طريق تشغيل الكود أدناه.

git clone https://github.com/google/ExoPlayer.git

فتح العرض التوضيحي

في "استوديو Android"، افتح المشروع التجريبي الرئيسي ضمن "demos/main".

سيطلب منك "استوديو Android" ضبط مسار حزمة تطوير البرامج (SDK). إذا واجهت أي مشاكل، ننصحك باتّباع توصيات تحديث أدوات IDE وSDK.

10e3b5c652186d57.png

إِذَا كَانَ الْمَطْلُوبُ اسْتِخْدَامْ أَحْدَثْ إِصْدَارْ مِنْ Gradle، يُرْجَى تَحْدِيثُهُ.

توقف لحظة للتعرف الأساسي على كيفية تصميم التطبيق. لاحظ أن هناك نشاطين: SampleChooserActivity و PlayerActivity. سنقضي ما تبقّى من الدرس التطبيقي حول الترميز في PlayerActivity، حيث يتم تشغيل الوسائط فعليًا، لذا افتح هذا الصف وانتقِل إلى القسم التالي.

3- إنشاء جلسة وسائط وإدارة حالتها

إنشاء جلسة الوسائط

فتح "PlayerActivity.java" تقوم هذه الفئة بإنشاء ExoPlayer وإدارة وظائفه، مثل عرض الفيديو على الشاشة. في هذا النشاط، سنربط ExoPlayer بجلسة وسائط.

يُرجى تعريف الحقلَين التاليَين في أعلى الصف. سنستخدم هذه الحقول في هذا القسم.

private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;

ستحتاج إلى إدراج "extension-mediasession" تبعية المشروع إلى build.gradle على مستوى الوحدة في "الوحدة: تجريبي":

implementation project(path: ':extension-mediasession')

تجدر الإشارة إلى أنّ "استوديو Android" يمكن أن يساعدك في إضافة هذه الاعتمادية تلقائيًا إذا مرّرت مؤشر الماوس فوق الخطأ في حل MediaSessionConnector:

60055e4ad54fbb97.png

أخيرًا، يمكنك حلّ عمليات استيراد الفئة بإضافة ما يلي:

import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;

عند إنشاء النشاط، سنحتاج إلى إنشاء جلسة وسائط وموصل جلسة وسائط يعمل كوسيط بين جلسة الوسائط وExoPlayer.

المكان المثالي لإدراج هذا هو مكان إنشاء ExoPlayer أيضًا. في التطبيق التجريبي، يمكننا إلحاق الرمز بنهاية initializePlayer(). تأكَّد من إضافة هذا المنطق بعد إنشاء مثيل للمشغّل.

private void initializePlayer() {
  if (player == null) {
    ...
    player = ...
    ...
    mediaSession = new MediaSessionCompat(this, "sample");
    mediaSessionConnector = new MediaSessionConnector(mediaSession);
    mediaSessionConnector.setPlayer(player);
  }
  ...
}

إطلاق جلسة الوسائط

حرر جلسة الوسائط عند عدم الحاجة إليها. عند إصدار ExoPlayer في releasePlayer()، يمكننا أيضًا تضمين الرمز التالي لإجراء ذلك:

private void releasePlayer() {
  if (mediaSession != null) {
    mediaSession.release();
  }
  ...
}

إدارة حالة جلسة الوسائط

الآن وبعد إنشاء مثيل لجلسة الوسائط، نحتاج إلى التأكد من انعكاس حالتها بشكل صحيح أثناء تفاعل المستخدم مع النشاط.

عندما يبدأ المستخدم النشاط، يجب أن تصبح جلسة الوسائط نشطة:

@Override
public void onStart() {
  ...
  if (mediaSession != null) {
    mediaSession.setActive(true);
  }
}

نظرًا لأن التطبيق لا يشغِّل الوسائط في الخلفية، من الضروري التأكد من أن جلسة الوسائط تصبح غير نشطة عند مغادرة المستخدم للنشاط:

@Override
public void onStop() {
  super.onStop();
  if (mediaSession != null) {
    mediaSession.setActive(false);
  }
  ...
}

لنبدأ تشغيل العرض التوضيحي

  1. عليك توصيل جهاز Android أو تشغيل محاكي.
  2. تأكد من أن "العرض التوضيحي" لتشغيله من شريط أدوات "استوديو Android". cb1ec4e50886874f.png
  3. النقر على 9d8fb3a9ddf12827.png من شريط أدوات "استوديو Android"
  4. بعد تشغيل التطبيق على جهازك، حدد أحد مقاطع الفيديو لتشغيله.
  5. بعد بدء التشغيل، يمكنك استخدام أوامر adb التالية للتحكّم في جلسة الوسائط:
adb shell media dispatch pause
adb shell media dispatch play
adb shell media dispatch play-pause
adb shell media dispatch fast-forward
adb shell media dispatch rewind
  1. يمكنك أيضًا استكشاف كيفية ظهور جلسة الوسائط لنظام التشغيل Android. وعلى وجه التحديد، يمكنك الاطّلاع على الإجراءات المتاحة من خلال الاطّلاع على حقل الإجراء. الرقم الظاهر هنا هو مجموعة من معرّفات الإجراءات، كما هو موضّح في العنصر PlaybackState. لعرض جلسة تشغيل الوسائط: adb shell dumpsys media_session
  2. إذا كنت تستخدم جهازًا فعليًا مزوَّدًا بميكروفون، حاوِل استدعاء "مساعد Google" وإصدار طلبات صوتية، مثل: "إيقاف مؤقت". "استئناف" (Resume) "تقديم سريع بمقدار دقيقة واحدة"

b8dda02a6fb0f6a4.pngيتم تشغيل نموذج ExoPlayer على Android TV.

4. تضمين البيانات الوصفية للعناصر في قائمة انتظار التشغيل

يمكننا الآن توسيع الميزات المتاحة لجلسة الوسائط حيث سبق أن أنشأنا MediaSessionConnector في initializePlayer().

إضافة مخطَّط زمني Navigator

يمثل ExoPlayer بنية الوسائط كجدول زمني. للحصول على تفاصيل حول كيفية عمل ذلك، يُرجى تخصيص بعض الوقت لقراءة كائن المخطط الزمني في ExoPlayer. من خلال استخدام هذه البنية، يمكننا إبلاغنا عندما يتغيّر المحتوى، ونعرض البيانات الوصفية للمحتوى الذي يتم تشغيله حاليًا عندما يُطلب منك ذلك.

ولتنفيذ ذلك، سنعرف الجدول الزمنيّسانتظار Navigator. حدِّد موقع مثيل MediaSessionConnector في initializePlayer() وأضِف عملية تنفيذ ScheduleInventoryNavigator بعد mediaSession.

mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
  @Override
  public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
    return new MediaDescriptionCompat.Builder()
            .setTitle(player.getCurrentMediaItem().mediaMetadata.title)
            .setDescription("MediaDescription description for " + windowIndex)
            .setSubtitle("MediaDescription subtitle")
            .build();
  }
});

يمكنك حلّ عمليات استيراد الصف بإضافة ما يلي:

import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;

لاحظ أن المعلمة windowIndex تتوافق مع عنصر هذا الفهرس في قائمة انتظار التشغيل.

الآن بعد أن أضفت بعض البيانات الوصفية، يمكنك اختبار ما إذا كان "مساعد Google" يفهم ما يتم تشغيله. أثناء تشغيل فيديو على Android TV، استدعِ "مساعد Google" واسأل "ما الذي يتم تشغيله؟"

6c7fc0cb853cbc38.png

5- تخصيص الإجراءات

قد يكون لاعبك لا يتيح تنفيذ بعض الإجراءات، أو تريد توفير الدعم للمزيد من الإجراءات؟ لنتحدث الآن بشكل أكثر تفصيلاً عن جلسة الوسائط التي سبق أن أنشأنا فيها MediaSessionConnector في initializePlayer().

الإعلان عن الإجراءات المتوافقة

جرِّب استخدام mediaSessionConnector.setEnabledPlaybackActions() لتخصيص الإجراءات التي تريد أن تتيحها جلسة الوسائط.

يُرجى العِلم أنّ المجموعة الكاملة هي:

mediaSessionConnector.setEnabledPlaybackActions(
        PlaybackStateCompat.ACTION_PLAY_PAUSE
                | PlaybackStateCompat.ACTION_PLAY
                | PlaybackStateCompat.ACTION_PAUSE
                | PlaybackStateCompat.ACTION_SEEK_TO
                | PlaybackStateCompat.ACTION_FAST_FORWARD
                | PlaybackStateCompat.ACTION_REWIND
                | PlaybackStateCompat.ACTION_STOP
                | PlaybackStateCompat.ACTION_SET_REPEAT_MODE
                | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);

لنطّلع مرة أخرى على كيفية عرض هذه البيانات على النظام الأساسي:

  1. كما في السابق، ابدأ تشغيل فيديو.
  2. تعرَّف على الطريقة التي يرى بها Android البيانات الوصفية من جلسة الوسائط من خلال تنفيذ ما يلي: adb shell dumpsys media_session
  3. حدِّد مكان السطر الذي يحتوي على البيانات الوصفية وتأكّد من أنّ العنوان والوصف تم تضمينهما وربطهما بالسمة com.google.android.exoplayer2.demo/sample.

إضافة إجراءات إضافية

يمكننا توسيع جلسة الوسائط من خلال بعض الإجراءات الإضافية. في هذا القسم، سنضيف ميزة الترجمة والشرح فقط.

إتاحة الترجمة والشرح

من خلال إتاحة ميزة الترجمة والشرح في جلسات الوسائط، يمكن للمستخدمين التبديل بين الصوت والفيديو. حيث تم إعداد موصل جلسة الوسائط، أضف ما يلي:

mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
      @Override
      public void onSetCaptioningEnabled(Player player, boolean enabled) {
        Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
      }

      @Override
      public boolean hasCaptions(Player player) {
        return true;
      }

      @Override
      public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
        return false;
      }
    }
);

أخيرًا، يجب حلّ أي عمليات استيراد مفقودة.

يمكنك اختبار ذلك من خلال استدعاء "مساعد Google" على Android TV وقول "تفعيل الترجمة". تحقَّق من Logcat بحثًا عن رسائل لمعرفة كيفية استدعاء هذا الرمز إلى رمزك.

6- تهانينا

تهانينا، لقد أضفت جلسات وسائط إلى العينة بنجاح.

لقد حصلت على قدر هائل من الوظائف من خلال:

  • وإضافة جلسة وسائط،
  • وربط جلسات الوسائط بمثيل من ExoPlayer،
  • وإضافة بيانات تعريف وإجراءات إضافية.

أنت تعرف الآن الخطوات الرئيسية المطلوبة لإثراء تطبيق وسائط وتقديم تجربة أكثر تنوّعًا للمستخدمين.

ملاحظة أخيرة

اعتمد هذا الدرس التطبيقي على عيّنة من رمز المصدر ExoPlayer. لا داعي لاستخدام ExoPlayer من المصدر، ويُنصح بدلاً من ذلك بسحب الاعتماديات لـ ExoPlayer وMediaSessionConnector لتسهيل الاطّلاع على آخر الإصدارات.

للقيام بذلك، ما عليك سوى استبدال تبعيات المشروع مثل:

implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')

سحبها من مستودعات Maven، مثل:

implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'

المستندات المرجعية