VideoView onPrepared is not called if the VideoView is invisible
Solution 1
You could try setting alpha channel of video view to 0 or close to 0.
Solution 2
Solved it making its layout invisible instead of videoView itself. Thanks to @J.Kowalski .
Layout:
<FrameLayout
android:id="@+id/layout_video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:scrollbars="none"/>
</FrameLayout>
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
/>
Set OnPreparedListener:
videoView.setOnPreparedListener(this);
Show progress bar before ready:
@Override
public void showProgress() {
progress.setVisibility(View.VISIBLE);
layoutVideoView.setVisibility(View.INVISIBLE);
}
Load video URI:
@Override
public void loadVideo(Uri uri) {
videoView.setVideoURI(uri);
}
When its ready, onPrepared is called:
@Override
public void onPrepared(MediaPlayer mp) {
Log.d("debug", "onPrepared");
iStepPreviewPresenter.onVideoViewReady();
}
Finally show layout and start video:
@Override
public void hideProgress() {
progress.setVisibility(View.INVISIBLE);
layoutVideoView.setVisibility(View.VISIBLE);
}
@Override
public void startVideo() {
videoView.start();
}
Nailed it!
Solution 3
It can be achieved by one of these tricks
You can set the height and width of the
VideoView
to1px
until the video is prepared and then switch to full screen by changing the properties tomatch parent
-
As @FDIM said in his answer, we can set the alpha value of the view to 0 until video is prepared. But it works only if we use TextureView to load the video. It doesn't work with normal
VideoView
. Here is a custom VideoView extendingTextureView
which mimics the defaultVideoVideo
implementation. This class can be directly used in xml file and can set the alpha to 0 to hide the video.public class TextureVideoView extends TextureView implements SurfaceTextureListener { private MediaPlayer mMediaPlayer; public TextureVideoView(Context context) { super(context); init(); } public TextureVideoView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mMediaPlayer = new MediaPlayer(); this.setSurfaceTextureListener(this); } public void seekTo(int msec) { mMediaPlayer.seekTo(msec); } public void setVideoPath(final String path) throws IOException { mMediaPlayer.reset(); mMediaPlayer.setDataSource(path); mMediaPlayer.prepare(); } public void setVideoPath(FileDescriptor fd, long offset, long length) throws IOException { mMediaPlayer.reset(); mMediaPlayer.setDataSource(fd, offset, length); mMediaPlayer.prepare(); } public void setVideoURI(Context context, Uri uri) throws IOException { mMediaPlayer.reset(); mMediaPlayer.setDataSource(context, uri); } public void setOnPreparedListener(OnPreparedListener onPreparedListener) { mMediaPlayer.setOnPreparedListener(onPreparedListener); } public void setOnCompletionListener(OnCompletionListener onCompletionListener) { mMediaPlayer.setOnCompletionListener(onCompletionListener); } public void setOnErrorListener(OnErrorListener onErrorListener) { mMediaPlayer.setOnErrorListener(onErrorListener); } public void start() { mMediaPlayer.start(); } public void pause() { mMediaPlayer.pause(); } public void setVolume(float leftVolume, float rightVolume ) { mMediaPlayer.setVolume(leftVolume, rightVolume); } public boolean isPlaying() { return mMediaPlayer.isPlaying(); } public void stopPlayback() { mMediaPlayer.stop(); } public void reset() { mMediaPlayer.reset(); } public void release() { mMediaPlayer.release(); } @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mMediaPlayer.setSurface(new Surface(surface)); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { }
Related videos on Youtube
Abhishek V
Android developer. Love reading books and watching movies/tv series/cricket :) #SOreadytohelp linkedin | email
Updated on June 27, 2022Comments
-
Abhishek V almost 2 years
I am hiding the
VideoView
initially and when the video is loaded I am showing theVideoView
. ButonPrepared
is never called if theVideoView
isinvisible
initially. HoweveronPrepared
is called properly ifVideoView
is visible. Is there any way to hide thevideoView
until video is loaded. Any help would be appreciated. Thanks!activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <VideoView android:id="@+id/video" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:visibility="invisible" /> </RelativeLayout>
MainActivity.java
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); VideoView videoView = (VideoView) findViewById(R.id.video); Uri videoUri = Uri.parse(url); videoView.setVideoURI(videoUri); videoView.requestFocus(); videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { Toast.makeText(mActivity, "on prepared", Toast.LENGTH_SHORT).show(); videoView.setVisibility(View.VISIBLE); } }); }
-
Kaloyan Roussev about 10 yearswere you able to solve this?
-
Abhishek V about 10 years@J.Kowalski Check the answers :)
-
Kaloyan Roussev about 10 yearsI solved it using your original approach but I made the layout that held the videoview invisible instead of the videoview itself :)
-
Abhishek V about 10 yearsOh nice :) I should have tried that in the beginning
-
-
Abhishek V about 10 yearsThis trick works only if you use TextureView to load the video. It doesn't work with normal
VideoView
. Anyway thanks for the answer :) -
LeoFarage about 9 yearsI used a FrameLayout as a wrapper for the video view and set the wrapper Alpha to 0 before setting its Visibility to Visible and inside the onPreparedListener return the video view wrapper's alpha back to 1. The View.setAlpha is only available since API 11.
-
Narendra Singh almost 7 yearswhat do you mean by Alpha here? I am unable to understand the term
Alpha
in the whole context. -
FDIM almost 7 years@MrNarendra It is just opacity. See this: developer.android.com/reference/android/view/…