diff --git a/packages/video_player/video_player_android/CHANGELOG.md b/packages/video_player/video_player_android/CHANGELOG.md index 8faafadf36b..1606316b554 100644 --- a/packages/video_player/video_player_android/CHANGELOG.md +++ b/packages/video_player/video_player_android/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 2.4.12 * Updates compileSdk version to 34. +* Adds error handling for `BehindLiveWindowException`, which may occur upon live-video playback failure. ## 2.4.11 diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 57fc1037cc7..b8b78191230 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -227,7 +227,11 @@ public void onPlaybackStateChanged(final int playbackState) { @Override public void onPlayerError(@NonNull final PlaybackException error) { setBuffering(false); - if (eventSink != null) { + if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { + // See https://exoplayer.dev/live-streaming.html#behindlivewindowexception-and-error_code_behind_live_window + exoPlayer.seekToDefaultPosition(); + exoPlayer.prepare(); + } else if (eventSink != null) { eventSink.error("VideoError", "Video player had error " + error, null); } } diff --git a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java index 2ba6ee05388..85c1715dd6c 100644 --- a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java +++ b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java @@ -5,22 +5,25 @@ package io.flutter.plugins.videoplayer; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.*; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; import io.flutter.plugin.common.EventChannel; import io.flutter.view.TextureRegistry; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -278,4 +281,28 @@ public void onIsPlayingChangedSendsExpectedEvent() { assertEquals(event2.get("event"), "isPlayingStateUpdate"); assertEquals(event2.get("isPlaying"), false); } + + @Test + public void behindLiveWindowErrorResetsPlayerToDefaultPosition() { + List listeners = new LinkedList<>(); + doAnswer(invocation -> listeners.add(invocation.getArgument(0))) + .when(fakeExoPlayer) + .addListener(any()); + + VideoPlayer unused = + new VideoPlayer( + fakeExoPlayer, + fakeEventChannel, + fakeSurfaceTextureEntry, + fakeVideoPlayerOptions, + fakeEventSink, + httpDataSourceFactorySpy); + + PlaybackException exception = + new PlaybackException(null, null, PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW); + listeners.forEach(listener -> listener.onPlayerError(exception)); + + verify(fakeExoPlayer).seekToDefaultPosition(); + verify(fakeExoPlayer).prepare(); + } } diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index 5f488dde746..3a8bbb0aced 100644 --- a/packages/video_player/video_player_android/pubspec.yaml +++ b/packages/video_player/video_player_android/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_android description: Android implementation of the video_player plugin. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.4.11 +version: 2.4.12 environment: sdk: ">=3.0.0 <4.0.0"