diff --git a/packages/video_player/video_player_android/CHANGELOG.md b/packages/video_player/video_player_android/CHANGELOG.md index 9486013f6344..e2b39f8f44f8 100644 --- a/packages/video_player/video_player_android/CHANGELOG.md +++ b/packages/video_player/video_player_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.4.17 + +* Revert Impeller support. + ## 2.4.16 * [Supports Impeller](https://docs.flutter.dev/release/breaking-changes/android-surface-plugins). 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 5cb5f0e2b304..b8b781912308 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 @@ -9,6 +9,7 @@ import android.content.Context; import android.net.Uri; +import android.view.Surface; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; @@ -47,7 +48,9 @@ final class VideoPlayer { private ExoPlayer exoPlayer; - private TextureRegistry.SurfaceProducer surfaceProducer; + private Surface surface; + + private final TextureRegistry.SurfaceTextureEntry textureEntry; private QueuingEventSink eventSink; @@ -55,29 +58,22 @@ final class VideoPlayer { private static final String USER_AGENT = "User-Agent"; - private MediaSource mediaSource; - @VisibleForTesting boolean isInitialized = false; - // State that must be reset when the surface is re-created. private final VideoPlayerOptions options; - private long restoreVideoLocation = 0; - private int restoreRepeatMode = 0; - private float restoreVolume = 0; - private PlaybackParameters restorePlaybackParameters; private DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory(); VideoPlayer( Context context, EventChannel eventChannel, - TextureRegistry.SurfaceProducer surfaceProducer, + TextureRegistry.SurfaceTextureEntry textureEntry, String dataSource, String formatHint, @NonNull Map httpHeaders, VideoPlayerOptions options) { this.eventChannel = eventChannel; - this.surfaceProducer = surfaceProducer; + this.textureEntry = textureEntry; this.options = options; ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build(); @@ -87,7 +83,7 @@ final class VideoPlayer { DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(context, httpDataSourceFactory); - mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint); + MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint); exoPlayer.setMediaSource(mediaSource); exoPlayer.prepare(); @@ -100,12 +96,12 @@ final class VideoPlayer { VideoPlayer( ExoPlayer exoPlayer, EventChannel eventChannel, - TextureRegistry.SurfaceProducer surfaceProducer, + TextureRegistry.SurfaceTextureEntry textureEntry, VideoPlayerOptions options, QueuingEventSink eventSink, DefaultHttpDataSource.Factory httpDataSourceFactory) { this.eventChannel = eventChannel; - this.surfaceProducer = surfaceProducer; + this.textureEntry = textureEntry; this.options = options; this.httpDataSourceFactory = httpDataSourceFactory; @@ -173,40 +169,6 @@ private MediaSource buildMediaSource( } } - public void recreateSurface(Context context) { - ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build(); - - exoPlayer.setMediaSource(mediaSource); - exoPlayer.prepare(); - - setUpVideoPlayer(exoPlayer, new QueuingEventSink()); - exoPlayer.setVideoSurface(surfaceProducer.getSurface()); - exoPlayer.seekTo(restoreVideoLocation); - exoPlayer.setRepeatMode(restoreRepeatMode); - exoPlayer.setVolume(restoreVolume); - if (restorePlaybackParameters != null) { - exoPlayer.setPlaybackParameters(restorePlaybackParameters); - } - } - - public void pauseSurface() { - if (!isInitialized) { - return; - } - restoreVideoLocation = exoPlayer.getCurrentPosition(); - restoreRepeatMode = exoPlayer.getRepeatMode(); - restoreVolume = exoPlayer.getVolume(); - restorePlaybackParameters = exoPlayer.getPlaybackParameters(); - eventChannel.setStreamHandler(null); - if (isInitialized) { - exoPlayer.stop(); - } - if (exoPlayer != null) { - exoPlayer.release(); - } - isInitialized = false; - } - private void setUpVideoPlayer(ExoPlayer exoPlayer, QueuingEventSink eventSink) { this.exoPlayer = exoPlayer; this.eventSink = eventSink; @@ -224,7 +186,8 @@ public void onCancel(Object o) { } }); - exoPlayer.setVideoSurface(surfaceProducer.getSurface()); + surface = new Surface(textureEntry.surfaceTexture()); + exoPlayer.setVideoSurface(surface); setAudioAttributes(exoPlayer, options.mixWithOthers); exoPlayer.addListener( @@ -371,8 +334,11 @@ void dispose() { if (isInitialized) { exoPlayer.stop(); } - surfaceProducer.release(); + textureEntry.release(); eventChannel.setStreamHandler(null); + if (surface != null) { + surface.release(); + } if (exoPlayer != null) { exoPlayer.release(); } diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index 54234dd6df8e..5259e1ad3fed 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -8,16 +8,9 @@ import android.os.Build; import android.util.LongSparseArray; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.lifecycle.DefaultLifecycleObserver; -import androidx.lifecycle.Lifecycle; -import androidx.lifecycle.LifecycleOwner; import io.flutter.FlutterInjector; import io.flutter.Log; import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.embedding.engine.plugins.activity.ActivityAware; -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; -import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; import io.flutter.plugins.videoplayer.Messages.AndroidVideoPlayerApi; @@ -36,13 +29,11 @@ import javax.net.ssl.HttpsURLConnection; /** Android platform implementation of the VideoPlayerPlugin. */ -public class VideoPlayerPlugin - implements FlutterPlugin, AndroidVideoPlayerApi, DefaultLifecycleObserver, ActivityAware { +public class VideoPlayerPlugin implements FlutterPlugin, AndroidVideoPlayerApi { private static final String TAG = "VideoPlayerPlugin"; private final LongSparseArray videoPlayers = new LongSparseArray<>(); private FlutterState flutterState; private final VideoPlayerOptions options = new VideoPlayerOptions(); - @Nullable Lifecycle lifecycle; /** Register this with the v2 embedding for the plugin to respond to lifecycle callbacks. */ public VideoPlayerPlugin() {} @@ -92,7 +83,7 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { } flutterState.stopListening(binding.getBinaryMessenger()); flutterState = null; - performDestroy(); + onDestroy(); } private void disposeAllPlayers() { @@ -102,7 +93,7 @@ private void disposeAllPlayers() { videoPlayers.clear(); } - public void performDestroy() { + public void onDestroy() { // The whole FlutterView is being destroyed. Here we release resources acquired for all // instances // of VideoPlayer. Once https://github.com/flutter/flutter/issues/19358 is resolved this may @@ -116,7 +107,8 @@ public void initialize() { } public @NonNull TextureMessage create(@NonNull CreateMessage arg) { - TextureRegistry.SurfaceProducer handle = flutterState.textureRegistry.createSurfaceProducer(); + TextureRegistry.SurfaceTextureEntry handle = + flutterState.textureRegistry.createSurfaceTexture(); EventChannel eventChannel = new EventChannel( flutterState.binaryMessenger, "flutter.io/videoPlayer/videoEvents" + handle.id()); @@ -152,6 +144,7 @@ public void initialize() { options); } videoPlayers.put(handle.id(), player); + return new TextureMessage.Builder().setTextureId(handle.id()).build(); } @@ -207,62 +200,6 @@ public void setMixWithOthers(@NonNull MixWithOthersMessage arg) { options.mixWithOthers = arg.getMixWithOthers(); } - // Activity Aware - - @Override - public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding); - lifecycle.addObserver(this); - } - - @Override - public void onDetachedFromActivity() {} - - @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { - onAttachedToActivity(binding); - } - - @Override - public void onDetachedFromActivityForConfigChanges() { - onDetachedFromActivity(); - } - - // DefaultLifecycleObserver - @Override - public void onResume(@NonNull LifecycleOwner owner) { - recreateAllSurfaces(); - } - - @Override - public void onPause(@NonNull LifecycleOwner owner) { - destroyAllSurfaces(); - } - - @Override - public void onStop(@NonNull LifecycleOwner owner) { - destroyAllSurfaces(); - } - - @Override - public void onDestroy(@NonNull LifecycleOwner owner) { - if (lifecycle != null) { - lifecycle.removeObserver(this); - } - } - - private void destroyAllSurfaces() { - for (int i = 0; i < videoPlayers.size(); i++) { - videoPlayers.valueAt(i).pauseSurface(); - } - } - - private void recreateAllSurfaces() { - for (int i = 0; i < videoPlayers.size(); i++) { - videoPlayers.valueAt(i).recreateSurface(flutterState.applicationContext); - } - } - private interface KeyForAssetFn { String get(String asset); } 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 e9f69a57d36b..7ff5000d3cf7 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 @@ -13,6 +13,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; +import android.graphics.SurfaceTexture; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.PlaybackException; @@ -37,7 +38,8 @@ public class VideoPlayerTest { private ExoPlayer fakeExoPlayer; private EventChannel fakeEventChannel; - private TextureRegistry.SurfaceProducer fakeSurfaceProducer; + private TextureRegistry.SurfaceTextureEntry fakeSurfaceTextureEntry; + private SurfaceTexture fakeSurfaceTexture; private VideoPlayerOptions fakeVideoPlayerOptions; private QueuingEventSink fakeEventSink; private DefaultHttpDataSource.Factory httpDataSourceFactorySpy; @@ -50,7 +52,9 @@ public void before() { fakeExoPlayer = mock(ExoPlayer.class); fakeEventChannel = mock(EventChannel.class); - fakeSurfaceProducer = mock(TextureRegistry.SurfaceProducer.class); + fakeSurfaceTextureEntry = mock(TextureRegistry.SurfaceTextureEntry.class); + fakeSurfaceTexture = mock(SurfaceTexture.class); + when(fakeSurfaceTextureEntry.surfaceTexture()).thenReturn(fakeSurfaceTexture); fakeVideoPlayerOptions = mock(VideoPlayerOptions.class); fakeEventSink = mock(QueuingEventSink.class); httpDataSourceFactorySpy = spy(new DefaultHttpDataSource.Factory()); @@ -62,7 +66,7 @@ public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -81,7 +85,7 @@ public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -107,7 +111,7 @@ public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -131,7 +135,7 @@ public void sendInitializedSendsExpectedEvent_90RotationDegrees() { new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -160,7 +164,7 @@ public void sendInitializedSendsExpectedEvent_270RotationDegrees() { new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -189,7 +193,7 @@ public void sendInitializedSendsExpectedEvent_0RotationDegrees() { new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -218,7 +222,7 @@ public void sendInitializedSendsExpectedEvent_180RotationDegrees() { new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -247,7 +251,7 @@ public void onIsPlayingChangedSendsExpectedEvent() { new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); @@ -292,7 +296,7 @@ public void behindLiveWindowErrorResetsPlayerToDefaultPosition() { new VideoPlayer( fakeExoPlayer, fakeEventChannel, - fakeSurfaceProducer, + fakeSurfaceTextureEntry, fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); diff --git a/packages/video_player/video_player_android/example/android/app/src/test/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java b/packages/video_player/video_player_android/example/android/app/src/test/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java index d41e80cf6d1a..750d4a486dda 100644 --- a/packages/video_player/video_player_android/example/android/app/src/test/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java +++ b/packages/video_player/video_player_android/example/android/app/src/test/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java @@ -45,6 +45,6 @@ public void disposeAllPlayers() { engine.destroy(); verify(videoPlayerPlugin, times(1)).onDetachedFromEngine(pluginBindingCaptor.capture()); - verify(videoPlayerPlugin, times(1)).performDestroy(); + verify(videoPlayerPlugin, times(1)).onDestroy(); } } diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index b9de2c60ffe5..864c3ec8efac 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.16 +version: 2.4.17 environment: sdk: ^3.4.0 @@ -20,7 +20,6 @@ flutter: dependencies: flutter: sdk: flutter - flutter_plugin_android_lifecycle: ^2.0.1 video_player_platform_interface: ">=6.1.0 <7.0.0" dev_dependencies: