Search code examples
javaandroidandroid-viewpagerexoplayer

Stopping Exoplayer onSwipe of ViewPager


I am using a ViewPager with single fragment instance in which I am showing Media files like Images, Videos, Audio.

I have implemented ExoPlayer for handling Video & Audio files. And Glide for images.

To avoid the memory leaks I am releasing the ExoPlayer object like this in ItemViewerFragment.java :

 private void releasePlayer() {
        if (player != null) {
            player.release();
            player = null;
            trackSelector = null;
            simpleExoPlayerView.setPlayer(null);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (player == null && currentGalleryModel != null) {
            initializePlayer();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (player == null && currentGalleryModel != null) {
            initializePlayer();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        releasePlayer();
    }

    @Override
    public void onStop() {
        super.onStop();
        releasePlayer();
    }

And in onViewCreated() I am initializing view like this :

 @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        if (currentGalleryModel.isVideo() || currentGalleryModel.isAudio()) {

            simpleExoPlayerView.setVisibility(View.VISIBLE);
            imageView.setVisibility(View.GONE);

            initializePlayer();
        } else if (currentGalleryModel.isImage() || currentGalleryModel.isGif()) {
            simpleExoPlayerView.setVisibility(View.GONE);
            imageView.setVisibility(View.VISIBLE);


            Glide.with(this)
                    .load(currentGalleryModel.getFilePath())
                    .placeholder(android.R.color.black)
                    .fitCenter()
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .into(imageView);

        }
    }

I am using FragmentStatePagerAdapeter. This is the getItem method :

@Override
public Fragment getItem(int position) {
    return ItemViewerFragment.newInstance(mItems.get(position));
}

I am not able to detect the onPause of the fragment on first swipe of Viewpager. On second swipe video/audio files are stopped playing.

In activity I have tried adding .addOnPageChangeListener :

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

     try {
        ((ItemViewerFragment)mAdapter.getItem(mPreviousPos)).imHiddenNow();
        } catch (Exception e) {
            e.printStackTrace();
        }
        mPreviousPos = position;
    }

And in ItemViewerFragment.java :

public void imHiddenNow(){
      releasePlayer();
    }

Still video/audio keeps on playing.

Here is a Video Link to the Screencast.

Demo project GitHub link.


Solution

  • I followed an approach of maintaining HashMap of fragment objects inside PagerAdapter

    1. Declare an interface :
    interface FragmentLifecycle {
        void onPauseFragment()
    }
    
    1. Implement an interface in Fragment.
    public void onPauseFragment() {
        if (simpleExoPlayer != null){
            simpleExoPlayer.setPlayWhenReady(false);
        }
    }
    
    1. Store all the fragment objects in a HashMap<Integer,Fragment> with there respective positions as a key. Declare hashmap inside PagerAdapter. Also declare one getter method for accessing fragment objects from hashmap. e.g.

      @Override
      public Fragment getItem(int position) {
          ItemViewerFragment fragment = ItemViewerFragment.newInstance(mItems.get(position));
          mFragments.put(position,fragment);
          return fragment;
      }
      

      public ItemViewerFragment getMapItem(int position) { return mFragments.get(position); }

    2. In activity where you have declared viewPager keep one variable currentPosition and implement ViewPager.OnPageChangeListener.

    3. Inside onPageSelected method,

          @Override
          public void onPageSelected(int position) {
              if(mAdapter.getMapItem(currentPosition) != null) (mAdapter.getMapItem(currentPosition)).onPauseFragment();
              currentPosition = position;
          }