1

我正在研究Android TV應用程序,該應用程序使用VideoView從url播放視頻。每次視頻暫停然後重新開始 - 需要一段時間才能預先下載(幾秒鐘內會出現進度條)。我們的目標是在播放過程中緩衝視頻,這樣當我暫停播放並恢復播放時,它會立即從預緩衝狀態立即恢復。我也試過videoView.resume()方法,但它也沒有幫助。有沒有辦法做到這一點,或者我做錯了什麼?Android VideoView緩存

這裏是起着代碼/恢復視頻:,我沒有找到VideoView實現這一目標的方式,只能用ExoPlayer

public void onFragmentPlayPause(final Video video, 
            final VideoQuality quality, 
            final int position, 
            final Boolean play) { 
     stopSeeking(); 

     videoView.setVideoPath(video.videoUrl(quality)); 

     if (position == 0 || playbackState == LeanbackPlaybackState.IDLE) { 
      setupCallbacks(); 
      playbackState = LeanbackPlaybackState.IDLE; 
     } 

     if (play && playbackState != LeanbackPlaybackState.PLAYING) { 
      progressBar.setVisibility(View.VISIBLE); 
      playbackState = LeanbackPlaybackState.PLAYING; 
      if (position > 0) { 
       videoView.seekTo(position); 
       videoView.start(); 
      } 
      playbackFragment.startProgressObservation(progressFlowable()); 
     } else { 
      playbackState = LeanbackPlaybackState.PAUSED; 
      videoView.pause(); 
      playbackFragment.stopProgressObservation(); 
     } 

     updatePlaybackState(position); 
     updateMetadata(video); 
    } 
+0

試圖[ExoPlayer](https://developer.android.com/ guide/topics/media/exoplayer.html)?更多在這裏:http://google.github.io/ExoPlayer/guide.html#pros-and-cons – pskink

+0

@pskink不,我沒有。如果我使用它,有很多代碼需要更改,所以我想用'VideoView'來實現。目前,它是唯一的問題,其他所有的工作。 –

+0

如果沒有辦法使用'VideoView'平滑流,這是一個壞消息。 –

回答

1

不幸的是,由於@pskink爲右方向。 API正在返回mp4視頻,所以我使用了ExtractorMediaSource。支持多種格式的完整演示示例可在ExoPlayer GitHub page上找到。

下面是最後的代碼我已經結束了使用ExoPlayer

private void playPause(final Video video, final int position, final Boolean play) { 
     if (position == 0 || playbackState == LeanbackPlaybackState.IDLE) { 
      setupCallbacks(); 
      playbackState = LeanbackPlaybackState.IDLE; 
     } 

     if (play && playbackState != LeanbackPlaybackState.PLAYING) { 
      progressBar.setVisibility(View.VISIBLE); 
      playbackState = LeanbackPlaybackState.PLAYING; 
      player.start(); 
      playbackFragment.startProgressObservation(progressFlowable()); 
     } else { 
      playbackState = LeanbackPlaybackState.PAUSED; 
      player.pause(); 
      playbackFragment.stopProgressObservation(); 
     } 

     updatePlaybackState(position); 
     updateMetadata(video); 
    } 

而且Player實現:

public class Player implements MediaController.MediaPlayerControl, ExoPlayer.EventListener { 

    private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter(); 

    private final SimpleExoPlayer exoPlayer; 
    private final Context context; 

    private OnErrorListener onErrorListener; 
    private OnPreparedListener onPreparedListener; 
    private OnCompletionListener onCompletionListener; 

    private String url; 

    public interface OnErrorListener { 
     void onError(final Exception e); 
    } 

    public interface OnPreparedListener { 
     void onPrepared(); 
    } 

    public interface OnCompletionListener { 
     void onComplete(); 
    } 

    public Player(final Context context) { 
     this.context = context; 

     final @SimpleExoPlayer.ExtensionRendererMode int extensionRendererMode = 
       SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF; 
     final TrackSelection.Factory videoTrackSelectionFactory = 
       new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); 
     this.exoPlayer = ExoPlayerFactory.newSimpleInstance(
       context, 
       new DefaultTrackSelector(videoTrackSelectionFactory), 
       new DefaultLoadControl(), 
       null, 
       extensionRendererMode 
     ); 
     this.exoPlayer.addListener(this); 
    } 

    @Override 
    public boolean canPause() { 
     return true; 
    } 

    @Override 
    public boolean canSeekBackward() { 
     return true; 
    } 

    @Override 
    public boolean canSeekForward() { 
     return true; 
    } 

    @Override 
    public int getAudioSessionId() { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public int getBufferPercentage() { 
     return exoPlayer.getBufferedPercentage(); 
    } 

    @Override 
    public int getCurrentPosition() { 
     return exoPlayer.getDuration() == com.google.android.exoplayer2.C.TIME_UNSET ? 0 
       : (int) exoPlayer.getCurrentPosition(); 
    } 

    @Override 
    public int getDuration() { 
     return exoPlayer.getDuration() == com.google.android.exoplayer2.C.TIME_UNSET ? 0 
       : (int) exoPlayer.getDuration(); 
    } 

    @Override 
    public boolean isPlaying() { 
     return exoPlayer.getPlayWhenReady(); 
    } 

    @Override 
    public void start() { 
     exoPlayer.setPlayWhenReady(true); 
    } 

    @Override 
    public void pause() { 
     exoPlayer.setPlayWhenReady(false); 
    } 

    public void stop() { 
     exoPlayer.seekTo(0); 
     pause(); 
    } 

    public void setOnErrorListener(final OnErrorListener onErrorListener) { 
     this.onErrorListener = onErrorListener; 
    } 

    public void setOnPreparedListener(final OnPreparedListener onPreparedListener) { 
     this.onPreparedListener = onPreparedListener; 
    } 

    public void setOnCompletionListener(final OnCompletionListener onCompletionListener) { 
     this.onCompletionListener = onCompletionListener; 
    } 

    public void setVolume(final float volume) { 
     exoPlayer.setVolume(volume); 
    } 

    public void release() { 
     exoPlayer.release(); 
    } 

    public void updateUrl(final String url) { 
     this.url = url; 
     exoPlayer.prepare(buildMediaSource(Uri.parse(url))); 
    } 

    public SimpleExoPlayer exoPlayer() { 
     return exoPlayer; 
    } 

    @Override 
    public void seekTo(final int timeMillis) { 
     exoPlayer.seekTo(timeMillis); 
    } 

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

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

    @Override 
    public void onLoadingChanged(final boolean isLoading) { 
    } 

    @Override 
    public void onPlayerStateChanged(final boolean playWhenReady, final int playbackState) { 
     if (playbackState == ExoPlayer.STATE_READY) { 
      onPreparedListener.onPrepared(); 
     } 
     if (playbackState == ExoPlayer.STATE_ENDED) { 
      onCompletionListener.onComplete(); 
     } 
    } 

    @Override 
    public void onPlayerError(final ExoPlaybackException error) { 
     onErrorListener.onError(error); 
    } 

    @Override 
    public void onPositionDiscontinuity() { 
    } 

    public String url() { 
     return url; 
    } 

    private MediaSource buildMediaSource(final Uri uri) { 
     return new ExtractorMediaSource(uri, buildDataSourceFactory(true), new DefaultExtractorsFactory(), 
       null, null); 
    } 

    private DataSource.Factory buildDataSourceFactory(final DefaultBandwidthMeter bandwidthMeter) { 
     return new DefaultDataSourceFactory(context, bandwidthMeter, 
       buildHttpDataSourceFactory(bandwidthMeter)); 
    } 

    private HttpDataSource.Factory buildHttpDataSourceFactory(final DefaultBandwidthMeter bandwidthMeter) { 
     return new DefaultHttpDataSourceFactory(Util.getUserAgent(context, Application.TAG), bandwidthMeter); 
    } 

    private DataSource.Factory buildDataSourceFactory(final boolean useBandwidthMeter) { 
     return buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null); 
    } 
}