Introduction
The android media viewer mediaplayer MediaSessionCompat tutorial series describes how to set up the MediaSession and its callback. Which will receive requests from the the MediaController and then pass them onto the MediaPlayer.
Get Code
The code can be found on github from the following instructions below
https://github.com/mobapptuts/media-thumbnail-viewer.git Tag
media-viewer-mediasession
or you can run this command
git clone https://github.com/mobapptuts/media-thumbnail-viewer.git –branch
media-viewer-mediasession
This video describes how to import the code from github using android studio and also how to use git tags
Steps
Create the members to support the MediaSession callback
Now is a good time to add the TAG which normally gets done at the start
private static final String TAG = "VideoPlayActivity";
Add the PlaybackStateCompat & MediaSessionCompat members
private PlaybackStateCompat.Builder mPBuilder; private MediaSessionCompat mSession;
Create the MediaSession callback class
All of the previous code that calls directly to the MediaPlayer will be moved into the MediaSession callback. Note a new method for releasing the MediaSession and MediaPlayer resources is implemented.
And the SurfaceHolder implementation is also relocated inside the MediaSession callback class because it is required for the creation of the MediaPlayer
All references to the UI are replaced by updating the MediaSession of the media player’s state.
And the audio focus implementation is also relocated to the media session callback.
private class MediaSessionCallback extends MediaSessionCompat.Callback implements SurfaceHolder.Callback, MediaPlayer.OnCompletionListener, AudioManager.OnAudioFocusChangeListener { private Context mContext; private AudioManager mAudioManager; private IntentFilter mNoisyIntentFilter; private AudioBecommingNoisy mAudioBecommingNoisy; public MediaSessionCallback(Context context) { super(); mContext = context; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioBecommingNoisy = new AudioBecommingNoisy(); mNoisyIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); mSurfaceView.getHolder().addCallback(this); } private class AudioBecommingNoisy extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { mediaPause(); } } @Override public void onPlay() { super.onPlay(); mediaPlay(); } @Override public void onPause() { super.onPause(); mediaPause(); } @Override public void onStop() { super.onStop(); releaseResources(); } private void releaseResources() { mSession.setActive(false); if(mMediaPlayer != null) { mMediaPlayer.stop(); mMediaPlayer.reset(); mMediaPlayer.release(); mMediaPlayer = null; } } private void mediaPlay() { registerReceiver(mAudioBecommingNoisy, mNoisyIntentFilter); int requestAudioFocusResult = mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); if(requestAudioFocusResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { mSession.setActive(true); mPBuilder.setActions(PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_STOP); mPBuilder.setState(PlaybackStateCompat.STATE_PLAYING, mMediaPlayer.getCurrentPosition(), 1.0f, SystemClock.elapsedRealtime()); mSession.setPlaybackState(mPBuilder.build()); mMediaPlayer.start(); } } private void mediaPause() { mMediaPlayer.pause(); mPBuilder.setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_STOP); mPBuilder.setState(PlaybackStateCompat.STATE_PAUSED, mMediaPlayer.getCurrentPosition(), 1.0f, SystemClock.elapsedRealtime()); mSession.setPlaybackState(mPBuilder.build()); mAudioManager.abandonAudioFocus(this); unregisterReceiver(mAudioBecommingNoisy); } @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { mMediaPlayer = MediaPlayer.create(mContext, mVideoUri, surfaceHolder); mMediaPlayer.setOnCompletionListener(this); } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { } @Override public void onCompletion(MediaPlayer mediaPlayer) { mPBuilder.setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_STOP); mPBuilder.setState(PlaybackStateCompat.STATE_STOPPED, mMediaPlayer.getCurrentPosition(), 1.0f, SystemClock.elapsedRealtime()); mSession.setPlaybackState(mPBuilder.build()); } @Override public void onAudioFocusChange(int audioFocusChanged) { switch (audioFocusChanged) { case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: mediaPause(); break; case AudioManager.AUDIOFOCUS_GAIN: mediaPlay(); break; case AudioManager.AUDIOFOCUS_LOSS: mediaPause(); break; } } }
Initialise the PlaybackStateCompat & MediaSessionCompat members in onCreate
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_play); mPlayPauseButton = (ImageButton) findViewById(R.id.videoPlayPauseButton); mSurfaceView = (SurfaceView) findViewById(R.id.videoSurfaceView); Intent callingIntent = this.getIntent(); if(callingIntent != null) { mVideoUri = callingIntent.getData(); } mSession = new MediaSessionCompat(this, TAG); mSession.setCallback(new MediaSessionCallback(this)); mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); mPBuilder = new PlaybackStateCompat.Builder(); }
Remove all references to the media player in the activity methods
This is because the activity methods are directly related to the application UI. Therefore should not be calling the media player directly.
public void playPauseClick(View view) { } @Override protected void onStop() { super.onStop(); } @Override protected void onPause() { super.onPause(); }
Android media viewer mediaplayer MediaSessionCompat summary
In the android media viewer mediaplayer MediaSessionCompat tutorial we focused to the MediaSessionCompat and it’s callback. All the MediaPlayer calls are referred to from the MediaSessionCompat. And all the UI calls were required to be moved across to the MediaControllerCompat callback.
By extracting the media player calls from the UI allows the application to now support any number of media players.
The following tutorial will focus on the implementation of the MediaController callback.