diff --git a/app/src/main/java/com/example/android/classicalmusicquiz/QuizActivity.java b/app/src/main/java/com/example/android/classicalmusicquiz/QuizActivity.java index e0cd02a8..f6fcad22 100644 --- a/app/src/main/java/com/example/android/classicalmusicquiz/QuizActivity.java +++ b/app/src/main/java/com/example/android/classicalmusicquiz/QuizActivity.java @@ -24,8 +24,9 @@ import android.os.Bundle; import android.os.Handler; import android.support.v4.content.ContextCompat; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; import android.support.v7.app.AppCompatActivity; -import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; @@ -64,6 +65,8 @@ public class QuizActivity extends AppCompatActivity implements View.OnClickListe private Button[] mButtons; private SimpleExoPlayer mExoPlayer; private SimpleExoPlayerView mPlayerView; + private MediaSessionCompat mMediaSession; + private PlaybackStateCompat.Builder mStateBuilder; @Override @@ -108,9 +111,9 @@ protected void onCreate(Bundle savedInstanceState) { // Initialize the buttons with the composers names. mButtons = initializeButtons(mQuestionSampleIDs); - // TODO (1): Create a method to initialize the MediaSession. It should create the MediaSessionCompat object, set the flags for external clients, set the available actions you want to support, and start the session. - // TODO (2): Create an inner class that extends MediaSessionCompat.Callbacks, and override the onPlay(), onPause(), and onSkipToPrevious() callbacks. Pass an instance of this class into the MediaSession.setCallback() method in the method you created in TODO 1. - + // Initialize the Media Session. + initializeMediaSession(); + Sample answerSample = Sample.getSampleByID(this, mAnswerSampleID); if (answerSample == null) { @@ -123,6 +126,41 @@ protected void onCreate(Bundle savedInstanceState) { initializePlayer(Uri.parse(answerSample.getUri())); } + /** + * Initializes the Media Session to be enabled with media buttons, transport controls, callbacks + * and media controller. + */ + private void initializeMediaSession() { + + // Create a MediaSessionCompat. + mMediaSession = new MediaSessionCompat(this, TAG); + + // Enable callbacks from MediaButtons and TransportControls. + mMediaSession.setFlags( + MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | + MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); + + // Do not let MediaButtons restart the player when the app is not visible. + mMediaSession.setMediaButtonReceiver(null); + + // Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player. + mStateBuilder = new PlaybackStateCompat.Builder() + .setActions( + PlaybackStateCompat.ACTION_PLAY | + PlaybackStateCompat.ACTION_PAUSE | + PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | + PlaybackStateCompat.ACTION_PLAY_PAUSE); + + mMediaSession.setPlaybackState(mStateBuilder.build()); + + + // MySessionCallback has methods that handle callbacks from a media controller. + mMediaSession.setCallback(new MySessionCallback()); + + // Start the Media Session since the activity is active. + mMediaSession.setActive(true); + + } /** * Initializes the button to the correct views, and sets the text to the composers names, @@ -266,9 +304,9 @@ private void showCorrectAnswer() { */ @Override protected void onDestroy() { - // TODO (4): When the activity is destroyed, set the MediaSession to inactive. super.onDestroy(); releasePlayer(); + mMediaSession.setActive(false); } @@ -286,15 +324,23 @@ public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray tra public void onLoadingChanged(boolean isLoading) { } + /** + * Method that is called when the ExoPlayer state changes. Used to update the MediaSession + * PlayBackState to keep in sync. + * @param playWhenReady true if ExoPlayer is playing, false if it's paused. + * @param playbackState int describing the state of ExoPlayer. Can be STATE_READY, STATE_IDLE, + * STATE_BUFFERING, or STATE_ENDED. + */ @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { if((playbackState == ExoPlayer.STATE_READY) && playWhenReady){ - // TODO (3): When ExoPlayer is playing, update the PlayBackState. - Log.d(TAG, "onPlayerStateChanged: PLAYING"); + mStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING, + mExoPlayer.getCurrentPosition(), 1f); } else if((playbackState == ExoPlayer.STATE_READY)){ - // TODO (3): When ExoPlayer is paused, update the PlayBackState. - Log.d(TAG, "onPlayerStateChanged: PAUSED"); + mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED, + mExoPlayer.getCurrentPosition(), 1f); } + mMediaSession.setPlaybackState(mStateBuilder.build()); } @Override @@ -304,4 +350,24 @@ public void onPlayerError(ExoPlaybackException error) { @Override public void onPositionDiscontinuity() { } + + /** + * Media Session Callbacks, where all external clients control the player. + */ + private class MySessionCallback extends MediaSessionCompat.Callback { + @Override + public void onPlay() { + mExoPlayer.setPlayWhenReady(true); + } + + @Override + public void onPause() { + mExoPlayer.setPlayWhenReady(false); + } + + @Override + public void onSkipToPrevious() { + mExoPlayer.seekTo(0); + } + } }