feat(service): add ExoPlayer controller and MediaSessionService

This commit is contained in:
nk
2026-06-01 12:21:22 +03:00
parent 9d68459df6
commit cf79af5273
2 changed files with 114 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
package com.radiola.service
import android.content.Context
import androidx.media3.common.AudioAttributes
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class PlayerController @Inject constructor(
@ApplicationContext context: Context
) {
private val _isPlaying = MutableStateFlow(false)
val isPlaying: StateFlow<Boolean> = _isPlaying
private val _currentStationPrefix = MutableStateFlow<String?>(null)
val currentStationPrefix: StateFlow<String?> = _currentStationPrefix
val exoPlayer: ExoPlayer = ExoPlayer.Builder(context)
.setAudioAttributes(
AudioAttributes.Builder()
.setUsage(C.USAGE_MEDIA)
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.build(),
true
)
.setHandleAudioBecomingNoisy(true)
.build()
.apply {
addListener(object : Player.Listener {
override fun onIsPlayingChanged(playing: Boolean) {
_isPlaying.value = playing
}
})
}
fun play(url: String, stationPrefix: String) {
val mediaItem = MediaItem.fromUri(url)
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.play()
_currentStationPrefix.value = stationPrefix
}
fun pause() {
exoPlayer.pause()
}
fun stop() {
exoPlayer.stop()
_currentStationPrefix.value = null
}
fun release() {
exoPlayer.release()
}
}

View File

@@ -0,0 +1,51 @@
package com.radiola.service
import android.app.PendingIntent
import android.content.Intent
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
import com.radiola.MainActivity
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
@UnstableApi
class PlayerService : MediaSessionService() {
@Inject
lateinit var playerController: PlayerController
private var mediaSession: MediaSession? = null
override fun onCreate() {
super.onCreate()
mediaSession = MediaSession.Builder(this, playerController.exoPlayer)
.setSessionActivity(
PendingIntent.getActivity(
this,
0,
Intent(this, MainActivity::class.java),
PendingIntent.FLAG_IMMUTABLE
)
)
.build()
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? = mediaSession
override fun onTaskRemoved(rootIntent: Intent?) {
if (!playerController.isPlaying.value) {
stopSelf()
}
}
override fun onDestroy() {
mediaSession?.run {
player.release()
release()
}
mediaSession = null
super.onDestroy()
}
}