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(); }