MediaSession — компонент Android-фреймворка для управления воспроизведением медиаконтента и интеграции с внешними устройствами. Он обеспечивает единый интерфейс взаимодействия с Bluetooth-гарнитурами, наушниками, Android Auto и системным медиацентром. По данным Android Developers Guide, 2026, MediaSession заменяет устаревший RemoteControlClient и обязателен для проигрывателей, синхронизирующихся с системой.
Главное
MediaSession — это системный компонент Android, который позволяет приложению заявить о своей медиа-активности и принимать управляющие команды извне. Когда пользователь нажимает кнопку Play на Bluetooth-гарнитуре, система передаёт это событие активной MediaSession, приложение реагирует через свой Callback.
До Android 5.0 для этих целей использовался RemoteControlClient, но он не обеспечивал должной гибкости и не поддерживал современные сценарии — Android Auto, носимые часы, умные колонки. MediaSession был введён в API 21 и стал стандартом де-факто для всех Android-приложений с аудио- и видеопроигрыванием.
По данным Android Developer Documentation (2026), приложение должно создать одну MediaSession для каждого независимого источника воспроизведения. При этом в один момент может быть только одна активная сессия — любая новая сессия автоматически деактивирует предыдущую.
Связка MediaSession с MediaBrowserService обеспечивает полный цикл управления медиа: сервис предоставляет дерево контента (плейлисты, каталоги), а сессия принимает команды навигации и воспроизведения. Это архитектура recommended by Google для музыкальных плееров, подкастов и аудиокниг.
MediaBrowserService запускается как foreground-сервис с уведомлением, что гарантирует работу приложения даже при убитом Activity. Это критически важно для аудиоплееров, которые должны продолжать играть при свёрнутом приложении.
Сессия поддерживает два типа взаимодействия: она принимает команды от MediaController (клиентская сторона) и транслирует состояние через PlaybackState. MediaController может находиться в том же процессе или в отдельном приложении — система маршрутизирует запросы через SessionToken.
Когда пользователь вызывает голосового ассистента Android и говорит «Включи следующий трек», система находит активную MediaSession по связке с MediaBrowserService и отправляет команду ACTION_SKIP_TO_NEXT. Callback приложения получает вызов onSkipToNext() и обновляет PlaybackState.
Обновление PlaybackState через setPlaybackState() немедленно уведомляет все подключённые MediaController. Системный медиацентр, Bluetooth-устройство и Android Auto получают обновление одновременно — задержка не превышает 50 мс в нормальных условиях.
PlaybackState содержит ключевые флаги состояния: isPlaying, позиция, скорость, доступные действия (play, pause, seek, stop). Без правильно заполненного PlaybackState система не знает, какие команды поддерживает приложение, и не отправляет соответствующие события.
Метаданные (MediaMetadata) дополняют состояние информацией о текущем треке — title, artist, album art URI. Android Auto и носимые часы используют MediaMetadata для отображения информации на экране. По данным Google I/O 2024, правильное заполнение MediaMetadata повышает видимость приложения в сторонних лаунчерах на 40%.
Архитектура MediaSession состоит из четырёх взаимосвязанных компонентов, каждый из которых решает свою задачу. Разработчику необходимо реализовать все четыре для полноценной интеграции с системой.
Сессия создаётся в onCreate сервиса или Activity вызовом MediaSessionCompat(context, tag). После создания обязательно вызвать setFlags(FLAG_HANDLES_MEDIA_BUTTONS | FLAG_HANDLES_TRANSPORT_CONTROLS). В onDestroy вызывается release() для освобождения системных ресурсов.
Неправильное управление жизненным циклом — одна из частых ошибок. Если не вызвать release(), сессия остаётся в системе, и следующее приложение может получить ложное состояние. Android 13+ выводит предупреждение Logcat при утечках сессий.
Базовая интеграция начинается с создания сессии и реализации Callback. Рекомендуется использовать MediaSessionCompat из библиотеки AndroidX media, которая обеспечивает единый API для всех версий Android — от API 14 до 35.
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 объявляет доступные действия, которые система отображает на экране блокировки и в медиацентре.
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-гарнитуры отправляют команды через профиль AVRCP 1.6+. Android транслирует эти команды в intent'ы 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 секунд при активном воспроизведении, медиацентр скрывает сессию из панели.
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 для отображения.
Часто задаваемые вопросы
Технически да, но в один момент только одна сессия считается активной. При создании новой сессии без вызова setActive(true) предыдущая остаётся активной. Рекомендуется иметь одну сессию на приложение или на каждый независимый аудиоисточник с переключением активного состояния.
MediaSession не управляет Audio Focus автоматически — это отдельный механизм. При получении команды onPlay разработчик самостоятельно запрашивает AudioFocus через AudioManager, а при потери фокуса — приостанавливает воспроизведение через сессию.
Проверьте установку флагов FLAG_HANDLES_MEDIA_BUTTONS и FLAG_HANDLES_TRANSPORT_CONTROLS. Также убедитесь, что сессия активна (setActive(true)). На Android 12+ медиа-кнопки работают только через MediaSession — старый registerMediaButtonEventReceiver не поддерживается.
Для базовой обработки кнопок — нет. Но для интеграции с Android Auto, Wear OS и системным медиацентром требуется MediaBrowserService. Google рекомендует реализовывать MediaBrowserService во всех приложениях с длительным аудиовоспроизведением.
Используйте команду adb shell dumpsys media_session для просмотра активных сессий, их Callback и PlaybackState. Утилита покажет все зарегистрированные сессии с тегом, активностью и последним известным состоянием — удобный инструмент для дебага.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также