I ended up having to do something very similar to @tommyd to avoid the black surfaceView flash at the beginning and end of my videos. However, I found that setting/nulling the background drawable for the videoView was not occurring instantly on many phones. There could be about a half-second delay between my call to set the background and when it was actually displayed.
What I ended up doing was creating a custom SurfaceView that showed a single, solid color, then overlayed this on top of the VideoView and made use of SurfaceView.setZOrderMediaOverlay().
My custom SurfaceView was heavily informed by:
http://android-er.blogspot.com/2010/05/android-surfaceview.html
public class SolidSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = SolidSurfaceView.class.getSimpleName();
private SolidSurfaceThread mThread;
private boolean mSurfaceIsValid;
private int mColor;
public SolidSurfaceView(Context context) {
super(context);
init();
}
public SolidSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SolidSurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
Log.verbose(TAG, "init");
getHolder().addCallback(this);
setZOrderMediaOverlay(true);
}
public void setColor(int color) {
mColor = color;
invalidate();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.verbose(TAG, "surfaceCreated");
mSurfaceIsValid = true;
mThread = new SolidSurfaceThread(getHolder(), this);
mThread.setRunning(true);
mThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.verbose(TAG, "surfaceDestroyed");
mSurfaceIsValid = false;
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
}
catch (InterruptedException e) {
Log.warning(TAG, "Thread join interrupted");
}
}
mThread = null;
}
@Override
protected void onDraw(Canvas canvas) {
if ( ! mSurfaceIsValid) {
return;
}
canvas.drawColor(mColor);
}
private static class SolidSurfaceThread extends Thread {
private final SurfaceHolder mSurfaceHolder;
private final SolidSurfaceView mSurfaceView;
private boolean mIsRunning;
public SolidSurfaceThread(SurfaceHolder surfaceHolder, SolidSurfaceView surfaceView) {
mSurfaceHolder = surfaceHolder;
mSurfaceView = surfaceView;
}
public void setRunning(boolean running) {
mIsRunning = running;
}
@Override
public void run() {
while (mIsRunning) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
mSurfaceView.onDraw(c);
}
}
finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
And in the parent activity that hosts the views:
mVideoView = (VideoView)findViewById(R.id.video_view);
mVideoMask = (SolidSurfaceView)findViewById(R.id.video_mask);
mVideoMask.setColor(Color.BLUE);
You can then do things like mVideoMask.setVisibility(View.GONE)
to hide the mask or mVideoMask.setVisibility(View.VISIBLE)
to show the mask (and hide the black-screened VideoView).
In my experiments on various phones, this method provided very fast showing/hiding of the video mask, as opposed to setting/nulling the background.