Skip to content

Instantly share code, notes, and snippets.

@IMoHaMeDHaMdYI
Last active January 27, 2019 22:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IMoHaMeDHaMdYI/9116d1f67a44af77f2ddbb93c249bc6e to your computer and use it in GitHub Desktop.
Save IMoHaMeDHaMdYI/9116d1f67a44af77f2ddbb93c249bc6e to your computer and use it in GitHub Desktop.
class MusicService : MediaBrowserServiceCompat() {
private var mMediaSession: MediaSessionCompat? = null
private lateinit var mStateBuilder: PlaybackStateCompat.Builder
private var mExoPlayer: SimpleExoPlayer? = null
private var oldUri: Uri? = null
private val mMediaSessionCallback = object : MediaSessionCompat.Callback() {
override fun onPlayFromUri(uri: Uri?, extras: Bundle?) {
super.onPlayFromUri(uri, extras)
uri?.let {
val mediaSource = extractMediaSourceFromUri(uri)
if (uri != oldUri)
play(mediaSource)
else play() // this song was paused so we don't need to reload it
oldUri = uri
}
}
override fun onPause() {
super.onPause()
pause()
}
override fun onStop() {
super.onStop()
stop()
}
}
override fun onCreate() {
super.onCreate()
initializePlayer()
initializeExtractor()
initializeAttributes()
mMediaSession = MediaSessionCompat(baseContext, "tag for debugging").apply {
// Enable callbacks from MediaButtons and TransportControls
setFlags(
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
)
// Set initial PlaybackState with ACTION_PLAY, so media buttons can start the player
mStateBuilder = PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PLAY_PAUSE)
setPlaybackState(mStateBuilder.build())
// methods that handle callbacks from a media controller
setCallback(mMediaSessionCallback)
// Set the session's token so that client activities can communicate with it
setSessionToken(sessionToken)
isActive = true
}
}
private var mAttrs: AudioAttributes? = null
private fun play(mediaSource: MediaSource) {
if (mExoPlayer == null) initializePlayer()
mExoPlayer?.apply {
// AudioAttributes here from exoplayer package !!!
mAttrs?.let { initializeAttributes() }
// In 2.9.X you don't need to manually handle audio focus :D
setAudioAttributes(mAttrs, true)
prepare(mediaSource)
play()
}
}
private fun play() {
mExoPlayer?.apply {
mExoPlayer?.playWhenReady = true
updatePlaybackState(PlaybackStateCompat.STATE_PLAYING)
mMediaSession?.isActive = true
}
}
private fun initializePlayer() {
mExoPlayer = ExoPlayerFactory.newSimpleInstance(
this, DefaultRenderersFactory(baseContext)
, DefaultTrackSelector(),
DefaultLoadControl()
)
}
private fun pause() {
mExoPlayer?.apply {
playWhenReady = false
if (playbackState == PlaybackStateCompat.STATE_PLAYING) {
updatePlaybackState(PlaybackStateCompat.STATE_PAUSED)
}
}
}
private fun stop() {
// release the resources when the service is destroyed
mExoPlayer?.playWhenReady = false
mExoPlayer?.release()
mExoPlayer = null
updatePlaybackState(PlaybackStateCompat.STATE_NONE)
mMediaSession?.isActive = false
mMediaSession?.release()
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
stopSelf()
}
override fun onDestroy() {
super.onDestroy()
stop()
}
private fun updatePlaybackState(state: Int) {
// You need to change the state because the action taken in the controller depends on the state !!!
mMediaSession?.setPlaybackState(
PlaybackStateCompat.Builder().setState(
state // this state is handled in the media controller
, 0L
, 1.0f // Speed playing
).build()
)
}
private fun initializeAttributes() {
mAttrs = AudioAttributes.Builder().setUsage(C.USAGE_MEDIA)
.setContentType(C.CONTENT_TYPE_MUSIC)
.build()
}
private lateinit var mExtractorFactory: ExtractorMediaSource.Factory
private fun initializeExtractor() {
val userAgent = Util.getUserAgent(baseContext, "Application Name")
mExtractorFactory = ExtractorMediaSource.Factory(DefaultDataSourceFactory(this, userAgent))
.setExtractorsFactory(DefaultExtractorsFactory())
}
private fun extractMediaSourceFromUri(uri: Uri): MediaSource {
return mExtractorFactory.createMediaSource(uri)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment