George Radu
George Radu

Reputation: 111

Releasing media player in Android ViewPager on swipe

CONTEXT: I have one activity, 4 fragments and a viewPager (each page consists of one fragment). Each fragment contains a list of short sounds (max 5 seconds each). The expected behavior is: if the user clicks on a sound on a certain page and the sound did not finish playing, if the user swipes to another page, the media player will be released, thus the sound will stop playing.

ISSUE: When swiping left or right, the method onPause or onStop are not called (since the viewPager by definition loads the current, the previous and the next page), thus the media player playing the sound from the last page does not stop on swipe.

RESEARCH: I have searched a lot on multiple posts, related to onPageChangeListener, setOffScreenPageLimit, set MediaPlayer not in fragment but in the activity (not possible in my case, since I have lists of sounds with adapter). Here are some links that I researched but did not solve my problem: ViewPager swipe previous sound, Multiple video players in viewpager in android, Android MediaPlayer on ViewPager blocking UI transition and no callback for initial page loads, How to handle MediaPlayer object inside a fragment inside view pager, Using Viewpager with MediaPlayer

SUGGESTIONS?: if you have any suggestions on how to tackle this issue, it would be highly appreciated! Thanks!

Upvotes: 6

Views: 2580

Answers (3)

Carlos Jimenez
Carlos Jimenez

Reputation: 114

You can create a Callback interface on your MainActivity with a method onPageChanged() like this:

public interface Callback {
    void onPageChanged();
}

Then, you can use this OnPageChangeListener:

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

    private int currentPage = 0;

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        Fragment fragment = adapter.getItem(currentPage);

        if (fragment instanceof Callback &&
                currentPage != position) {
            ((Callback)adapter.getItem(currentPage)).onPageChanged();
        }
        currentPage = position;
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }
});

Each and every Fragment in your ViewPager can be created like this:

public class TestFragment extends Fragment implements MainActivity.Callback {

    private void releaseMediaPlayer() {
        // ...
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // ...
    }

    @Override
    public void onPageChanged() {
        releaseMediaPlayer();
        // You can do more things here
    }
}

After doing that, every time that you change the Fragment on the ViewPager it will be calling the onPageChanged method on the previous Fragment, and in there you can release your media player and do any other operation that you require.

Upvotes: 3

Mo1989
Mo1989

Reputation: 2494

Consider you making the fragment itself an OnPageChangeListener. Then you can set the listener when you attach the page. This will allow you to pass the page change information to the fragment. You are allowed to have more than one OnPageChangeListener. Hope that helps.

EDIT:

Consider something like this.

public class PageFragment extends Fragment implements ViewPager.OnPageChangeListener {
    ViewPager pager;

    public void onPageScrollStateChanged (int state){
         // reset the player if needed. you can do this since player object is in this class
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ....
        pager = (ViewPager) getActivity().findViewById(ViewPagerId);
        pager.addOnPageChangeListener(this);
        ....
    }
    @Override
    public void onDestroyView (){
        ....
        pager.removeOnPageChangeListener(this);
        ....

    }
}

Upvotes: 1

D.J
D.J

Reputation: 1559

private int currentPos = 0;
private int prevPos = -1;

global variable

I am getting same problem. I have take two method play and stop in fragment. and call below code in onPageSelected(int position)

new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        prevPos = currentPos;
                        currentPos = position;
                        MyFragment fragment = (MainFragment) getChildFragmentManager().
                                findFragmentByTag("android:switcher:" + R.id.viewPagerVideo + ":" + prevPos);
                        if (fragment != null) {
                            fragment.stop();
                        }
                        fragment = (MyFragment) getChildFragmentManager().
                                findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + currentPos);
                        if (fragment != null) {
                            fragment.play(mListUrl.get(position));
                        }
                    }
                });
            } catch (Exception ignore) {
            }
        }
    }).start();

Upvotes: 1

Related Questions