الاستجابة لأزرار الوسائط

أزرار الوسائط هي أزرار أجهزة يتم العثور عليها في أجهزة Android والأجهزة الملحقة الأخرى، مثل زر الإيقاف المؤقت/التشغيل في سماعة رأس بلوتوث. عندما يضغط مستخدم على زر وسائط، ينشئ Android KeyEvent، الذي يحتوي على رمز مفتاح يحدّد الزر. الرموز الرئيسية لزر الوسائط "الأحداث الرئيسية" هي رموز ثابتة تبدأ بـ KEYCODE_MEDIA (على سبيل المثال، KEYCODE_MEDIA_PLAY).

يجب أن تتمكن التطبيقات من التعامل مع أحداث زر الوسائط في ثلاث حالات، بهذا الترتيب الأولوية:

  • عندما يكون نشاط واجهة المستخدم للتطبيق مرئيًا
  • عندما يكون نشاط واجهة المستخدم مخفيًا وجلسة الوسائط في التطبيق نشطة
  • عندما يكون نشاط واجهة المستخدم مخفيًا وتكون جلسة وسائط التطبيق غير نشطة وتتطلّب إعادة تشغيلها

التعامل مع أزرار الوسائط في نشاط في المقدّمة

يتلقّى النشاط الذي تعمل في المقدّمة الحدث الرئيسي لزر الوسائط في onKeyDown(). . استنادًا إلى إصدار Android المستخدَم حاليًا، هناك طريقتان يوجِّههما النظام الحدث إلى وحدة التحكم في الوسائط:

  • إذا كنت تستخدم Android 5.0 (مستوى واجهة برمجة التطبيقات 21) أو إصدارًا أحدث، اتصل FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected سيؤدي هذا إلى الاتصال تلقائيًا بوحدة التحكم في الوسائط dispatchMediaButtonEvent(), وهو ما يحوّل رمز المفتاح إلى استدعاء جلسة وسائط.
  • قبل الإصدار 5.0 من Android (المستوى 21 من واجهة برمجة التطبيقات)، عليك تعديل "onKeyDown()" للتعامل مع الإصدار الحالي. الحدث بنفسك. (راجع التعامل مع أزرار الوسائط في جلسة وسائط نشطة للحصول على التفاصيل.) يوضح مقتطف الرمز التالي كيفية اعتراض الرمز الأساسي واستدعاء dispatchMediaButtonEvent(). تأكَّد من إرجاع مبلغ true إلى للإشارة إلى أنه تم التعامل مع الحدث:

    Kotlin

        fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                return super.onKeyDown(keyCode, event)
            }
            when (keyCode) {
                KeyEvent.KEYCODE_MEDIA_PLAY -> {
                    yourMediaController.dispatchMediaButtonEvent(event)
                    return true
                }
            }
            return super.onKeyDown(keyCode, event)
        }
        

    Java

        @Override
        boolean onKeyDown(int keyCode, KeyEvent event) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                  return super.onKeyDown(keyCode, event);
                }
                switch (keyCode) {
                  case KeyEvent.KEYCODE_MEDIA_PLAY:
                          yourMediaController.dispatchMediaButtonEvent(event);
                          return true;
                }
                return super.onKeyDown(keyCode, event);
        }
        

العثور على جلسة وسائط

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

  • إذا كنت تستخدم الإصدار 8.0 من نظام التشغيل Android (المستوى 26 من واجهة برمجة التطبيقات) أو إصدارًا أحدث، سيحاول النظام ما يلي: البحث عن آخر تطبيق يتضمّن جلسة MediaSession تم فيها تشغيل الصوت محليًا. إذا كانت الجلسة نشط. يرسل Android الحدث إليه مباشرةً. وبخلاف ذلك، إذا كانت الجلسة غير نشطة وبها جهاز استقبال لزر الوسائط، ويرسل Android الحدث إلى المُستلِم، والذي سيعيد تشغيل الجلسة وبالتالي يمكنه تلقّي الحدث. (راجع استخدام أزرار الوسائط لإعادة تشغيل جلسة وسائط غير نشطة للحصول على التفاصيل). إذا لم تتضمن الجلسة متلقي زر وسائط، فسيتجاهل النظام الوسائط ولن يحدث أي شيء. يظهر المنطق في ما يلي الرسم التخطيطي:

  • في ما قبل Android 8.0 (مستوى واجهة برمجة التطبيقات 26)، يحاول النظام إرسال الحدث إلى جلسة وسائط نشطة. إذا كان هناك عدة جلسات وسائط نشطة، سيحاول Android لاختيار جلسة وسائط تستعد للتشغيل (التخزين المؤقت/الاتصال)، أو قيد التشغيل أو تم إيقافها مؤقتًا بدلاً من تشغيلها مؤقتًا (راجع التعامل مع أزرار الوسائط في جلسة وسائط نشطة للحصول على مزيد من التفاصيل). إذا لم يكن هناك رمز ، يحاول Android إرسال الحدث إلى آخر جلسة نشطة. (راجع استخدام أزرار الوسائط لإعادة تشغيل جلسة وسائط غير نشطة للحصول على التفاصيل). يظهر المنطق في الرسم التخطيطي التالي:

التعامل مع أزرار الوسائط في جلسة وسائط نشطة

في نظام التشغيل Android 5.0 (مستوى واجهة برمجة التطبيقات 21) والإصدارات الأحدث، يرسِل Android تلقائيًا أحداث أزرار الوسائط إلى جلسة الوسائط النشطة عن طريق استدعاء onMediaButtonEvent() بشكل تلقائي، يحول رد الاتصال هذا KeyEvent إلى طريقة معاودة الاتصال لجلسة الوسائط المناسبة التي تتطابق مع رمز المفتاح.

قبل Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات)، يتعامل Android مع أحداث أزرار الوسائط عن طريق بث هدف. مع الإجراء ACTION_MEDIA_BUTTON. يجب أن يسجّل التطبيق جهاز BroadcastRECEIVEr يهدف إلى اعتراض هذه الأهداف. تشير رسالة الأشكال البيانية MediaButtonReceiver صُمِّمت خصيصًا لهذا الغرض. إنها فئة صغيرة في أجهزة Android وسائط متوافقة على ACTION_MEDIA_BUTTON وتترجم الأهداف الواردة إلى استدعاء طريقة MediaSessionCompat.Callback ملائمة.

MediaButtonReceiver هو جهاز استقبال بث قصير الأجل. يعيد توجيه المكالمات الواردة الأهداف إلى الخدمة التي تدير جلسة الوسائط الخاصة بك. إذا كنت ترغب في استخدام أزرار الوسائط في الأنظمة التي تسبق Android 5.0، عليك تضمينها MediaButtonReceiver في ملف البيان مع فلتر الأهداف MEDIA_BUTTON.:

<receiver android:name="android.support.v4.media.session.MediaButtonReceiver" >
   <intent-filter>
     <action android:name="android.intent.action.MEDIA_BUTTON" />
   </intent-filter>
 </receiver>

يُعيد "BroadcastReceiver" توجيه الهدف إلى خدمتك. لتحليل الهدف وإنشاء رد الاتصال بجلسة تشغيل الوسائط، يمكنك تضمين طريقة MediaButtonReceiver.handleIntent() في onStartCommand() الخاص بالخدمة. وهذا يؤدي إلى ترجمة رمز المفتاح إلى طريقة معاودة الاتصال بالجلسة المناسبة.

Kotlin

private val mediaSessionCompat: MediaSessionCompat = ...

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    MediaButtonReceiver.handleIntent(mediaSessionCompat, intent)
    return super.onStartCommand(intent, flags, startId)
}

Java

private MediaSessionCompat mediaSessionCompat = ...;

 public int onStartCommand(Intent intent, int flags, int startId) {
   MediaButtonReceiver.handleIntent(mediaSessionCompat, intent);
   return super.onStartCommand(intent, flags, startId);
 }

استخدام أزرار الوسائط لإعادة تشغيل جلسة وسائط غير نشطة

إذا تمكّن نظام Android من تحديد آخر جلسة وسائط نشطة، سيحاول إعادة تشغيل الجلسة من خلال إرسال Intent من ACTION_MEDIA_BUTTON إلى مكوّن مسجَّل في ملف البيان (مثل إحدى الخدمات أو BroadcastReceiver).

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

يتم تفعيل هذا السلوك تلقائيًا عند استخدام MediaSessionCompat. إذا كنت استخدام MediaSession لإطار عمل Android أو الإصدار 24.0.0 من Support Library حتى 25.1.1 يجب الاتصال بـ setMediaButtonReceiver للسماح لزر وسائط بإعادة تشغيل جلسة وسائط غير نشطة.

يمكنك إيقاف هذا السلوك في الإصدار Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث من خلال إعداد مستقبل زر وسائط فارغ:

Kotlin

// Create a MediaSessionCompat
mediaSession = MediaSessionCompat(context, LOG_TAG)
mediaSession.setMediaButtonReceiver(null)

Java

// Create a MediaSessionCompat
mediaSession = new MediaSessionCompat(context, LOG_TAG);
mediaSession.setMediaButtonReceiver(null);

تخصيص معالِجات زر الوسائط

يعمل السلوك التلقائي لمتصفِّح onMediaButtonEvent() على استخراج الرمز البرمجي واستخدام الحالة الحالية لجلسة الوسائط وقائمة الإجراءات المتوافقة لتحديد الطريقة المطلوب الاتصال بها. على سبيل المثال، يستدعي KEYCODE_MEDIA_PLAY onPlay().

لتوفير تجربة متناسقة لزر الوسائط في جميع التطبيقات، يجب استخدام السلوك الافتراضي ينحرف عن غرض معين فقط. إذا ظهر زر وسائط تحتاج إلى معالجة مخصصة، فعليك إلغاء onMediaButtonEvent() استخرِج KeyEvent باستخدام intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT), التعامل مع الحدث بنفسك، ثم عرض true.

ملخّص

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

بالإضافة إلى ذلك وحسب إصدارات Android التي تخطّط لدعمها، يجب أيضًا أن تستوفي هذه المتطلبات:

عند استخدام إصدار Android 5.0 أو إصدار أحدث:

  • الاتصال بالرقم MediaControllerCompat.setMediaController() من خلال وحدة التحكّم في الوسائط معاودة الاتصال onConnected()
  • للسماح لزر وسائط بإعادة تشغيل جلسة غير نشطة، يجب إنشاء MediaButtonReceiver ديناميكيًا من خلال الاتصال setMediaButtonReceiver() واجتياز PendingIntent

عند تشغيل التطبيق على أنظمة أقدم من Android 5.0:

  • يمكنك تجاهُل onKeyDown() في النشاط للتعامل مع أزرار الوسائط
  • إنشاء MediaButtonReceiver بشكل ثابت من خلال إضافته إلى ملف بيان التطبيق