如何让exoplayer在活动的onstart()方法中恢复视频?

z4iuyo4d  于 2021-06-30  发布在  Java
关注(0)|答案(4)|浏览(510)

我用exoplayer从一个url上播放一些mp4。当用户单击home按钮,或任何导致应用程序从用户视图中删除,然后返回到我的应用程序(和视频活动)的操作时,我希望视频从停止的位置继续。我试图通过将视频位置保存在 onStop() 然后重建播放器并使用 seekTo()onStart() . 我有一个检查,看看我当前的exoplayer是否为空 onStart() 但是,这张支票从来没有通过,所以我认为这就是问题所在。现在我的视频再也不会恢复了。如果我按home按钮离开应用程序 onStop() 接到电话然后 onStart() 当我回到我的应用程序时会被调用,但是视频播放器仍然是黑色的并且从不播放视频。如果我去掉null检查,每当我从主活动启动一个视频时,我就会得到两个视频播放示例,因为它会同时被调用 onCreate() 以及 onStart() . 有没有更好的方法来获得我想要的功能?感谢您的帮助!

public class VideoActivity extends AppCompatActivity {

    private SimpleExoPlayer exoPlayer;
    private SimpleExoPlayerView simpleExoPlayerView;
    private long playerPosition;
    private String mp4Url;

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

        // Get the Intent that started this activity and extract the video url
        Intent intent = getIntent();
        mp4Url = intent.getStringExtra(MainActivity.VIDEO_URL);
        // Create an exoplayer instance and start playing video
        buildPlayer(mp4Url);

    }

    private void buildPlayer(String mp4Url) {
        // Create a default TrackSelector
        Handler mainHandler = new Handler();
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

        // Create the player
        exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); // no LoadControl?
        simpleExoPlayerView = new SimpleExoPlayerView(this);
        simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);

        // Set media controller
        simpleExoPlayerView.setUseController(true);
        simpleExoPlayerView.requestFocus();

        // Bind player to the view
        simpleExoPlayerView.setPlayer(exoPlayer);

        // Create Uri from video location
        // TODO: should this be in some network class? Should I be appending APIKEY here?
        Uri mp4Uri = Uri.parse(mp4Url + "?api_key=" + BuildConfig.GIANTBOMB_API_KEY);
        Timber.v("Video url with api key: " + mp4Uri.toString());

        // Create another bandwidth meter for bandwidth during playback (not strictly necessary)
        DefaultBandwidthMeter playbackBandwidthMeter = new DefaultBandwidthMeter();

        // DataSourceFactory to produce DataSource instances through which media data is loaded
        DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this,
                Util.getUserAgent(this, "GiantBombForAndroid"),
                playbackBandwidthMeter);

        // Produces Extractor instances for parsing the media data
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();

        ExtractorMediaSource.EventListener eventListener = new ExtractorMediaSource.EventListener() {
            @Override
            public void onLoadError(IOException error) {
                Timber.e("Error loading video from source");
            }
        };

        final MediaSource videoSource = new ExtractorMediaSource(mp4Uri,
                dataSourceFactory,
                extractorsFactory,
                mainHandler,
                eventListener);

        exoPlayer.prepare(videoSource);

        exoPlayer.addListener(new ExoPlayer.EventListener() {
            @Override
            public void onLoadingChanged(boolean isLoading) {
                Timber.v("Listener-onLoadingChanged...");

            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                Timber.v("Listener-onPlayerStateChanged...");

            }

            @Override
            public void onTimelineChanged(Timeline timeline, Object manifest) {
                Timber.v("Listener-onTimelineChanged...");

            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                // TODO: Do I need anything here?
            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
                Timber.v("Listener-onPlayerError...");
                exoPlayer.stop();
                exoPlayer.prepare(videoSource);
                exoPlayer.setPlayWhenReady(true);
            }

            @Override
            public void onPositionDiscontinuity() {
                Timber.v("Listener-onPositionDiscontinuity...");

            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                // TODO: Do I need anything here?
            }
        });
        exoPlayer.setPlayWhenReady(true);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Timber.v("onStart()...");
        if (exoPlayer == null) {
            Timber.v("No exoplayer instance, recreating...");
            buildPlayer(mp4Url);
            exoPlayer.seekTo(playerPosition);
        }
    }

    @Override
    protected void onStop(){
        super.onStop();
        Timber.v("onStop()...");
        //TODO: pull player creation code into it's own method so it can be called here as well
        playerPosition = exoPlayer.getCurrentPosition();
        exoPlayer.release();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Timber.v("onDestroy()...");
        exoPlayer.release();
    }
}
nqwrtyyt

nqwrtyyt1#

目前你正在呼叫释放 onStop() 这将消除所有的球员的重要部分,但不是 exoPlayer 场(并摧毁任何你没有跟踪自己的状态)。
有几种不同的方法。但不管你做什么,你都可能想自己记录一些状态。下面我将它们用作字段,但它们也可以放在 onSavedInstanceState() . 在 onStop() 我们保存了两条信息,然后把它们提取出来 onStart() . 1) 我们球员的最后一个位置是暂停时,以及2)我们是否应该继续比赛时。你可以移动你的 seekTo 把电话拨出去 if == null 阻止,因为您可能总是希望从上次停止的位置继续

@Override
public void onStart() {
    // ...

    if (exoPlayer == null) {
        // init player
    }

    // Seek to the last position of the player.
    exoPlayer.seekTo(mLastPosition);

    // Put the player into the last state we were in.
    exoPlayer.setPlayWhenReady(mPlayVideoWhenForegrounded);

    // ...
}

@Override
public void onStop() {
    // ...

    // Store off if we were playing so we know if we should start when we're foregrounded again.
    mPlayVideoWhenForegrounded = exoPlayer.getPlayWhenReady();

    // Store off the last position our player was in before we paused it.
    mLastPosition = exoPlayer.getCurrentPosition();

    // Pause the player
    exoPlayer.setPlayWhenReady(false);

    // ...
}

我在代码示例中看到的另一个问题是 exoPlayer.release() 不会使字段无效 exoPlayer . 所以你可以再加上一行 exoPlayer = null 之后 exoPlayer.release() 希望能解决你的多个外星玩家的问题。你也可以移动 release() 呼叫 onDestroy() 但前提是你知道你正在正确地重新测试一切。

x759pob2

x759pob22#

没有必要再束缚玩家。下面的代码就足够了:

@Override
 protected void onPause() {
     super.onPause();
     if (player!=null) {
         player.stop();
          mLastPosition = player.getCurrentPosition();
     }
 }

 @Override
 protected void onResume() {
     super.onResume();
     //initiatePlayer();
     if(mLastPosition!=0 && player!=null){
         player.seekTo(mLastPosition);
     }
 }
56lgkhnf

56lgkhnf3#

请尝试以下操作
在onpause中获得玩家的位置。
在onresume中再次启动palyer并将seek设置到玩家的最后一个位置

private void initiatePlayer() {

        try {

            exoPlayer = ExoPlayerFactory.newSimpleInstance(this);

            DataSource.Factory dataSourceFactory =
                    new DefaultDataSourceFactory(this, Util.getUserAgent(this, this.getResources().getString(R.string.app_name)));
            DefaultExtractorsFactory extractorsFactory =
                    new DefaultExtractorsFactory()
                            .setMp4ExtractorFlags(Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS);

            ProgressiveMediaSource progressiveMediaSource =
                    new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
                            .createMediaSource(videoUri);
            // playerView = new PlayerView(this);

            playerView.setPlayer(exoPlayer);
            exoPlayer.prepare(progressiveMediaSource);
            exoPlayer.setPlayWhenReady(true);

            PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
            mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
            ImageView volumeControl = controlView.findViewById(R.id.exo_volume);
            mFullScreenIcon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(ORIENTATION ==Configuration.ORIENTATION_LANDSCAPE){
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    }else {
                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    }

                    Timer mRestoreOrientation = new Timer();
                    mRestoreOrientation.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                        }
                    }, 2000);
                }
            });

            volumeControl.setOnClickListener(view -> {
                float currentvolume = exoPlayer.getVolume();
                if (currentvolume > 0f) {
                    previousVolume = currentvolume;
                    exoPlayer.setVolume(0f);
                    volumeControl.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_volume_off_white_24dp));
                } else {
                    exoPlayer.setVolume(previousVolume);
                    volumeControl.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_volume_up_white_24dp));
                }
            });

        } catch (Exception e) {
            e.printStackTrace();
            Log.d("MainExcep", e.getMessage());
        }
    }

 @Override
    protected void onPause() {
        super.onPause();
        if (exoPlayer!=null) {
            exoPlayer.stop();
            mLastPosition = exoPlayer.getCurrentPosition();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        initiatePlayer();
        if(mLastPosition!=0){
            exoPlayer.seekTo(mLastPosition);
        }
    }
1bqhqjot

1bqhqjot4#

在我的情况下,如果我最小化或试图从这个播放器视频应用程序移动到另一个应用程序。视频播放器应用程序始终从0开始播放。我试着成功地,视频播放器应用程序播放视频从上一个当前位置时,你最小化或移动到另一个应用程序,这就是它。

private void buildPlayer(String mp4Url)

添加

player.seekTo(playbackPosition);

然后

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

@Override
public void onPause() {
    super.onPause();
    player.stop();
    if(player != null && player.getPlayWhenReady()) {
        player.stop();
        playbackPosition = player.getCurrentPosition();
        player.setPlayWhenReady(true);
    }

}

@Override
public void onStop() {
    super.onStop();
   player.setPlayWhenReady(false);
   player.stop();
   player.seekTo(0);
}

你可以试着把

exoPlayer.setPlayWhenReady(true);

private void buildPlayer(String mp4Url)

相关问题