Я пытаюсь написать приложение, в котором у меня будет пара URL-адресов видео, которые мне нужно воспроизвести. Я использую Exo Player для воспроизведения видео.
Exo Player воспроизводит видео, но проблема, с которой я сталкиваюсь, заключается в том, что exo player загружает некоторую часть видео (скажем, 5 секунд), а затем воспроизводит их, и как только exo Player завершает воспроизведение этой части, он пытается загрузить следующую часть видео, а затем воспроизводить эту часть видео. Эта проблема возникает, даже если скорость интернета хорошая. Я пытался читать документы exo player и другие сообщения от stackoverflow, но я не могу понять, что здесь не так.
Ниже приведен мой код для синглтон-класса экзо-игрока:
/**
* Singleton class that manages all video playback in the app. Ensures that only a single stream can be heard at a time
* and reports the current playback status to any interested listeners.
*/
public class VideoWrapper {
private static String TAG = "VideoWrapper";
private int VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_STOPPED;
// Player that plays the videos.
private SimpleExoPlayer exoPlayer;
// Singleton instance of the class
private static VideoWrapper videoWrapper;
// URL of Current Video Item that is getting played.
private String mCurrentStreamingUrl;
// Handler to take request of video playback in-case there is a playlist is being sent for play.
private Handler handler;
// Add the listener and notify them if required. -- For demo i am not using it but for UI updates and all it will be useful.
private List<VideoPlaybackListener> listeners = new LinkedList<>();
// Tells to which screen we have to go back
private String mPreviousScreenName;
private Context context;
public static VideoWrapper getInstance() {
if (videoWrapper == null) {
videoWrapper = new VideoWrapper();
}
return videoWrapper;
}
// Default constrructor!
private VideoWrapper() {
// Nothing to do.
}
public void setCurrentPreviousScreen(String screen) {
mPreviousScreenName = screen;
}
public void init(Context context) {
try {
this.context = context;
handler = new Handler(context.getMainLooper());
} catch (Exception e) {
// TODO
}
}
public void stopAndReleasePlayer() {
// Stop the player first.
stopVideoStreaming();
// Now release the player and make it null.
if (exoPlayer != null) {
exoPlayer.release();
exoPlayer = null;
}
}
public void addListener(VideoPlaybackListener listener) {
listeners.add(listener);
}
public void removeListener(VideoPlaybackListener listener) {
listeners.remove(listener);
}
public int getVideoPlaybackState() {
return VideoPlaybackState;
}
private SimpleExoPlayer.VideoListener gVideoEventListener = new SimpleExoPlayer.VideoListener() {
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
// TODO: Do Something!
}
@Override
public void onRenderedFirstFrame() {
// TODO: Do Something!
}
};
private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// TODO: Do Something!
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
// TODO: Do Something!
}
@Override
public void onLoadingChanged(boolean isLoading) {
// TODO: Do Something!
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
// playback state handling serially
case ExoPlayer.STATE_IDLE:
// TODO: Do something!
break;
case ExoPlayer.STATE_BUFFERING:
// TODO: Do something!
break;
case ExoPlayer.STATE_READY:
// TODO: Do something!
break;
case ExoPlayer.STATE_ENDED:
// TODO: Do something!
break;
}
}
@Override
public void onPlayerError(ExoPlaybackException error) {
int errorType = error.type;
switch (errorType) {
case ExoPlaybackException.TYPE_RENDERER:
// TODO: Do something!
break;
case ExoPlaybackException.TYPE_SOURCE:
// TODO: Do something!
break;
case ExoPlaybackException.TYPE_UNEXPECTED:
// TODO: Do something!
break;
default:
// TODO: Do something!
break;
}
}
@Override
public void onPositionDiscontinuity() {
// TODO: Do something!
}
};
private boolean canPlayCurrentItem() {
return mCurrentStreamingUrl != null && !TextUtils.isEmpty(mCurrentStreamingUrl);
}
public void stopVideoStreaming() {
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(false);
}
}
private void restartVideoStreaming() {
if (canPlayCurrentItem()) {
streamCurrentTrack();
}
}
public void startVideoStreaming(String streamUrl) {
// Stop any video if it is playing.
stopVideoStreaming();
VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_STOPPED;
mCurrentStreamingUrl = streamUrl;
openStreamUrl();
}
private void openStreamUrl() {
Uri uri = Uri.parse(mCurrentStreamingUrl);
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = buildDataSourceFactory(bandwidthMeter);
// This is the MediaSource representing the media to be played.
HlsMediaSource mediaSource = new HlsMediaSource(uri, dataSourceFactory, handler, new AdaptiveMediaSourceEventListener() {
@Override
public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) {
// TODO: Do something!
}
@Override
public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
// TODO: Do something!
}
@Override
public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
// TODO: Do something!
}
@Override
public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) {
// TODO: Do something!
}
@Override
public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
// TODO: Do something!
}
@Override
public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) {
// TODO: Do something!
}
});
exoPlayer.prepare(mediaSource);
streamCurrentTrack();
}
private DataSource.Factory buildDataSourceFactory(DefaultBandwidthMeter bandwidthMeter){
return new DefaultDataSourceFactory(context, bandwidthMeter, buildHttpDataSourceFactory(bandwidthMeter));
}
private HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter){
return new DefaultHttpDataSourceFactory("TiVoPhoenix", bandwidthMeter);
}
public void togglePlayPause() {
if (canPlayCurrentItem()) {
if (VideoPlaybackState == PlaybackListener.STATE_PLAYING) {
stopVideoStreaming();
VideoPlaybackState = PlaybackListener.STATE_PAUSED;
} else {
restartVideoStreaming();
}
}
}
private void streamCurrentTrack() {
VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_PLAYING;
exoPlayer.setPlayWhenReady(true);
}
public SimpleExoPlayer getPlayer() {
TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
// Stop and release the video player before re-creating it.
stopAndReleasePlayer();
exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl);
exoPlayer.addListener(eventListener);
exoPlayer.setVideoListener(gVideoEventListener);
return exoPlayer;
}
}
Не могли бы вы, ребята, помочь мне с этим?