From 651b79d3ed6372715fde1b9318e5ec18061541a7 Mon Sep 17 00:00:00 2001 From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com> Date: Sat, 15 Jan 2022 13:42:48 +0100 Subject: [PATCH] Catch properly BehindLiveWindowExceptions Instead of trying to reload the play queue manager and then throwing an error, BehindLiveWindowExceptions now make the app seek to the default playback position, like recommended by ExoPlayer. The buffering state is shown in this case. Error handling of other exceptions is not changed. --- .../org/schabi/newpipe/player/Player.java | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 993357ac4..179486bb1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -2517,8 +2517,34 @@ public final class Player implements Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error); saveStreamProgressState(); + boolean isBehindLiveWindowException = false; - // create error notification + switch (error.type) { + case ExoPlaybackException.TYPE_SOURCE: + isBehindLiveWindowException = processSourceError(error.getSourceException()); + if (!isBehindLiveWindowException) { + createErrorNotification(error); + } + break; + case ExoPlaybackException.TYPE_UNEXPECTED: + createErrorNotification(error); + setRecovery(); + reloadPlayQueueManager(); + break; + case ExoPlaybackException.TYPE_REMOTE: + case ExoPlaybackException.TYPE_RENDERER: + default: + createErrorNotification(error); + onPlaybackShutdown(); + break; + } + + if (fragmentListener != null && !isBehindLiveWindowException) { + fragmentListener.onPlayerError(error); + } + } + + private void createErrorNotification(@NonNull final ExoPlaybackException error) { final ErrorInfo errorInfo; if (currentMetadata == null) { errorInfo = new ErrorInfo(error, UserAction.PLAY_STREAM, @@ -2530,37 +2556,36 @@ public final class Player implements currentMetadata.getMetadata()); } ErrorUtil.createNotification(context, errorInfo); - - switch (error.type) { - case ExoPlaybackException.TYPE_SOURCE: - processSourceError(error.getSourceException()); - break; - case ExoPlaybackException.TYPE_UNEXPECTED: - setRecovery(); - reloadPlayQueueManager(); - break; - case ExoPlaybackException.TYPE_REMOTE: - case ExoPlaybackException.TYPE_RENDERER: - default: - onPlaybackShutdown(); - break; - } - - if (fragmentListener != null) { - fragmentListener.onPlayerError(error); - } } - private void processSourceError(final IOException error) { + /** + * Process an {@link IOException} returned by {@link ExoPlaybackException#getSourceException()} + * for {@link ExoPlaybackException#TYPE_SOURCE} exceptions. + * + *

+ * This method sets the recovery position and sends an error message to the play queue if the + * exception is not a {@link BehindLiveWindowException}. + *

+ * @param error the source error which was thrown by ExoPlayer + * @return whether the exception thrown is a {@link BehindLiveWindowException} ({@code false} + * is always returned if ExoPlayer or the play queue is null) + */ + private boolean processSourceError(final IOException error) { if (exoPlayerIsNull() || playQueue == null) { - return; + return false; } + setRecovery(); if (error instanceof BehindLiveWindowException) { - reloadPlayQueueManager(); + simpleExoPlayer.seekToDefaultPosition(); + simpleExoPlayer.prepare(); + // Inform the user that we are reloading the stream by switching to the buffering state + onBuffering(); + return true; } else { playQueue.error(); + return false; } } //endregion