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 обезбеђује пун циклус управљања медијима: сервис пружа стабло садржаја (плејлисте, каталоге), а сесија прима команде навигације и репродукције. Ово је архитектура коју 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 ms у нормалним условима.
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 преноси ове команде у ACTION_MEDIA_BUTTON intent-е, које пресреће 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 за категорију Музика и Аудио.
Почев од Android 11, системски медијски центар (Media Control Panel) приказује до 5 недавних MediaSession у панелу обавештења. Корисник може управљати плејером без отварања апликације. За коректан приказ потребно је имплементирати MediaBrowserService и правилно попуњавати PlaybackState.
Media Control Panel приказује: назив песме, извођача, омот (из MediaMetadata), дугмад за управљање (из дозвољених радњи PlaybackState-а). Ако апликација не ажурира PlaybackState најмање једном у 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође