VideoView inside fragment causes black screen flicking
Asked Answered
Q

4

22

We have an Android application running on Android API 4.0. One of the activities has a layout that divides the screen in 2 parts. On the left side we have a static part with some buttons. On the right side we have a FrameLayout that will switch to the corresponding fragment depending on the button that is pressed.

Problem: One of the fragments on the right side contains a VideoView. When the user clicks on the button to show this fragment the fragment is shown and the video immediately starts playing however: upon rendering this fragment the complete screen flickers in black which is very annoying.

Here is some code of the VideoFragment class:

public class VideoFragment extends Fragment {

    public VideoView videoView;

    private ExternalVideo mVideo;
    private boolean mVideoExists;
    private String mDestination;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDestination = ApplicationParams.MEDIA_STORAGE_PATH + "videos/"
                + FilenameUtils.getBaseName(((DetailActivity)getActivity()).getProduct().getVideoUrl())
                + "."
                + FilenameUtils.getExtension(((DetailActivity) getActivity()).getProduct().getVideoUrl());

        File file = new File(mDestination);
        mVideoExists = file.exists() && file.isFile();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view;

        if (mVideoExists) {
            getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT);
            view = inflater.inflate(R.layout.video, null);
            mVideo = new ExternalVideo(mDestination);

            videoView = (VideoView) view.findViewById(R.id.video_video);

            MediaController mediaController = new MediaController(getActivity());
            mediaController.setAnchorView(videoView);

            videoView.setMediaController(mediaController);
            videoView.setVideoPath(mVideo.getFullPath());
            videoView.requestFocus();
            videoView.setVisibility(View.VISIBLE);

            videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                public void onPrepared(MediaPlayer mp) {
                    videoView.start();

                }
            });
        } else {
            TextView textView = new TextView(getActivity());
            textView.setText(getActivity().getString(R.string.videofragment_video_coming_soon));
            textView.setPadding(50, 50, 50, 50);
            view = textView;
        }

        return view;
    }

}

Here is the layout of the video fragment:

<?xml version="1.0" encoding="utf-8"?>

<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_video"
               android:layout_width="fill_parent"
               android:layout_alignParentRight="true"
               android:layout_alignParentLeft="true"
               android:layout_alignParentTop="true"
               android:layout_alignParentBottom="true"
               android:layout_height="fill_parent"/>
</RelativeLayout>

Does anyone have an idea what could be causing this flickering issue upon rendering the fragment that contains the VideoView? A solution would be appreciated!

EDIT1: If I click on the fragment where the VideoView is on the screen flickers in the beginning. When I then navigate to anoter fragment and go back to the one containing the VideoView the flicker is gone.

Quattrocento answered 18/7, 2013 at 8:2 Comment(10)
Did you run your application in emulator ?Washboard
Running the application on a Samsung Galaxy Tab 2 10.1 tabletQuattrocento
Try setAnchorView(videoView) on your MediaController developer.android.com/reference/android/widget/…Satterfield
@KenWolf Tried it and the flicking still persists.Quattrocento
That code works perfect now. #17698170Washboard
Hmm, I can't see really anything wrong with what you've posted. I have apps that render VideoViews in fragments much like you describe without any problem. I would see if I could test on a different device or alternatively, post your fragment code/layout too.Satterfield
@KenWolf Same problem on a Samsung Galaxy Tab 10.1. I have updated my question with the complete VideoFragment class.Quattrocento
OK, last guess and I'll stop hogging the comments :) Try removing the following 3 lines: getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT); videoView.requestFocus(); and videoView.setVisibility(View.VISIBLE);Satterfield
@KenWolf Same problem still persists :(Quattrocento
Added Edit1 to the questionQuattrocento
Q
44

I was able to fix this by adding a 0px by 0px SurfaceView in the layout of the parent activity of the fragment:

<SurfaceView
        android:layout_width="0px"
        android:layout_height="0px" />
Quattrocento answered 18/7, 2013 at 10:50 Comment(6)
I also facing same problem, When I launch Video Fragment, it show first BG(Wallpaper screen) n then it show video fragment. I tried to use onPreparedListener(..) but same result...any idea/suggestion?Headliner
Worked for me as well. Applies to an activity class as wellNewark
#8773362Lynch
@Med AL In the layout XMLQuattrocento
Yeah I know but where exactly ? before the VideoView tag? @KennyDsCanonry
@Nathan see explanation of Xavier Lin below.Quattrocento
W
13

KennyDs is right, but better be sure to hide the SurfaceView, otherwise you'll have really weird behavior if you animate fragments, then you won't see anything but black screen in the place of the animated fragment. Fortunately this collateral issue has a easy fix too:

<SurfaceView
    android:layout_width="0px"
    android:layout_height="0px"
    android:visibility="gone" />
Winston answered 10/4, 2014 at 17:46 Comment(1)
Doesn't make a difference on Android 5.1.Minesweeper
P
4

If you wonder why adding a zero sized SurfaceView solves the problem, you can take a look at this question SurfaceView flashes black on load. It explains well.

Quoted from Evos's answer

when the surface view appears in the window the very fist time, it requests the window's parameters changing by calling a private IWindowSession.relayout(..) method. This method "gives" you a new frame, window, and window surface. I think the screen blinks right at that moment.The solution is pretty simple: if your window already has appropriate parameters it will not refresh all the window's stuff and the screen will not blink. The simplest solution is to add a 0px height plain SurfaceView to the first layout of your activity. This will recreate the window before the activity is shown on the screen, and when you set your second layout it will just continue using the window with the current parameters.

And here is a cleaner way to solve this problem, call this before you call setContentView(), just tested on my ViewPager with some Fragments containing VideoView, it works as good as adding zero-sized SurfaceView:

getWindow().setFormat(PixelFormat.TRANSLUCENT);
Pulsatory answered 26/5, 2016 at 23:3 Comment(2)
This single line of code solved the issue. Thank youImpignorate
This makes no difference for me on Android 5.1.Minesweeper
S
-4

Just add transparent background color of VideoView. It will solve the problem.

android:background="@color/transparent"
Stenophyllous answered 10/9, 2015 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.