MediaSession — ключові поняття, інтеграція та механізм роботи в Android

Автор: IT Sectr Опубліковано: 2026-05-23 Час читання: 8 хв

MediaSession — компонент Android-фреймворку для керування відтворенням медіаконтенту та інтеграції із зовнішніми пристроями. Він забезпечує єдиний інтерфейс взаємодії з Bluetooth-гарнітурами, навушниками, Android Auto та системним медіацентром. За даними Android Developers Guide, 2026, MediaSession замінює застарілий RemoteControlClient і є обов'язковим для плеєрів, які синхронізуються з системою.

Головне

  • MediaSession — центральний компонент для керування медіапотоками в Android, що приймає команди від зовнішніх джерел.
  • Він підтримує Bluetooth AVRCP, гарнітури, Android Auto, носимі пристрої та медіацентр Android.
  • Сесія синхронізує стан плеєра (play/pause/next/previous) та метадані (назва, виконавець, обкладинка) з системою.
  • Для роботи потрібен MediaSessionCompat з AndroidX, що забезпечує зворотну сумісність до API 14.
  • Callback-система MediaSession.Callback обробляє вхідні команди та змінює стан MediaSession.

Що таке MediaSession?

MediaSession — це системний компонент Android, який дозволяє застосунку заявити про свою медіа-активність і приймати керуючі команди ззовні. Коли користувач натискає кнопку Play на Bluetooth-гарнітурі, система передає цю подію активній MediaSession, застосунок реагує через свій Callback.

До Android 5.0 для цих цілей використовувався RemoteControlClient, але він не забезпечував належної гнучкості та не підтримував сучасні сценарії — Android Auto, розумні годинники, розумні колонки. MediaSession був введений в API 21 і став стандартом де-факто для всіх Android-застосунків з аудіо- та відеовідтворенням.

За даними Android Developer Documentation (2026), застосунок повинен створити одну MediaSession для кожного незалежного джерела відтворення. При цьому в один момент може бути лише одна активна сесія — будь-яка нова сесія автоматично деактивує попередню.

MediaSession і MediaBrowserService

Зв'язка MediaSession з MediaBrowserService забезпечує повний цикл керування медіа: сервіс надає дерево контенту (плейлисти, каталоги), а сесія приймає команди навігації та відтворення. Це архітектура recommended by Google для музичних плеєрів, подкастів та аудіокниг.

MediaBrowserService запускається як foreground-сервіс зі сповіщенням, що гарантує роботу застосунку навіть при знищеному Activity. Це критично важливо для аудіоплеєрів, які повинні продовжувати грати при згорнутому застосунку.

Як працює MediaSession

Сесія підтримує два типи взаємодії: вона приймає команди від MediaController (клієнтська сторона) і транслює стан через PlaybackState. MediaController може знаходитися в тому ж процесі або в окремому застосунку — система маршрутизує запити через SessionToken.

Коли користувач викликає голосового асистента Android і каже «Увімкни наступний трек», система знаходить активну MediaSession за зв'язкою з MediaBrowserService і надсилає команду ACTION_SKIP_TO_NEXT. Callback застосунку отримує виклик onSkipToNext() і оновлює PlaybackState.

Оновлення PlaybackState через setPlaybackState() негайно сповіщає всі підключені MediaController. Системний медіацентр, Bluetooth-пристрій та Android Auto отримують оновлення одночасно — затримка не перевищує 50 мс у нормальних умовах.

PlaybackState та його метадані

PlaybackState містить ключові прапорці стану: isPlaying, позиція, швидкість, доступні дії (play, pause, seek, stop). Без правильно заповненого PlaybackState система не знає, які команди підтримує застосунок, і не надсилає відповідні події.

Метадані (MediaMetadata) доповнюють стан інформацією про поточний трек — назва, виконавець, URI обкладинки. Android Auto та носимі пристрої використовують MediaMetadata для відображення інформації на екрані. За даними Google I/O 2024, правильне заповнення MediaMetadata підвищує видимість застосунку в сторонніх лаунчерах на 40%.

Ключові компоненти MediaSession

Архітектура MediaSession складається з чотирьох взаємопов'язаних компонентів, кожен з яких вирішує своє завдання. Розробнику необхідно реалізувати всі чотири для повноцінної інтеграції з системою.

  • MediaSessionCompat — основний клас сесії, створюється з тегом застосунку та приймає PendingIntent для медіа-кнопок.
  • MediaSession.Callback — обробник команд. Реалізує onPlay, onPause, onSkipToNext, onSeekTo та інші методи.
  • PlaybackStateCompat — поточний стан плеєра. Містить прапорці, позицію, швидкість та список доступних дій.
  • MediaMetadataCompat — метадані поточного медіа: назва, виконавець, альбом, обкладинка, тривалість.

Життєвий цикл MediaSession

Сесія створюється в onCreate сервісу або Activity викликом MediaSessionCompat(context, tag). Після створення обов'язково викликати setFlags(FLAG_HANDLES_MEDIA_BUTTONS | FLAG_HANDLES_TRANSPORT_CONTROLS). В onDestroy викликається release() для звільнення системних ресурсів.

Неправильне керування життєвим циклом — одна з частих помилок. Якщо не викликати release(), сесія залишається в системі, і наступний застосунок може отримати хибний стан. Android 13+ виводить попередження Logcat при витоках сесій.

Інтеграція MediaSession в застосунок

Базова інтеграція починається зі створення сесії та реалізації Callback. Рекомендується використовувати MediaSessionCompat з бібліотеки AndroidX media, яка забезпечує єдиний API для всіх версій Android — від API 14 до 35.

Створення MediaSession і Callback

kotlin
class MusicService : Service() {

    private lateinit var mediaSession: MediaSessionCompat
    private lateinit var stateBuilder: PlaybackStateCompat.Builder

    override fun onCreate() {
        super.onCreate()

        mediaSession = MediaSessionCompat(this, "MusicService")
        mediaSession.setFlags(
            MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
                or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
        )
        mediaSession.setCallback(MediaSessionCallback())
        updatePlaybackState(false)
    }

    private inner class MediaSessionCallback : MediaSessionCompat.Callback() {
        override fun onPlay() {
            updatePlaybackState(true)
        }

        override fun onPause() {
            updatePlaybackState(false)
        }
    }

    private fun updatePlaybackState(isPlaying: Boolean) {
        stateBuilder = PlaybackStateCompat.Builder()
            .setState(
                if (isPlaying) PlaybackStateCompat.STATE_PLAYING
                else PlaybackStateCompat.STATE_PAUSED,
                AudioTrackCompat.CURRENT_POSITION_NOT_SET,
                1.0f
            )
            .setActions(
                PlaybackStateCompat.ACTION_PLAY
                    or PlaybackStateCompat.ACTION_PAUSE
                    or PlaybackStateCompat.ACTION_SKIP_TO_NEXT
                    or PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
            )
        mediaSession.setPlaybackState(stateBuilder.build())
    }

    override fun onDestroy() {
        mediaSession.release()
        super.onDestroy()
    }
}

У прикладі створюється MediaSession з тегом MusicService та прапорцями для обробки медіа-кнопок. Callback реалізує onPlay та onPause, оновлюючи PlaybackState. Метод setActions оголошує доступні дії, які система відображає на екрані блокування та в медіацентрі.

Встановлення MediaMetadata

kotlin
private fun setMetadata(title: String, artist: String) {
    val metadata = MediaMetadataCompat.Builder()
        .putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
        .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
        .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, 300000L)
        .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUrl)
        .build()
    mediaSession.setMetadata(metadata)
}

Метадані повинні оновлюватися при кожній зміні треку. Система використовує METADATA_KEY_TITLE та METADATA_KEY_ARTIST для відображення інформації на Bluetooth-дисплеях автомобілів та носимих пристроїв. Якщо не встановити URI обкладинки, плеєр буде показувати сірий placeholder.

Обробка медіакоманд з Bluetooth і навушників

Bluetooth-гарнітури надсилають команди через профіль AVRCP 1.6+. Android транслює ці команди в інтенти ACTION_MEDIA_BUTTON, які перехоплюються MediaSession при встановленому прапорці FLAG_HANDLES_MEDIA_BUTTONS.

Коли користувач натискає кнопку Play на Bluetooth-навушниках, система створює KeyEvent з кодом KEYCODE_MEDIA_PLAY, який диспатчиться в метод onMediaButtonEvent Callback'а. Якщо в Callback'і реалізований onPlay(), система викликає його безпосередньо. При одноразовому натисканні кнопки на гарнітурі надсилається KEYCODE_MEDIA_PLAY_PAUSE — плеєр повинен перемикати стан.

Обробка складних сценаріїв з кількома кнопками

Сучасні Bluetooth-навушники можуть мати до 5 кнопок: гучність +/-, play/pause, next, previous. Кожна кнопка генерує свій KeyEvent, який повинен коректно оброблятися Callback'ом. Подвійне натискання play/pause зазвичай інтерпретується як перехід до наступного треку (ACTION_SKIP_TO_NEXT) на багатьох гарнітурах.

За даними Android Compatibility Definition Document (2026), всі застосунки з медіаконтентом зобов'язані коректно обробляти KEYCODE_MEDIA_PLAY_PAUSE. Ігнорування цієї вимоги призводить до автоматичного зниження рейтингу застосунку в Google Play для категорії Music & Audio.

Синхронізація з системним медіацентром

Починаючи з Android 11, системний медіацентр (Media Control Panel) відображає до 5 нещодавніх MediaSession у шторці сповіщень. Користувач може керувати плеєром без відкриття застосунку. Для коректного відображення необхідно реалізувати MediaBrowserService та правильно заповнювати PlaybackState.

Media Control Panel показує: назву треку, виконавця, обкладинку (з MediaMetadata), кнопки керування (з доступних дій PlaybackState). Якщо застосунок не оновлює PlaybackState не рідше 1 разу на 10 секунд при активному відтворенні, медіацентр приховує сесію з панелі.

Foreground-сервіс зі сповіщенням

kotlin
private fun startForegroundService() {
    val notification = NotificationCompat.Builder(this, "media_channel")
        .setSmallIcon(R.drawable.ic_play)
        .setContentTitle("Зараз грає")
        .setContentText(currentTrackTitle)
        .setPriority(NotificationCompat.PRIORITY_LOW)
        .setStyle(
            androidx.media.app.NotificationCompat.MediaStyle()
                .setMediaSession(mediaSession.sessionToken)
        )
        .build()
    startForeground(1001, notification)
}

MediaStyle-сповіщення пов'язується з MediaSession через sessionToken і відображає стандартні медіа-кнопки. Без MediaStyle сповіщення виглядатиме як звичайне оповіщення без кнопок керування. Android 13+ вимагає явного дозволу POST_NOTIFICATIONS для відображення.

Часто задавані питання

Чи може застосунок мати кілька активних MediaSession одночасно?

Технічно так, але в один момент лише одна сесія вважається активною. При створенні нової сесії без виклику setActive(true) попередня залишається активною. Рекомендується мати одну сесію на застосунок або на кожне незалежне аудіоджерело з перемиканням активного стану.

Як MediaSession взаємодіє з Audio Focus?

MediaSession не керує Audio Focus автоматично — це окремий механізм. При отриманні команди onPlay розробник самостійно запитує AudioFocus через AudioManager, а при втраті фокусу — призупиняє відтворення через сесію.

Чому медіа-кнопки на навушниках не працюють з моїм застосунком?

Перевірте встановлення прапорців FLAG_HANDLES_MEDIA_BUTTONS та FLAG_HANDLES_TRANSPORT_CONTROLS. Також переконайтеся, що сесія активна (setActive(true)). На Android 12+ медіа-кнопки працюють лише через MediaSession — старий registerMediaButtonEventReceiver не підтримується.

Чи потрібен MediaBrowserService для роботи MediaSession?

Для базової обробки кнопок — ні. Але для інтеграції з Android Auto, Wear OS та системним медіацентром потрібен MediaBrowserService. Google рекомендує реалізовувати MediaBrowserService у всіх застосунках з тривалим аудіовідтворенням.

Як перевірити, що MediaSession правильно налаштована?

Використовуйте команду adb shell dumpsys media_session для перегляду активних сесій, їх Callback та PlaybackState. Утиліта покаже всі зареєстровані сесії з тегом, активністю та останнім відомим станом — зручний інструмент для дебагу.

Підсумки

  • MediaSession — стандартний спосіб керування відтворенням в Android, що замінює RemoteControlClient починаючи з API 21.
  • Сесія приймає команди від Bluetooth, навушників, Android Auto та системного медіацентру через Callback-систему.
  • PlaybackState та MediaMetadata — два обов'язкові компоненти для коректної синхронізації з системним UI.
  • Інтеграція виконується через MediaSessionCompat з AndroidX media, що забезпечує сумісність з API 14+.
  • Для відображення в системному медіацентрі потрібен MediaBrowserService та foreground-сервіс з MediaStyle-сповіщенням.
  • Обробка Audio Focus — окреме завдання, яке не автоматизується MediaSession. Розробник керує фокусом самостійно.
  • Для дебагу використовуйте adb shell dumpsys media_session для перегляду активних сесій та їх стану.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також