Make onPlayerError take a PlaybackException

PiperOrigin-RevId: 380174672
This commit is contained in:
aquilescanta 2021-06-18 14:35:41 +01:00 committed by Oliver Woodman
parent 1ef6326385
commit fc1d3dd192
18 changed files with 81 additions and 61 deletions

View File

@ -32,7 +32,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
@ -424,7 +423,7 @@ public class PlayerActivity extends AppCompatActivity
}
@Override
public void onPlayerError(@NonNull ExoPlaybackException e) {
public void onPlayerError(@NonNull PlaybackException e) {
if (e.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
player.seekToDefaultPosition();
player.prepare();

View File

@ -67,21 +67,23 @@ public void onIsPlayingChanged(boolean isPlaying) {
### Playback errors ###
Errors that cause playback to fail can be received by implementing
`onPlayerError(ExoPlaybackException error)` in a registered
`onPlayerError(PlaybackException error)` in a registered
`Player.Listener`. When a failure occurs, this method will be called
immediately before the playback state transitions to `Player.STATE_IDLE`.
Failed or stopped playbacks can be retried by calling `ExoPlayer.retry`.
[`ExoPlaybackException`][] has a `type` field, as well as corresponding getter
methods that return cause exceptions providing more information about the
failure. The example below shows how to detect when a playback has failed due to
a HTTP networking issue.
Note that some [`Player`][] implementations pass instances of subclasses of
`PlaybackException` to provide additional information about the failure. For
example, [`ExoPlayer`][] passes [`ExoPlaybackException`][] which has `type`,
`rendererIndex` and other ExoPlayer-specific fields.
The following example shows how to detect when a playback has failed due to an
HTTP networking issue:
~~~
@Override
public void onPlayerError(ExoPlaybackException error) {
if (error.type == ExoPlaybackException.TYPE_SOURCE) {
IOException cause = error.getSourceException();
public void onPlayerError(PlaybackException error) {
Throwable cause = error.getCause();
if (cause instanceof HttpDataSourceException) {
// An HTTP error occurred.
HttpDataSourceException httpError = (HttpDataSourceException) cause;
@ -98,7 +100,6 @@ public void onPlayerError(ExoPlaybackException error) {
}
}
}
}
~~~
{: .language-java }
@ -228,6 +229,8 @@ player
[`Player.Listener`]: {{ site.exo_sdk }}/Player.Listener.html
[Javadoc]: {{ site.exo_sdk }}/Player.Listener.html
[`Individual callbacks vs onEvents`]: #individual-callbacks-vs-onevents
[`Player`]: {{ site.exo_sdk }}/Player.html
[`ExoPlayer`]: {{ site.exo_sdk }}/ExoPlayer.html
[`ExoPlaybackException`]: {{ site.exo_sdk }}/ExoPlaybackException.html
[log output]: event-logger.html
[`Parameters`]: {{ site.exo_sdk }}/trackselection/DefaultTrackSelector.Parameters.html

View File

@ -142,7 +142,7 @@ the demo app exemplifies this approach.
~~~
@Override
public void onPlayerError(ExoPlaybackException e) {
public void onPlayerError(PlaybackException e) {
if (e.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
// Re-initialize player at the current live window default position.
player.seekToDefaultPosition();

View File

@ -23,8 +23,8 @@ import android.os.Looper;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory;
@ -96,7 +96,7 @@ public class FlacPlaybackTest {
private final AudioSink audioSink;
@Nullable private SimpleExoPlayer player;
@Nullable private ExoPlaybackException playbackException;
@Nullable private PlaybackException playbackException;
public TestPlaybackRunnable(Uri uri, Context context, AudioSink audioSink) {
this.uri = uri;
@ -129,7 +129,7 @@ public class FlacPlaybackTest {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
playbackException = error;
}

View File

@ -51,8 +51,8 @@ import com.google.ads.interactivemedia.v3.api.player.ContentProgressProvider;
import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer;
import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
@ -514,7 +514,7 @@ import java.util.Map;
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
if (imaAdState != IMA_AD_STATE_NONE) {
AdMediaInfo adMediaInfo = checkNotNull(imaAdMediaInfo);
for (int i = 0; i < adCallbacks.size(); i++) {

View File

@ -255,15 +255,16 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
}
@Override
public void onPlayerError(ExoPlaybackException exception) {
public void onPlayerError(PlaybackException exception) {
Callback callback = getCallback();
if (errorMessageProvider != null) {
Pair<Integer, String> errorMessage = errorMessageProvider.getErrorMessage(exception);
callback.onError(LeanbackPlayerAdapter.this, errorMessage.first, errorMessage.second);
} else {
// TODO: Conditionally assign the rendererIndex depending on whether the exception is an
// ExoPlaybackException once onPlayerError takes a PlaybackException.
int rendererIndex = exception.rendererIndex;
int rendererIndex = C.INDEX_UNSET;
if (exception instanceof ExoPlaybackException) {
rendererIndex = ((ExoPlaybackException) exception).rendererIndex;
}
callback.onError(
LeanbackPlayerAdapter.this,
exception.errorCode,

View File

@ -27,8 +27,8 @@ import androidx.media2.common.SessionPlayer;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ControlDispatcher;
import com.google.android.exoplayer2.DefaultControlDispatcher;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
@ -597,7 +597,7 @@ import java.util.List;
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
updateSessionPlayerState();
}

View File

@ -23,8 +23,8 @@ import android.os.Looper;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory;
@ -79,7 +79,7 @@ public class OpusPlaybackTest {
private final Uri uri;
@Nullable private SimpleExoPlayer player;
@Nullable private ExoPlaybackException playbackException;
@Nullable private PlaybackException playbackException;
public TestPlaybackRunnable(Uri uri, Context context) {
this.uri = uri;
@ -109,7 +109,7 @@ public class OpusPlaybackTest {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
playbackException = error;
}

View File

@ -24,8 +24,8 @@ import android.os.Looper;
import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory;
@ -107,7 +107,7 @@ public class VpxPlaybackTest {
private final Uri uri;
@Nullable private SimpleExoPlayer player;
@Nullable private ExoPlaybackException playbackException;
@Nullable private PlaybackException playbackException;
public TestPlaybackRunnable(Uri uri, Context context) {
this.uri = uri;
@ -144,7 +144,7 @@ public class VpxPlaybackTest {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
playbackException = error;
}

View File

@ -681,7 +681,7 @@ public class ForwardingPlayer implements Player {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
eventListener.onPlayerError(error);
}

View File

@ -267,9 +267,12 @@ public interface Player {
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
* other events that happen in the same {@link Looper} message queue iteration.
*
* <p>Implementations of Player may pass an instance of a subclass of {@link PlaybackException}
* to this method in order to include more information about the error.
*
* @param error The error.
*/
default void onPlayerError(ExoPlaybackException error) {}
default void onPlayerError(PlaybackException error) {}
/**
* @deprecated Use {@link #onPositionDiscontinuity(PositionInfo, PositionInfo, int)} instead.
@ -1488,14 +1491,14 @@ public interface Player {
/**
* Returns the error that caused playback to fail. This is the same error that will have been
* reported via {@link Listener#onPlayerError(ExoPlaybackException)} at the time of failure. It
* can be queried using this method until the player is re-prepared.
* reported via {@link Listener#onPlayerError(PlaybackException)} at the time of failure. It can
* be queried using this method until the player is re-prepared.
*
* <p>Note that this method will always return {@code null} if {@link #getPlaybackState()} is not
* {@link #STATE_IDLE}.
*
* @return The error, or {@code null}.
* @see Listener#onPlayerError(ExoPlaybackException)
* @see Listener#onPlayerError(PlaybackException)
*/
@Nullable
PlaybackException getPlayerError();

View File

@ -245,8 +245,7 @@ public final class PlayerMessage {
/**
* Sends the message. If the target throws an {@link ExoPlaybackException} then it is propagated
* out of the player as an error using {@link
* Player.Listener#onPlayerError(ExoPlaybackException)}.
* out of the player as an error using {@link Player.Listener#onPlayerError(PlaybackException)}.
*
* @return This message.
* @throws IllegalStateException If this message has already been sent.

View File

@ -26,6 +26,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.MediaMetadata;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
@ -708,15 +709,22 @@ public class AnalyticsCollector
}
@Override
public final void onPlayerError(ExoPlaybackException error) {
EventTime eventTime =
error.mediaPeriodId != null
? generateEventTime(new MediaPeriodId(error.mediaPeriodId))
: generateCurrentPlayerMediaPeriodEventTime();
public final void onPlayerError(PlaybackException error) {
EventTime eventTime = null;
if (error instanceof ExoPlaybackException) {
ExoPlaybackException exoError = (ExoPlaybackException) error;
if (exoError.mediaPeriodId != null) {
eventTime = generateEventTime(new MediaPeriodId(exoError.mediaPeriodId));
}
}
if (eventTime == null) {
eventTime = generateCurrentPlayerMediaPeriodEventTime();
}
EventTime finalEventTime = eventTime;
sendEvent(
eventTime,
AnalyticsListener.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerError(eventTime, error));
listener -> listener.onPlayerError(finalEventTime, error));
}
// Calling deprecated callback.

View File

@ -650,6 +650,9 @@ public interface AnalyticsListener {
/**
* Called when a fatal player error occurred.
*
* <p>Implementations of {@link Player} may pass an instance of a subclass of {@link
* PlaybackException} to this method in order to include more information about the error.
*
* @param eventTime The event time.
* @param error The error.
*/

View File

@ -21,6 +21,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import java.lang.annotation.Documented;
@ -122,7 +123,7 @@ public interface AudioSink {
* wishes to do so.
*
* <p>Fatal errors that cannot be recovered will be reported wrapped in a {@link
* ExoPlaybackException} by {@link Player.Listener#onPlayerError(ExoPlaybackException)}.
* ExoPlaybackException} by {@link Player.Listener#onPlayerError(PlaybackException)}.
*
* @param audioSinkError The error that occurred. Typically an {@link InitializationException},
* a {@link WriteException}, or an {@link UnexpectedDiscontinuityException}.

View File

@ -20,8 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player.Listener;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.robolectric.RobolectricUtil;
@ -95,7 +95,7 @@ public final class RtspPlaybackTest {
player.addListener(
new Listener() {
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
playbackError.set(error);
}
});

View File

@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.os.Looper;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
@ -199,8 +200,9 @@ public class TestPlayerRunHelper {
Player.Listener listener =
new Player.Listener() {
@Override
public void onPlayerError(ExoPlaybackException error) {
receivedError.set(error);
public void onPlayerError(PlaybackException error) {
// ExoPlayer is guaranteed to throw an ExoPlaybackException.
receivedError.set((ExoPlaybackException) error);
player.removeListener(this);
}
};

View File

@ -29,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory;
@ -692,7 +693,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
}
@Override
public void onPlayerError(ExoPlaybackException error) {
public void onPlayerError(PlaybackException error) {
handleException(error);
}