How to avoid flickering and black screen issues when using VideoView?

VideoView is the most straightforward way to show video content in layout.
It took a few lines of code to setup and show for example mp4 file.
It’s fine when you don’t care about UX too much, but when you do, things are going to be annoying.

When you tested app for different cases like: change device orientation, swipe the view, lock screen or go to home screen and back to the app, you probably know what I’m talking about.
If you don’t, take a look at:

VideoView Black Screen
VideoView Black Flash Before and After Playing
VideoView Inside Fragment Causes Black Screen Flickering
VideoView Flickering Issue

Workaround

To deal with these problems we can use ‘placeholder solution’ described in the above links.
The idea is to show placeholder, which has the same color as video background, when VideoView is not ready to show the content yet. When VideoView is ready the placeholder will go away and already prepared video will be revealed without any issues.
Thereby we achieve nice solid experience, because user doesn’t see how system prepares video to render it, which causes VideoView displays black screen or the content flickering. If you want to observe these issues try to move the app to the background (by pressing home screen button) and bring back the app to the foreground.
If it still seems to work well, try it a couple of times… it will happen ;)

FrameVideoView

FrameVideoView is a class which implements ‘placeholder workaround’ dynamically by creating views in runtime. You don’t have to create additional layout for placeholder and put VideoView in there nor have you to take care about showing and hiding placeholder in an appropriate time. FrameVideoView does it for you.
If device is running API level 13 or below, VideoView will be used to show video content. This approach should fix most of the flickering and black screen issues.
For devices running API level 14 or higher, TextureView will be used to show video content. It provides a lot better performance than VideoView implementation because it was created to show ‘stream content’ like video or OpenGL scenes.

I wrote app with ViewPager where each of three fragments has different video and are playing simultaneously. When FrameVideoView used VideoView implementation there were problems because sometimes black screen issues appeared again when swiping. There was also the problem when user swiped to the last page and ViewPager showed overscroll animation that can’t overlay VideoView. When TextureView implementation was used all problems were gone and app worked as expected.

How to use it?

Add FrameVideoView to layout:

  <mateuszklimek.framevideoview.FrameVideoView
    android:id="@+id/frame_video_view"
    android:layout_width="@dimen/video_width"
    android:layout_height="@dimen/video_height"
  />

find its instance in Activity and call corresponding methods in onResume and onPause:

public class SampleActivity extends Activity {

  private FrameVideoView videoView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple);

    String uriString = "android.resource://" + getPackageName() + "/" + R.raw.movie;
    videoView = (FrameVideoView) findViewById(R.id.frame_video_view);
    videoView.setup(Uri.parse(uriString), Color.GREEN);
  }

    @Override
    protected void onResume() {
      super.onResume();
      videoView.onResume();
    }

    @Override
    protected void onPause() {
      videoView.onPause();
      super.onPause();
    }
  }
  

If you want to execute method for particular implementation eg. seekTo() from VideoView you can call it like that:

  frameVideoView.asVideoView().seekTo(x);

but before, it’s better to check what type of implementation is used:

if(videoView.getImplType() == VIDEO_VIEW){
    frameVideoView.asVideoView().seekTo(x);
}


I uploaded project to github so you can run example app and see full implementation of FrameVideoView. Feel free to use it as you like.

Written on January 11, 2015