Android Exoplayer,在屏幕旋转时恢复视频

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Exoplayer,在屏幕旋转时恢复视频相关的知识,希望对你有一定的参考价值。

我使用FragmentStatePagerAdapter来实例化一些片段,每个片段都包含SimpleExoPlayerView。在屏幕旋转,我希望视频自动恢复。我在saveInstantState中保存playbackPosition和currentWindow,并在onActivityCreated上恢复它们​​。问题是当我旋转设备时,我正确恢复了playbackPosition,但是再次实例化了SimpleExoPlayerView并且视频没有自动恢复,似乎片段在屏幕旋转时再次被实例化


StepInfoActivity

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_step_info);
        ...

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), recipeModel.getSteps(), recipes_json);
        mViewPager = findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        TabLayout tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

包含ExoPlayerView的片段

public class PlaceholderFragment extends Fragment {

    private static final String ARG_SECTION_NUMBER = "section_number";
    SimpleExoPlayer player;
    long playbackPosition;
    int currentWindow;
    boolean playWhenReady = true;
    RecipeModel recipeModel;
    int received_index;
    @BindView(R.id.simple_exp_view)
    SimpleExoPlayerView playerView;
    @BindView(R.id.step_long_desc)
    TextView step_desc;
    @BindView(R.id.video_thumbnail)
    ImageView videoThumbnail;


    public PlaceholderFragment() {
    }


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String recipes_json = getArguments().getString(DetailFragment.STEP_INFO_EXTRA);
        received_index = getArguments().getInt(DetailFragment.STEP_INFO_POSITION, 0);
        recipeModel = new Gson().fromJson(recipes_json, RecipeModel.class);

    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);

        savedInstanceState.putInt("current_window", currentWindow);
        savedInstanceState.putLong("play_back_pos", playbackPosition);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_step_info, container, false);
        ButterKnife.bind(this, rootView);

        setPlayerVisibility();
        StepModel stepModel = recipeModel.getSteps().get(getArguments().getInt(ARG_SECTION_NUMBER) - 1);
        if (stepModel.getDescription() != null) {
            step_desc.setText(stepModel.getDescription());
        }

        return rootView;
    }

    private void setPlayerVisibility() {
        StepModel stepModel = recipeModel.getSteps().get(getArguments().getInt(ARG_SECTION_NUMBER) - 1);
        if (stepModel.getVideoURL().isEmpty()) {
            playerView.setVisibility(View.GONE);
        } else if (!stepModel.getThumbnailURL().isEmpty()) {
            videoThumbnail.setVisibility(View.VISIBLE);
            Picasso.with(getContext()).load(stepModel.getThumbnailURL()).into(videoThumbnail);
        } else {
            playerView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null) {
            playbackPosition = savedInstanceState.getLong("play_back_pos");
            currentWindow = savedInstanceState.getInt("current_window");
        }

    }

    @Override
    public void onStart() {
        super.onStart();
        initializePlayer();
    }

    @Override
    public void onResume() {
        super.onResume();
        if ((Util.SDK_INT <= 23 || player == null)) {
            initializePlayer();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (Util.SDK_INT <= 23) {
            releasePlayer();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (Util.SDK_INT > 23) {
            releasePlayer();
        }
    }

    private void releasePlayer() {
        if (player != null) {
            playbackPosition = player.getCurrentPosition();
            currentWindow = player.getCurrentWindowIndex();
            playWhenReady = player.getPlayWhenReady();
            player.release();
            player = null;
        }
    }


    private void initializePlayer() {

        if (player == null) {

            player = ExoPlayerFactory.newSimpleInstance(
                    new DefaultRenderersFactory(getContext()),
                    new DefaultTrackSelector(), new DefaultLoadControl());

            playerView.setPlayer(player);
            player.setPlayWhenReady(playWhenReady);
            player.seekTo(currentWindow, playbackPosition);

            Uri uri = Uri.parse(recipeModel.getSteps().get(getArguments().getInt(ARG_SECTION_NUMBER) - 1).getVideoURL()); //todo
            MediaSource mediaSource = buildMediaSource(uri);
            player.prepare(mediaSource, true, false);

            videoThumbnail.setVisibility(View.GONE);
        }
    }

    private MediaSource buildMediaSource(Uri uri) {
        return new ExtractorMediaSource.Factory(
                new DefaultHttpDataSourceFactory("Baking_app")).
                createMediaSource(uri);
    }


    public static PlaceholderFragment newInstance(int sectionNumber, String recipeModel) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        args.putString(DetailFragment.STEP_INFO_EXTRA, recipeModel);
        fragment.setArguments(args);
        return fragment;
    }
}

FragmentStatePagerAdapter

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
    List<StepModel> steps;
    String recipeModel;

    public SectionsPagerAdapter(FragmentManager fm, List<StepModel> steps, String recipeModel) {
        super(fm);
        this.steps = steps;
        this.recipeModel = recipeModel;
    }

    @Override
    public Fragment getItem(int position) {
        return PlaceholderFragment.newInstance(position + 1, recipeModel);
    }

    @Override
    public int getCount() {
        return steps.size();
    }


    @Override
    public CharSequence getPageTitle(int position) {
        if (position == 0) return "intro";
        else return "step " + position;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        return super.instantiateItem(container, position);

    }
}
答案

我设法通过在清单中添加一行来让视频继续播放:

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar"
this line -> android:configChanges="keyboardHidden|orientation|screenSize"
        android:icon="@drawable/appicon"
        android:launchMode="singleTop">

以上是关于Android Exoplayer,在屏幕旋转时恢复视频的主要内容,如果未能解决你的问题,请参考以下文章

旋转到横向时的Exoplayer方向问题

在 Exoplayer IMA 扩展中保存和恢复广告进度

android--屏幕旋转方法总结

如何在 android 中实现 Exoplayer 2.11.1?

android 屏幕旋转生命周期和setRequestedOrientation强制旋转

如何从 android SERVICE 禁用/启用屏幕旋转?