Last active
January 27, 2019 22:36
-
-
Save IMoHaMeDHaMdYI/9116d1f67a44af77f2ddbb93c249bc6e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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