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

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

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

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

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

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

  • اگر Android نسخه 5.0 (سطح API 21) یا بالاتر را اجرا می‌کنید، با FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected تماس بگیرید. با این کار به طور خودکار dispatchMediaButtonEvent() کنترلر رسانه شما را فراخوانی می کند که کد کلید را به یک پاسخ تماس جلسه رسانه ترجمه می کند.
  • قبل از Android 5.0 (سطح API 21)، باید 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 سعی می‌کند جلسه رسانه‌ای را پیدا کند که بتواند آن را مدیریت کند. باز هم، بسته به نسخه در حال اجرا اندروید، دو راه برای جستجوی یک جلسه رسانه وجود دارد:

  • اگر از اندروید 8.0 (سطح API 26) یا بالاتر استفاده می کنید، سیستم سعی می کند آخرین برنامه را با MediaSession پیدا کند که صدا را به صورت محلی پخش می کند. اگر جلسه هنوز فعال باشد، اندروید رویداد را مستقیماً به آن ارسال می کند. در غیر این صورت، اگر جلسه فعال نباشد و دارای یک گیرنده دکمه مدیا باشد، اندروید رویداد را به گیرنده ارسال می کند که جلسه را مجددا راه اندازی می کند و بنابراین می تواند رویداد را دریافت کند. (برای جزئیات بیشتر به استفاده از دکمه های رسانه برای راه اندازی مجدد یک جلسه رسانه غیرفعال مراجعه کنید.) اگر جلسه گیرنده دکمه رسانه نداشته باشد، سیستم رویداد دکمه رسانه را کنار می گذارد و هیچ اتفاقی نمی افتد. منطق در نمودار زیر نشان داده شده است:

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

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

در Android 5.0 (سطح API 21) و بالاتر، Android به طور خودکار رویدادهای دکمه رسانه را با فراخوانی onMediaButtonEvent() به جلسه رسانه فعال شما ارسال می کند. به‌طور پیش‌فرض، این callback، KeyEvent را به روش بازگشت به تماس رسانه‌ای مناسب ترجمه می‌کند که با کد کلید مطابقت دارد.

قبل از Android 5.0 (سطح API 21)، Android رویدادهای دکمه رسانه را با پخش یک هدف با عملکرد ACTION_MEDIA_BUTTON کنترل می‌کند. برنامه شما باید یک BroadcastReceiver برای رهگیری این اهداف ثبت کند. کلاس MediaButtonReceiver به طور خاص برای این منظور طراحی شده است. این یک کلاس راحتی در کتابخانه Android media-compat است که ACTION_MEDIA_BUTTON مدیریت می کند و Intent های دریافتی را به فراخوانی های متد 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 هدف را به خدمت شما ارسال می کند. برای تجزیه و تحلیل intent و ایجاد پاسخ تماس به جلسه رسانه خود، متد 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 یا Support Library 24.0.0 تا 25.1.1 چارچوب Android استفاده می‌کنید، باید با setMediaButtonReceiver تماس بگیرید تا به دکمه رسانه اجازه دهید جلسه رسانه غیرفعال را مجدداً راه اندازی کند.

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

کاتلین

// 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 را مشخص کنید.

علاوه بر این، بسته به نسخه های اندرویدی که قصد پشتیبانی از آن را دارید، باید این شرایط را نیز رعایت کنید:

هنگام اجرا در اندروید 5.0 یا بالاتر:

  • تماس با MediaControllerCompat.setMediaController() از کنترلر رسانه onConnected()
  • برای اینکه یک دکمه رسانه اجازه راه اندازی مجدد یک جلسه غیرفعال را بدهد، با فراخوانی setMediaButtonReceiver() و ارسال آن به صورت PendingIntent ، به صورت پویا یک MediaButtonReceiver ایجاد کنید.

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

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