如何在onPause之后恢复ExoPlayer

时间:2018-02-13 11:31:58

标签: android android-fragments android-activity state

我在片段中创建了一个ExoPlayer。如果在播放期间我按下主页按钮,然后返回播放器,播放器似乎为空,播放/暂停按钮不再起作用。视频消失了。视频播放器视图似乎完全是空的。

public class PlaybackFragment extends Fragment implements View.OnClickListener, EventListener, PlaybackControlView.VisibilityListener {
    private static final String TAG = PlaybackFragment.class.getSimpleName();
    Video mVideo; //Video object passed in for playback
    SimpleExoPlayerView mExoPlayerView;
    private TextView mVideoTitle;
    private SimpleExoPlayer mExoPlayer;
    private FrameLayout mFullScreenButton; //Holds the fullscreen icon
    private Dialog mFullScreenDialog;
    private ImageView mFullScreenIcon;
    private boolean mExoPlayerFullScreen; //full-screen dialog
    private static final String LOG_TAG = PlaybackFragment.class.getSimpleName();
    /**
     * Root ViewGroup holding the fragment
     */
    private ViewGroup mPlayerViewContainer;

    /**
     * Context used across the class
     */
    private Context mContext;

    /**
     * Activity to which the fragment is added
     */
    private Activity mActivity;

    /**
     * Uri received from calling activity containing Uri to the video to be played
     */
    private Uri mUri;


    public PlaybackFragment() {
        super();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onCreate: ");
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView: ");
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_playback, container, false);
        mVideoTitle = root.findViewById(R.id.playback_video_title);
        mExoPlayerView = root.findViewById(R.id.exoPlayerView);
        mPlayerViewContainer = (ViewGroup) mExoPlayerView.getParent();
        return root;
    }



    /**
     * Sets the Uri to video to be played
     * @param mediaUri
     */
    public void playUri(Uri mediaUri) {
        mUri = mediaUri;
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onViewStateRestored: ");
        super.onViewStateRestored(savedInstanceState);
    }

    private void preparePlayback() {
        mExoPlayerView.setControllerVisibilityListener(this);
        mExoPlayerView.requestFocus();

        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

        TrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);

        TrackSelector trackSelector =
                new DefaultTrackSelector(trackSelectionFactory);

        mExoPlayer =
                ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector);

        mExoPlayerView.setPlayer(mExoPlayer);

        DataSource.Factory dsFactory =  new DefaultDataSourceFactory(mContext,
                com.google.android.exoplayer2.util.Util.getUserAgent(mContext, mActivity.getApplicationInfo().processName), null);
        // Produces Extractor instances for parsing the media data.
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        MediaSource videoSource = new ExtractorMediaSource(mUri,
                dsFactory, extractorsFactory, null, null);

        // Prepare the player with the source.
        mExoPlayer.prepare(videoSource);

        //start player
        mExoPlayer.setPlayWhenReady(true);
        mExoPlayer.addListener(this);
//        initFullscreenDialog();
        initFullscreenButton();
    }


    @Override
    public void onVisibilityChange(int visibility) {

    }

    @Override
    public void onTimelineChanged(Timeline timeline, Object manifest) {
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onActivityCreated: ");
        super.onActivityCreated(savedInstanceState);
        mContext = mActivity = getActivity();
        preparePlayback();

    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: ");
    }



    @Override
    public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

    }

    @Override
    public void onLoadingChanged(boolean isLoading) {

    }

    @Override
    public void onClick(View v) {

    }

    public void pause() {
        mExoPlayer.stop();
    }

    //Interface to trigger playback-finish event in the parent activity
    public interface OnPlayStateListener {
        void onPlayFinish();
    }

    OnPlayStateListener mCallback;
    @Override
    public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
        if(playbackState == Player.STATE_ENDED) {
            quitFullScreen(); //Leave fullscreen after playback finished
            mCallback.onPlayFinish();
            Log.i(LOG_TAG,"onPlayFinish() triggered");
        }

    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mCallback = (OnPlayStateListener) context;
        } catch (ClassCastException e){
            throw new ClassCastException(context.toString() + " must implement OnPlayStateListener");
        }
    }


    @Override
    public void onRepeatModeChanged(int repeatMode) {

    }

    @Override
    public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {

    }

    @Override
    public void onPlayerError(ExoPlaybackException error) {
        Toast.makeText(mContext,error.getLocalizedMessage(),Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onPositionDiscontinuity(int reason) {

    }


    @Override
    public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

    }

    @Override
    public void onSeekProcessed() {

    }

    private void goFullScreen() {
        Util.showFullScreen(mActivity, mExoPlayerView);
//        ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
//        mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_fullscreen_exit));
        mExoPlayerFullScreen = true;
//        mFullScreenDialog.show();
    }
    private void quitFullScreen() {
        Util.quitFullScreen(mActivity, mPlayerViewContainer, mExoPlayerView);
//        ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
//        FrameLayout frame = mActivity.findViewById(R.id.main_media_frame);
//        frame.addView(mExoPlayerView);
        mExoPlayerFullScreen = false;
//        mFullScreenDialog.dismiss();
        mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_fullscreen_expand));
    }
    private void initFullscreenButton() {

        PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
        mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
        mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
        mFullScreenButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!mExoPlayerFullScreen) {
                    goFullScreen();
                }
                else {
                    quitFullScreen();
                }
            }
        });

    }
    private void initFullscreenDialog() {

        //The following uses anonymous class to create a custom dialog
        mFullScreenDialog = new Dialog(mContext, android.R.style.Theme_DeviceDefault_NoActionBar_Fullscreen) {
            @Override
            public void onBackPressed() {
                if(mExoPlayerFullScreen) {
                    quitFullScreen();
                }
                super.onBackPressed();
            }
        };

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mExoPlayer != null) mExoPlayer.release();
        Log.d(TAG, "onDestroy: ");
    }

    /**
     * Moves forward or backward by step milliseconds <br/>
     * @param step specifies step size. It is a positive or negative integer for moving forward and
     *             backward, respectively.
     */
    public void movePlayPos(int step) {
        mExoPlayer.seekTo(mExoPlayer.getCurrentPosition() + step);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        Log.d(TAG, "onSaveInstanceState: ");
        super.onSaveInstanceState(outState);
        outState.putLong("position", mExoPlayer.getCurrentPosition());
    }

}

我已经检查过Logcat中的片段生命周期,但似乎在我回到播放器活动后,只调用片段的onStart()。所以,没有办法恢复状态。任何想法如何在暂停时保存视频播放位置并在活动的onResume上恢复播放?

1 个答案:

答案 0 :(得分:1)

您可以在exPause()中保存exoplayer的当前位置,然后在onResume()中搜索该位置。  试试这个:

 long position;

 @Override
 protected void onPause() {
          super.onPause();
          if(mExoPlayerView != null && mExoPlayerView.getPlayWhenReady()) {
          position = mExoPlayerView.getCurrentPosition();
          mExoPlayerView.setPlayWhenReady(false);
          }
 }

 @Override
 protected void onResume() {
          super.onResume();
          if(mExoPlayerView != null) {
          mExoPlayerView.seekTo(position);
          mExoPlayerView.setPlayWhenReady(true);
          }
 }