1

私はExoPlayerを使ってURLからいくつかのmp4を再生しています。ユーザーのクリックがホームボタンの場合、またはユーザーのビューからアプリが削除されてからアプリ(および動画のアクティビティ)に戻った場合、動画は中断したところから再開します。私はonStop()にビデオの位置を保存し、次にプレーヤーを再構築し、seekTo()onStart()に使用して実装しようとしました。現在のexoplayerがonStart()でヌルであるかどうかを確認するチェックがありますが、このチェックは決して通過しないので、問題がどこにあるかと思います。どのようにコード化され、私のビデオは決して再開しません。ホームボタンを押してアプリを離れると、onStop()が呼び出され、onStart()が私のアプリに戻ったときに呼び出されますが、ビデオプレーヤーは黒のままで、ビデオは再生されません。ヌルチェックを解除すると、メインアクティビティからビデオを開始するたびにビデオが2つ再生されます(onCreate()onStart()の両方で呼び出されるため)。私が望む機能を得るためのより良い方法はありますか?どんな助けもありがとう!アクティビティのonStart()メソッドでビデオを再開するためにExoPlayerを取得するにはどうすればよいですか?

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(); 
    } 
} 

答えて

3

現在、あなたはプレーヤーのすべての重要な部分をゼロますonStop()でのリリースを呼び出すことではなく、exoPlayerフィールド(と自分自身を追跡するされていない任意の状態を破壊)しています。

いくつかのアプローチがあります。しかし、あなたが何をしていても、自分で何らかの状態を把握したいと思うでしょう。以下ではフィールドとして使用しますが、onSavedInstanceState()に配置することもできます。 onStop()では、2つの情報を保存してからonStart()に引き出します。 1)プレイヤーが一時停止したときの最後の位置と、2)再開時にプレイするかどうか。あなたはおそらく、常にあなたは:

@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()ウォン」であるif == nullブロックのうち、あなたのseekToコールを移動することができますフィールドexoPlayerを無効にしてください。したがって、exoPlayer.release()の後にexoPlayer = null行を追加して、複数のexoPlayersの問題を修正してください。 release()の電話をonDestroy()に移動することもできますが、すべてを正しく再インスタンス化していることがわかっている場合のみです。

関連する問題