updated: onPlayerError to not catch unspecified source errors so notifications are created.
updated: Throwable usage to Exceptions. updated: minor styles and documentations.
This commit is contained in:
parent
b81eb35f3d
commit
d289dc8a53
|
@ -1961,13 +1961,12 @@ public final class Player implements
|
|||
final boolean showPrev = playQueue.getIndex() != 0;
|
||||
final boolean showNext = playQueue.getIndex() + 1 != playQueue.getStreams().size();
|
||||
final boolean showQueue = playQueue.getStreams().size() > 1 && !popupPlayerSelected();
|
||||
boolean showSegment = false;
|
||||
showSegment = /*only when stream has segment and playing in fullscreen player*/
|
||||
!popupPlayerSelected()
|
||||
&& !getCurrentStreamInfo()
|
||||
.map(StreamInfo::getStreamSegments)
|
||||
.map(List::isEmpty)
|
||||
.orElse(/*no stream info=*/true);
|
||||
/* only when stream has segments and is not playing in popup player */
|
||||
final boolean showSegment = !popupPlayerSelected()
|
||||
&& !getCurrentStreamInfo()
|
||||
.map(StreamInfo::getStreamSegments)
|
||||
.map(List::isEmpty)
|
||||
.orElse(/*no stream info=*/true);
|
||||
|
||||
binding.playPreviousButton.setVisibility(showPrev ? View.VISIBLE : View.INVISIBLE);
|
||||
binding.playPreviousButton.setAlpha(showPrev ? 1.0f : 0.0f);
|
||||
|
@ -2014,7 +2013,7 @@ public final class Player implements
|
|||
+ "playWhenReady = [" + playWhenReady + "], "
|
||||
+ "reason = [" + reason + "]");
|
||||
}
|
||||
final int playbackState = simpleExoPlayer == null
|
||||
final int playbackState = exoPlayerIsNull()
|
||||
? com.google.android.exoplayer2.Player.STATE_IDLE
|
||||
: simpleExoPlayer.getPlaybackState();
|
||||
updatePlaybackState(playWhenReady, playbackState);
|
||||
|
@ -2026,8 +2025,7 @@ public final class Player implements
|
|||
Log.d(TAG, "ExoPlayer - onPlaybackStateChanged() called with: "
|
||||
+ "playbackState = [" + playbackState + "]");
|
||||
}
|
||||
final boolean playWhenReady = simpleExoPlayer != null && simpleExoPlayer.getPlayWhenReady();
|
||||
updatePlaybackState(playWhenReady, playbackState);
|
||||
updatePlaybackState(getPlayWhenReady(), playbackState);
|
||||
}
|
||||
|
||||
private void updatePlaybackState(final boolean playWhenReady, final int playbackState) {
|
||||
|
@ -2486,6 +2484,19 @@ public final class Player implements
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
//region ExoPlayer listeners (that didn't fit in other categories)
|
||||
|
||||
/**
|
||||
* <p>Listens for event or state changes on ExoPlayer. When any event happens, we check for
|
||||
* changes in the currently-playing metadata and update the encapsulating
|
||||
* {@link Player}. Downstream listeners are also informed.
|
||||
*
|
||||
* <p>When the renewed metadata contains any error, it is reported as a notification.
|
||||
* This is done because not all source resolution errors are {@link PlaybackException}, which
|
||||
* are also captured by {@link ExoPlayer} and stops the playback.
|
||||
*
|
||||
* @param player The {@link com.google.android.exoplayer2.Player} whose state changed.
|
||||
* @param events The {@link com.google.android.exoplayer2.Player.Events} that has triggered
|
||||
* the player state changes.
|
||||
**/
|
||||
@Override
|
||||
public void onEvents(@NonNull final com.google.android.exoplayer2.Player player,
|
||||
@NonNull final com.google.android.exoplayer2.Player.Events events) {
|
||||
|
@ -2602,11 +2613,12 @@ public final class Player implements
|
|||
* <li>{@link PlaybackException#ERROR_CODE_BEHIND_LIVE_WINDOW BEHIND_LIVE_WINDOW}:
|
||||
* If the playback on livestreams are lagged too far behind the current playable
|
||||
* window. Then we seek to the latest timestamp and restart the playback.
|
||||
* This error is <b>catchable</b>.
|
||||
* </li>
|
||||
* <li>From {@link PlaybackException#ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE BAD_IO} to
|
||||
* {@link PlaybackException#ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED UNSUPPORTED_FORMATS}:
|
||||
* If the stream source is validated by the extractor but not recognized by the player,
|
||||
* then we can try to recover playback by signal an error on the {@link PlayQueue}.</li>
|
||||
* then we can try to recover playback by signalling an error on the {@link PlayQueue}.</li>
|
||||
* <li>For {@link PlaybackException#ERROR_CODE_TIMEOUT PLAYER_TIMEOUT},
|
||||
* {@link PlaybackException#ERROR_CODE_IO_UNSPECIFIED MEDIA_SOURCE_RESOLVER_TIMEOUT} and
|
||||
* {@link PlaybackException#ERROR_CODE_IO_NETWORK_CONNECTION_FAILED NO_NETWORK}:
|
||||
|
@ -2617,8 +2629,8 @@ public final class Player implements
|
|||
* We terminate the playback.</li>
|
||||
* <li>For any other unspecified issue internal: We set a recovery and try to restart
|
||||
* the playback.</li>
|
||||
* In the case of decoder/renderer or unspecified errors, the player will create a
|
||||
* notification so the users are aware.
|
||||
* For any error above that is <b>not</b> explicitly <b>catchable</b>, the player will
|
||||
* create a notification so users are aware.
|
||||
* </ul>
|
||||
* @see com.google.android.exoplayer2.Player.Listener#onPlayerError(PlaybackException)
|
||||
* */
|
||||
|
@ -2627,7 +2639,6 @@ public final class Player implements
|
|||
public void onPlayerError(@NonNull final PlaybackException error) {
|
||||
Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error);
|
||||
|
||||
setRecovery();
|
||||
saveStreamProgressState();
|
||||
boolean isCatchableException = false;
|
||||
|
||||
|
@ -2652,7 +2663,6 @@ public final class Player implements
|
|||
case ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED:
|
||||
// Source errors, signal on playQueue and move on:
|
||||
if (!exoPlayerIsNull() && playQueue != null) {
|
||||
isCatchableException = true;
|
||||
playQueue.error();
|
||||
}
|
||||
break;
|
||||
|
@ -2660,11 +2670,6 @@ public final class Player implements
|
|||
case ERROR_CODE_IO_UNSPECIFIED:
|
||||
case ERROR_CODE_IO_NETWORK_CONNECTION_FAILED:
|
||||
case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT:
|
||||
// Don't create notification on timeout/networking errors:
|
||||
isCatchableException = true;
|
||||
setRecovery();
|
||||
reloadPlayQueueManager();
|
||||
break;
|
||||
case ERROR_CODE_UNSPECIFIED:
|
||||
// Reload playback on unexpected errors:
|
||||
setRecovery();
|
||||
|
@ -3010,10 +3015,9 @@ public final class Player implements
|
|||
}
|
||||
|
||||
public void saveStreamProgressStateCompleted() {
|
||||
getCurrentStreamInfo().ifPresent(info -> {
|
||||
// current stream has ended, so the progress is its duration (+1 to overcome rounding)
|
||||
saveStreamProgressState((info.getDuration() + 1) * 1000);
|
||||
});
|
||||
// current stream has ended, so the progress is its duration (+1 to overcome rounding)
|
||||
getCurrentStreamInfo().ifPresent(info ->
|
||||
saveStreamProgressState((info.getDuration() + 1) * 1000));
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
@ -3414,7 +3418,8 @@ public final class Player implements
|
|||
case VIDEO_STREAM:
|
||||
if (currentMetadata == null
|
||||
|| !currentMetadata.getMaybeQuality().isPresent()
|
||||
|| info.getVideoStreams().size() + info.getVideoOnlyStreams().size() == 0) {
|
||||
|| (info.getVideoStreams().isEmpty()
|
||||
&& info.getVideoOnlyStreams().isEmpty())) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3684,10 +3689,8 @@ public final class Player implements
|
|||
}
|
||||
|
||||
// Normalize mismatching language strings
|
||||
final List<String> preferredLanguages =
|
||||
trackSelector.getParameters().preferredTextLanguages;
|
||||
final String preferredLanguage =
|
||||
preferredLanguages.isEmpty() ? null : preferredLanguages.get(0);
|
||||
final String preferredLanguage = trackSelector.getParameters()
|
||||
.preferredTextLanguages.stream().findFirst().orElse(null);
|
||||
// Build UI
|
||||
buildCaptionMenu(availableLanguages);
|
||||
if (trackSelector.getParameters().getRendererDisabled(textRenderer)
|
||||
|
|
|
@ -24,12 +24,12 @@ public final class ExceptionTag implements MediaItemTag {
|
|||
@NonNull
|
||||
private final PlayQueueItem item;
|
||||
@NonNull
|
||||
private final List<Throwable> errors;
|
||||
private final List<Exception> errors;
|
||||
@Nullable
|
||||
private final Object extras;
|
||||
|
||||
private ExceptionTag(@NonNull final PlayQueueItem item,
|
||||
@NonNull final List<Throwable> errors,
|
||||
@NonNull final List<Exception> errors,
|
||||
@Nullable final Object extras) {
|
||||
this.item = item;
|
||||
this.errors = errors;
|
||||
|
@ -37,13 +37,13 @@ public final class ExceptionTag implements MediaItemTag {
|
|||
}
|
||||
|
||||
public static ExceptionTag of(@NonNull final PlayQueueItem playQueueItem,
|
||||
@NonNull final List<Throwable> errors) {
|
||||
@NonNull final List<Exception> errors) {
|
||||
return new ExceptionTag(playQueueItem, errors, null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Throwable> getErrors() {
|
||||
public List<Exception> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import androidx.annotation.Nullable;
|
|||
**/
|
||||
public interface MediaItemTag {
|
||||
|
||||
List<Throwable> getErrors();
|
||||
List<Exception> getErrors();
|
||||
|
||||
int getServiceId();
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public final class PlaceholderTag implements MediaItemTag {
|
|||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Throwable> getErrors() {
|
||||
public List<Exception> getErrors() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public final class StreamInfoTag implements MediaItemTag {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Throwable> getErrors() {
|
||||
public List<Exception> getErrors() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
|
|||
|
||||
private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode());
|
||||
private final PlayQueueItem playQueueItem;
|
||||
private final Throwable error;
|
||||
private final Exception error;
|
||||
private final long retryTimestamp;
|
||||
private final MediaItem mediaItem;
|
||||
/**
|
||||
|
@ -51,7 +51,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
|
|||
* @param retryTimestamp epoch timestamp when this MediaSource can be refreshed
|
||||
*/
|
||||
public FailedMediaSource(@NonNull final PlayQueueItem playQueueItem,
|
||||
@NonNull final Throwable error,
|
||||
@NonNull final Exception error,
|
||||
final long retryTimestamp) {
|
||||
this.playQueueItem = playQueueItem;
|
||||
this.error = error;
|
||||
|
@ -68,7 +68,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
|
|||
}
|
||||
|
||||
public static FailedMediaSource of(@NonNull final PlayQueueItem playQueueItem,
|
||||
@NonNull final Throwable error,
|
||||
@NonNull final Exception error,
|
||||
final long retryWaitMillis) {
|
||||
return new FailedMediaSource(playQueueItem, error,
|
||||
System.currentTimeMillis() + retryWaitMillis);
|
||||
|
|
|
@ -441,7 +441,8 @@ public class MediaSourceManager {
|
|||
if (throwable instanceof ExtractionException) {
|
||||
return FailedMediaSource.of(stream, new StreamInfoLoadException(throwable));
|
||||
}
|
||||
return FailedMediaSource.of(stream, throwable, /*immediatelyRetryable=*/0L);
|
||||
return FailedMediaSource
|
||||
.of(stream, new Exception(throwable), /*immediatelyRetryable=*/0L);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue