Custom Android Media Controller

The default media controller of Android typically contains the buttons like "Play/Pause", "Rewind", "Fast Forward" and a progress slider. Instead of "Rewind" and "Fast Forward" buttons, sometimes what we need is a full screen toggle button. Based on this StackOverflow post, we can implement our own media controller instead of scratching in this post.
Pre-Conditions
- Download VideoControllerView.java and change the package name to match your project
- Download media_controller.xml into your project’s layout folder
- Download the 4 images into your project’s drawable folder: ic_media_play.png, ic_media_pause.png, ic_media_fullscreen_shrink.png and ic_media_fullscreen_stretch.png

- Visit Android Holo Colors Generator to create the style of SeekBar, and put them in drawable(or mipmap) and values/style.xml

style.xml
Create an Activity(FullscreenVideoActivity.java) with Layout(activity_fullscreen_video.xml)
FullscreenVideoActivity.java
- Initial MediaPlayer and VideoControlView
- Implement interface SurfaceHolder.Callback
// Implement SurfaceHolder.Callback @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceCreated(SurfaceHolder holder) { mediaPlayer.setDisplay(holder); mediaPlayer.prepareAsync(); } @Override public void surfaceDestroyed(SurfaceHolder holder) {} // End SurfaceHolder.Callback - Implement interface MediaPlayer.OnPreparedListener
// Implement MediaPlayer.OnPreparedListener @Override public void onPrepared(MediaPlayer mp) { controller.setMediaPlayer(this); controller.setAnchorView((FrameLayout) findViewById(R.id.videoSurfaceContainer)); mediaPlayer.start(); } // End MediaPlayer.OnPreparedListener - Implement interface VideoControllerView.MediaPlayerControl
In the project, we implement toggleFullScreen() and isFullScreen() to switch between normal(PORTRAIT) and full-screen mode(LANDSCAPE).// Implement VideoMediaController.MediaPlayerControl @Override public boolean canPause() { return true; } @Override public boolean canSeekBackward() { return true; } @Override public boolean canSeekForward() { return true; } @Override public int getBufferPercentage() { return 0; } @Override public int getCurrentPosition() { return mediaPlayer.getCurrentPosition(); } @Override public int getDuration() { return mediaPlayer.getDuration(); } @Override public boolean isPlaying() { return mediaPlayer.isPlaying(); } @Override public void pause() { mediaPlayer.pause(); } @Override public void seekTo(int i) { mediaPlayer.seekTo(i); } @Override public void start() { mediaPlayer.start(); } @Override public boolean isFullScreen() { boolean isFullScreen = (getResources().getConfiguration().orientation==2); Log.d(TAG, "isFullScreen: "+isFullScreen); return isFullScreen; } @Override public void toggleFullScreen() { Log.d(TAG, "toggleFullScreen"); mediaPlayer.pause(); if(getResources().getConfiguration().orientation==1){ this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }else{ this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } } - Implement touch event to show media controller
//Show the media controller @Override public boolean onTouchEvent(MotionEvent event) { controller.show(); return false; }
public class FullscreenVideoActivity extends Activity implements SurfaceHolder.Callback,
MediaPlayer.OnPreparedListener, VideoControllerView.MediaPlayerControl {
private String TAG = "FullscreenVideoActivity";
SurfaceView videoSurface;
private MediaPlayer mediaPlayer;
private VideoControllerView controller;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen_video);
videoSurface = (SurfaceView) findViewById(R.id.videoSurface);
SurfaceHolder videoHolder = videoSurface.getHolder();
videoHolder.addCallback(this);
String videoPath = "android.resource://" + getPackageName() + "/" + R.raw
.sample_video;
mediaPlayer = new MediaPlayer();
controller = new VideoControllerView(this);
try {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(this, Uri.parse(videoPath));
mediaPlayer.setOnPreparedListener(this);
} catch (IllegalArgumentException | SecurityException | IllegalStateException |
IOException e) {
e.printStackTrace();
}
}
}
activity_fullscreen_video.xml
- Default layout(PORTRAIT)
- Create LANDSCAPE layout
Create a folder named layout-land in res, and create a layout file with the same name as activity_fullscreen_video.xml in it.

Comment the unused component in VideoControllerView.java
private void initControllerView(View v) {
mPauseButton = (ImageButton) v.findViewById(R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
mFullscreenButton = (ImageButton) v.findViewById(R.id.fullscreen);
if (mFullscreenButton != null) {
mFullscreenButton.requestFocus();
mFullscreenButton.setOnClickListener(mFullscreenListener);
}
// mFfwdButton = (ImageButton) v.findViewById(R.id.ffwd);
// if (mFfwdButton != null) {
// mFfwdButton.setOnClickListener(mFfwdListener);
// if (!mFromXml) {
// mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
// }
// }
//
// mRewButton = (ImageButton) v.findViewById(R.id.rew);
// if (mRewButton != null) {
// mRewButton.setOnClickListener(mRewListener);
// if (!mFromXml) {
// mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
// }
// }
// By default these are hidden. They will be enabled when setPrevNextListeners() is called
// mNextButton = (ImageButton) v.findViewById(R.id.next);
// if (mNextButton != null && !mFromXml && !mListenersSet) {
// mNextButton.setVisibility(View.GONE);
// }
// mPrevButton = (ImageButton) v.findViewById(R.id.prev);
// if (mPrevButton != null && !mFromXml && !mListenersSet) {
// mPrevButton.setVisibility(View.GONE);
// }
mProgress = (SeekBar) v.findViewById(R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
seeker.setOnSeekBarChangeListener(mSeekListener);
}
mProgress.setMax(1000);
}
mEndTime = (TextView) v.findViewById(R.id.time);
mCurrentTime = (TextView) v.findViewById(R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
installPrevNextListeners();
}
Result
