Android: MediaPlayer gapless or seamless Video Playing
- by John Wang
I can play the videos fine back to back by implementing the OnCompletionListener to set the data source to a different file. No problems there. I call reset() and prepare() just fine.
What I haven't been able to figure out, is how to get rid of the 1-2 second gap screen flicker between the data source change and the new video starting. The gap shows a black screen, and I haven't found any way to get around it.
I've tried setting the background of the parent view to an image, but it manages to bypass that. Even if the SurfaceView is transparent (which it is by default.) I've also tried to have the multiple video files played at the same time, and switching mediaplayer's display when one ends and the other is supposed to start.
The last thing I tried, was to have a second view in the background that I show temporarily while the video is "preparing" and removing it when the video is ready to start. That also wasn't very seamless.
Is there any way to get rid of that gap. Running a video in a loop works wonderfully and does exactly what I want with the exception that it's looking through the same video instead of playing a different one that I pick.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:background="@drawable/background"
android:layout_height="fill_parent">
<SurfaceView
android:id="@+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center">
</SurfaceView>
</FrameLayout>
Player.java
public class Player extends Activity implements
OnCompletionListener, MediaPlayer.OnPreparedListener, SurfaceHolder.Callback {
private MediaPlayer player;
private SurfaceView surface;
private SurfaceHolder holder;
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.main);
surface = (SurfaceView)findViewById(R.id.surface);
holder = surface.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void onCompletion(MediaPlayer arg0) {
File clip = new File(Environment.getExternalStorageDirectory(),"file2.mp4");
playVideo(clip.getAbsolutePath());
}
public void onPrepared(MediaPlayer mediaplayer) {
holder.setFixedSize(player.getVideoWidth(), player.getVideoHeight());
player.start();
}
private void playVideo(String url) {
try {
File clip = new File(Environment.getExternalStorageDirectory(),"file1.mp4");
if (player == null) {
player = new MediaPlayer();
player.setScreenOnWhilePlaying(true);
}
else {
player.stop();
player.reset();
}
player.setDataSource(url);
player.setDisplay(holder);
player.setOnPreparedListener(this);
player.prepare();
player.setOnCompletionListener(this);
}
catch (Throwable t) {
Log.e("ERROR", "Exception Error", t);
}
}