پاسخ دادن به دکمه‌های رسانه

دکمه‌های رسانه دکمه‌های سخت‌افزاری هستند که در دستگاه‌های Android و سایر دستگاه‌های جانبی وجود دارند، برای مثال، دکمه توقف موقت/پخش در هدست بلوتوث. وقتی کاربر دکمه رسانه را فشار می‌دهد، Android یک KeyEvent تولید می‌کند که حاوی کد کلید است که دکمه را شناسایی می‌کند. کدهای کلید برای KeyEvents دکمه رسانه ثابت‌هایی هستند که با KEYCODE_MEDIA شروع می‌شوند (برای مثال، KEYCODE_MEDIA_PLAY).

برنامه‌ها باید بتوانند رویدادهای دکمه رسانه را در سه مورد، به‌ترتیب اولویت زیر، مدیریت کنند:

  • وقتی فعالیت میانای کاربر برنامه نمایان است
  • وقتی فعالیت میانای کاربر پنهان است و جلسه رسانه برنامه فعال است
  • وقتی فعالیت میانای کاربر پنهان است و جلسه رسانه برنامه غیرفعال است و باید بازراه‌اندازی شود

مدیریت دکمه‌های رسانه در فعالیت پیش‌زمینه

فعالیت پیش‌زمینه رویداد کلید دکمه رسانه را در روش onKeyDown() خود دریافت می‌کند. بسته به نسخه Android درحال اجرا، دو روش وجود دارد که سیستم رویداد را به کنترل‌کننده رسانه هدایت می‌کند:

  • اگر از Android 5.0 (سطح میانای برنامه‌سازی کاربردی ۲۱) یا بالاتر استفاده می‌کنید، با FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected تماس بگیرید. با این کار، dispatchMediaButtonEvent() کنترل‌کننده رسانه شما به‌طور خودکار فراخوانی می‌شود، که کد کلید را به فراخوانی جلسه رسانه ترجمه می‌کند.
  • پیش‌از Android 5.0 (سطح میانای برنامه‌سازی کاربردی ۲۱)، باید onKeyDown() را تغییر دهید تا خودتان رویداد را مدیریت کنید. (برای جزئیات، به مدیریت دکمه‌های رسانه در جلسه رسانه فعال مراجعه کنید.) تکه‌کد زیر نحوه رهگیری کد کلید و فراخوانی dispatchMediaButtonEvent() را نشان می‌دهد. حتماً true را برگردانید تا نشان دهید که رویداد مدیریت شده است:

    کاتلین

        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)
        }
        

    جاوا

        @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 درحال اجرا، دو روش برای جستجوی جلسه رسانه وجود دارد:

  • اگر از Android نسخه ۸.۰ (سطح میانای برنامه‌سازی کاربردی ۲۶) یا بالاتر استفاده می‌کنید، سیستم سعی می‌کند آخرین برنامه‌ای را که MediaSession دارد و به‌صورت محلی صدا پخش کرده است پیدا کند. اگر جلسه همچنان فعال باشد، Android رویداد را مستقیماً به آن ارسال می‌کند. درغیراین‌صورت، اگر جلسه فعال نباشد و گیرنده mediabutton داشته باشد، Android رویداد را به گیرنده ارسال می‌کند که جلسه را بازراه‌اندازی می‌کند و بنابراین می‌تواند رویداد را دریافت کند. (برای جزئیات، به استفاده از دکمه‌های رسانه برای بازراه‌اندازی جلسه رسانه‌ای غیرفعال مراجعه کنید.) اگر جلسه گیرنده دکمه رسانه نداشته باشد، سیستم رویداد دکمه رسانه را نادیده می‌گیرد و اتفاقی نمی‌افتد. منطق در نمودار زیر نشان داده شده است:

  • قبل‌از Android 8.0 (میانای برنامه‌سازی کاربردی سطح ۲۶)، سیستم تلاش می‌کند رویداد را به یک جلسه رسانه فعال ارسال کند. اگر چند جلسه رسانه فعال وجود داشته باشد، Android سعی می‌کند جلسه رسانه‌ای را انتخاب کند که درحال آماده شدن برای پخش (بافر کردن/اتصال)، پخش، یا توقف موقت است، نه جلسه‌ای که متوقف شده است. (برای جزئیات بیشتر، به مدیریت دکمه‌های رسانه در جلسه رسانه فعال مراجعه کنید.) اگر جلسه فعالی وجود نداشته باشد، Android سعی می‌کند رویداد را به آخرین جلسه فعال ارسال کند. (برای جزئیات، به استفاده از دکمه‌های رسانه برای بازراه‌اندازی جلسه رسانه‌ای غیرفعال مراجعه کنید.) منطق در نمودار زیر نشان داده شده است:

مدیریت دکمه‌های رسانه در جلسه رسانه فعال

در Android نسخه ۵.۰ (سطح میانای برنامه‌سازی کاربردی ۲۱) و بالاتر، Android به‌طور خودکار رویدادهای دکمه رسانه را با فراخوانی onMediaButtonEvent() به جلسه رسانه فعال شما ارسال می‌کند. به‌طور پیش‌فرض، این فراخوانی KeyEvent را به روش فراخوانی جلسه رسانه مناسب که با کد کلید مطابقت دارد ترجمه می‌کند.

قبل‌از Android 5.0 (میانای برنامه‌سازی کاربردی سطح ۲۱)، Android رویدادهای دکمه رسانه را با همه‌فرستی هدف با کنش ACTION_MEDIA_BUTTON مدیریت می‌کند. برنامه شما باید یک BroadcastReceiver را برای رهگیری این هدف‌ها ثبت کند. کلاس MediaButtonReceiver به‌طور خاص برای این هدف طراحی شده است. این کلاس راحتی در کتابخانه media-compat Android است که ACTION_MEDIA_BUTTON را مدیریت می‌کند و «هدف‌های» ورودی را به فراخوانی‌های روش MediaSessionCompat.Callback مناسب ترجمه می‌کند.

‫MediaButtonReceiver یک BroadcastReceiver کوتاه‌مدت است. این برنامه هدف‌های ورودی را به سرویسی که جلسه رسانه شما را مدیریت می‌کند بازارسال می‌کند. اگر می‌خواهید از دکمه‌های رسانه در سیستم‌های قدیمی‌تر از 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() سرویس خود اضافه کنید. این کار کد کلید را به روش مناسب فراخوانی جلسه ترجمه می‌کند.

کاتلین

private val mediaSessionCompat: MediaSessionCompat = ...

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

جاوا

private MediaSessionCompat mediaSessionCompat = ...;

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

استفاده از دکمه‌های رسانه برای بازراه‌اندازی جلسه رسانه غیرفعال

اگر Android بتواند آخرین جلسه رسانه فعال را شناسایی کند، سعی می‌کند با ارسال ACTION_MEDIA_BUTTON Intent به مؤلفه ثبت‌شده در مانیفست (مانند سرویس یا BroadcastReceiver)، جلسه را بازراه‌اندازی کند.

این کار به برنامه شما اجازه می‌دهد تا بازپخش را درحالی‌که واسط کاربر آن قابل‌مشاهده نیست بازراه‌اندازی کند، که این مورد برای اکثر برنامه‌های صوتی صادق است.

این رفتار به‌طور خودکار هنگام استفاده از MediaSessionCompat فعال می‌شود. اگر از MediaSession چارچوب Android یا Support Library نسخه ۲۴.۰.۰ تا ۲۵.۱.۱ استفاده می‌کنید، باید setMediaButtonReceiver را فراخوانی کنید تا دکمه رسانه بتواند جلسه رسانه غیرفعال را بازراه‌اندازی کند.

می‌توانید این رفتار را در Android 5.0 (سطح میانای برنامه‌سازی کاربردی ۲۱) و بالاتر با تنظیم گیرنده دکمه رسانه تهی غیرفعال کنید:

کاتلین

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

جاوا

// 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()
  • برای اینکه دکمه رسانه بتواند جلسه غیرفعال را بازراه‌اندازی کند، با فراخوانی setMediaButtonReceiver() و ارسال PendingIntent به آن، به‌طور پویا MediaButtonReceiver ایجاد کنید

هنگام اجرا در سیستم‌های قدیمی‌تر از Android 5.0:

  • onKeyDown() فعالیت را برای مدیریت دکمه‌های رسانه لغو کنید
  • با افزودن MediaButtonReceiver به مانیفست برنامه، آن را به‌صورت ایستا ایجاد کنید