I have been looking for a way to get rid of the nasty black initial screen on a VideoView before the start() method is run.
I have tried with background image on the widget but it doesnt work as expected at all. I have also tried putting an image of the first frame in the video on top of the VideoView and hiding it after the stars() method. Adding an onPrepared listener to start the video and then hide the image. This works but there is a horrible flicker in the transition and i don't know how to get rid of it.
Thanks for your reply. Adding the MediaController had no effect at all. The problem persists (I still see the black flicker) and I dont want to have the video controls visible at all. My code looks like this:
VideoView vSurface= (VideoView) findViewById(R.id.surfaceView1);
vSurface.setVideoURI(Uri.parse("android.resource://com.mypackage/" + R.raw.video1));
vSurface.setVisibility(View.VISIBLE);
vSurface.setOnPreparedListener(this);
vSurface.setDrawingCacheEnabled(true);
vSurface.setOnErrorListener(this);
I got the same problem and i found a solution. Its a little bit hacky but it do the trick. So basically you need to put your VideoView into a FrameLayout. Over the videoview you need to add another FrameLayout with the background of your video and when your video is loaded and ready to play you hide the placeholder.
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_marginTop="50dip" >
<VideoView
android:id="@+id/geoloc_anim"
android:layout_width="fill_parent"
android:layout_height="172dip" android:layout_gravity="top|center" android:visibility="visible"/>
<FrameLayout
android:id="@+id/placeholder"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="@drawable/fondvert_anim">
</FrameLayout>
In your activity you need to implements OnPreparedListener and add this
//Called when the video is ready to play
public void onPrepared(MediaPlayer mp) {
View placeholder = (View) findViewById(R.id.placeholder);
placeholder.setVisibility(View.GONE);
}
So when the video is ready we hide our placeholder and that trick avoid the black flicker screen.
Hope this help someone.
I meet the same problem, and solve it with the accepted solution above plus this:
@Override
public void onPrepared(MediaPlayer mp) {
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.d(TAG, "onInfo, what = " + what);
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
// video started; hide the placeholder.
placeholder.setVisibility(View.GONE);
return true;
}
return false;
}
});
I think onPrepared just means the video is ready to play, but not means video started playing. If hide placeholder in onPrepared, the screen still show a black screen.
On my Note3 and Nexus, this solution works well.
I had the same problem on Galaxy tab 2, Android 4.1.1.
Do videoView.setZOrderOnTop(true);
and next videoView.start()
It works fine for me.
I had same problem and this has worked for me ..
When you want to show video, make videoView.setZOrderOnTop(false); and when you want to hide video, just make videoView.setZOrderOnTop(true);
I 've got same problem I just used videov.setBackgroundColor(Color.WHITE) and then onprepare i used Color.TRANSPARENT) white is still better than black for me
By extending a TextureView, I get no black screens in the beginning or end. This is if you want to avoid using ZOrderOnTop(true)
.
public class MyVideoView extends TextureView implements TextureView.SurfaceTextureListener {
private MediaPlayer mMediaPlayer;
private Uri mSource;
private MediaPlayer.OnCompletionListener mCompletionListener;
private boolean isLooping = false;
public MyVideoView(Context context) {
this(context, null, 0);
}
public MyVideoView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setSurfaceTextureListener(this);
}
public void setSource(Uri source) {
mSource = source;
}
public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
mCompletionListener = listener;
}
public void setLooping(boolean looping) {
isLooping = looping;
}
@Override
protected void onDetachedFromWindow() {
// release resources on detach
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
super.onDetachedFromWindow();
}
/*
* TextureView.SurfaceTextureListener
*/
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Surface surface = new Surface(surfaceTexture);
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setLooping(isLooping);
mMediaPlayer.setDataSource(getContext(), mSource);
mMediaPlayer.setSurface(surface);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
mMediaPlayer.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
surface.release();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}
This worked for me:
videoView.setBackgroundColor(Color.WHITE); // Your color.
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
videoView.setBackgroundColor(Color.TRANSPARENT);
}
});
At least two years later, but I hope that was helpful.
This is definitely hacky, but better than overlaying an image (IMO).
boolean mRestored = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRestored = savedInstanceState != null;
}
@Override
public void onPrepared(MediaPlayer mp) {
if (!mRestored) vSurface.seekTo(1);
}
Assuming you are putting things into savedInstanceState
in onSaveInstanceState
.
None of the Above worked for me.
In my case, onPrepared
gets called BEFORE the black frame went away, so I would still see the black frame.
I needed a solution where the video appeared shortly after the first frame.
So what I did was set the VideoView alpha to 0 in xml:
android:alpha="0"
and then before I start the video I animate the alpha back to 1:
videoView.animate().alpha(1);
videoView.seekTo(0);
videoView.start();
alternatively, you can just post a delayed Runnable to set the alpha to 1, instead of animating it.
Just use VideoView#setBackgroundDrawable(), I think.
initial settings.
VideoView.setBackgroundDrawable(yourdrawableid);
start video
VideoView.start(); VideoView.setBackgroundDrawable(0);
Just show a frame from the video as preview.
vSurface.SeekTo(100);
For people still looking for answer for this, calling VideoView.start()
and VideoView.pause()
in succession inside onPrepared
worked for me. I know this may not be the ideal way of achieving this however it might be the one with minimal workaround required in the code. Hope this works for you too.
@Override
public void onPrepared(MediaPlayer mp) {
mVideoView.start();
mVideoView.pause();
}
This one works for me :
In XML : VideoView hide behind a Relative layout with white Background
<VideoView
android:id="@+id/myVideo"
android:layout_below="@+id/logo_top"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
/>
<RelativeLayout
android:id="@+id/mask"
android:background="#FFFFFF"
android:layout_below="@+id/logo_top"
android:layout_centerHorizontal="true"
android:layout_width="200dp" android:layout_height="200dp"
>
</RelativeLayout>
and in Activity : onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.acceuil);
myVideo = (VideoView) findViewById(R.id.myVideo);
mask = (RelativeLayout) findViewById(R.id.mask);
String path = "android.resource://"
+ getPackageName() + "/" + R.raw.anim_normal;
myVideo.setVideoURI(Uri.parse(path));
myVideo.start();
}
onStart :
public void onStart() {
final long time = System.currentTimeMillis();
super.onStart();
new CountDownTimer(5000, 100) {
@Override
public void onTick(long l) {
long time2 = System.currentTimeMillis();
if((time2 - time) > 500) {
mask.setVisibility(View.GONE);
}
}
}.start();
Hope this helps.
It works for me on both Activity and Fragment.
VideoView mVideo = (VideoView) findViewById(R.id.yourViewViewId);
mVideo.setVideoURI(mUri);
mVideo.setZOrderOnTop(false);
SurfaceHolder surfaceholder = mVideo.getHolder();
surfaceholder.setFormat(PixelFormat.TRANSPARENT);
It's a little late for this answer, but maybe other users have the same problem and find this question..
I have dealt with it, by setting a BackgroundResource initially and then, when starting the video, i have set the background to an invisible color..
VideoView myView = findViewById(R.id.my_view);
myView.setBackgroundResource(R.drawable.some_resource);
// some stuff
// this is when starting the video
myView.setVideoUri(someUri);
// also set MediaController somewhere...
//...
// now set the backgroundcolor to be not visible (first val of Color.argb(..) is the alpha)
myView.setBackGroundColor(Color.argb(0, 0, 0, 0));
//...
myView.start();
This is a nice solution:
package com.example.videoviewpractice;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;
public class MainActivity extends Activity {
VideoView myVideoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initVideo();
}
private void initVideo() {
myVideoView = (VideoView) findViewById(R.id.videoView1);
String url = "http://mtc.cdn.vine.co/r/videos/3DF00EB7001110633055418310656_1e50d6d9a65.3.2.mp4?" +
"versionId=KVMUFFGqe6rYRrGKgl8hxL6eakVAErPy";
myVideoView.setVideoURI(Uri.parse(url));
myVideoView.setMediaController(new MediaController(this));
myVideoView.requestFocus();
}
public void gone(View v){
myVideoView.setZOrderOnTop(true);
View placeholder = (View) findViewById(R.id.placeholder);
placeholder.setVisibility(View.GONE);
myVideoView.start();
}
}
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_marginTop="50dip" >
<VideoView
android:id="@+id/videoView1"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="top|center"
android:visibility="visible" />
<FrameLayout
android:id="@+id/placeholder"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="top|center"
android:background="@drawable/ic_launcher"
android:onClick="gone" >
</FrameLayout>
</FrameLayout>
</LinearLayout>
To avoid annoying flickering and black screen issues I wrote FrameVideoView.
It takes benefits from 'placeholder solution' and (if your device is running API level 14 or higher) from TextureView
, which is much more efficient than VideoView
.
I wrote article on our blog to cover what it actually does.
It's simple to use:
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();
}
}
Use svVideoView.seekTo(position).
Give Position within 5 (ms).
onPause():
position=svVideoView.getCurrentPosition()
onResume():
svVideoView.seekTo(position);
I had the same issue. I found that the main reason for that was the use of FrameLayout
as the parent layout. Use RelativeLayout
as the parent layout of the VideoView
Modifying @emmgfx's answer worked for me:
videoView.setBackgroundColor(Color.WHITE)
videoView.start()
Timer().schedule(100){
videoView?.setBackgroundColor(Color.TRANSPARENT)
}
Trick is to delay the video view untill video loads. PS : It's kotlin.
see this
VideoView videoView = (VideoView) findViewById(R.id.VideoView);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
Uri video = Uri.parse("android.resource://your_package_name/"+R.raw.monkeysonthebed_video);
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.start();
来源:https://stackoverflow.com/questions/9765629/android-videoview-black-screen