VideoView onPrepared is not called if the VideoView is invisible

12,741

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

  1. You can set the height and width of the VideoView to 1px until the video is prepared and then switch to full screen by changing the properties to match parent

  2. 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 extending TextureView which mimics the default VideoVideo 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) {
    
    }
    
Share:
12,741

Related videos on Youtube

Abhishek V
Author by

Abhishek V

Android developer. Love reading books and watching movies/tv series/cricket :) #SOreadytohelp linkedin | email

Updated on June 27, 2022

Comments

  • Abhishek V
    Abhishek V almost 2 years

    I am hiding the VideoView initially and when the video is loaded I am showing the VideoView. But onPrepared is never called if the VideoView is invisible initially. However onPrepared is called properly if VideoView is visible. Is there any way to hide the videoView 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
      Kaloyan Roussev about 10 years
      were you able to solve this?
    • Abhishek V
      Abhishek V about 10 years
      @J.Kowalski Check the answers :)
    • Kaloyan Roussev
      Kaloyan Roussev about 10 years
      I solved it using your original approach but I made the layout that held the videoview invisible instead of the videoview itself :)
    • Abhishek V
      Abhishek V about 10 years
      Oh nice :) I should have tried that in the beginning
  • Abhishek V
    Abhishek V about 10 years
    This trick works only if you use TextureView to load the video. It doesn't work with normal VideoView. Anyway thanks for the answer :)
  • LeoFarage
    LeoFarage about 9 years
    I 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
    Narendra Singh almost 7 years
    what do you mean by Alpha here? I am unable to understand the term Alpha in the whole context.
  • FDIM
    FDIM almost 7 years
    @MrNarendra It is just opacity. See this: developer.android.com/reference/android/view/…