Skip to content

Commit 6efa04b

Browse files
[camera,video_player] replace onSurfaceDestroyed with onSurfaceCleanup (#9316)
Replaces deprecated `onSurfaceDestroyed` with `onSurfaceCleanup`, which became available in Flutter 3.29 (which these packages require as of #9317). The changes to video player are non-trivial because rather than make the minimal change, this makes the changes discussed in flutter/flutter#160933 (comment) that motivated the change in API in the first place, which simplifies the handling of backgrounding, and restores background playback. Fixes flutter/flutter#161256 Fixes flutter/flutter#156936 ## Pre-Review Checklist [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent c33fa39 commit 6efa04b

File tree

15 files changed

+61
-200
lines changed

15 files changed

+61
-200
lines changed

packages/camera/camera_android_camerax/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.6.17+1
2+
3+
* Replaces deprecated `onSurfaceDestroyed` with `onSurfaceCleanup`.
4+
15
## 0.6.17
26

37
* Replaces `BroadcastReceiver` usage with an `OrientationEventListener` to detect changes in device

packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PreviewProxyApi.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,7 @@ public void onSurfaceAvailable() {
109109
}
110110

111111
@Override
112-
// TODO(bparrishMines): Replace with onSurfaceCleanup once available on stable. See
113-
// https://github.com/flutter/flutter/issues/161256.
114-
@SuppressWarnings({"deprecation", "removal"})
115-
public void onSurfaceDestroyed() {
112+
public void onSurfaceCleanup() {
116113
// Invalidate the SurfaceRequest so that CameraX knows to to make a new request
117114
// for a surface.
118115
request.invalidate();

packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ TextureRegistry getTextureRegistry() {
113113

114114
final TextureRegistry.SurfaceProducer.Callback callback = callbackCaptor.getValue();
115115

116-
// Verify callback's onSurfaceDestroyed invalidates SurfaceRequest.
117-
simulateSurfaceDestruction(callback);
116+
// Verify callback's onSurfaceCleanup invalidates SurfaceRequest.
117+
simulateSurfaceCleanup(callback);
118118
verify(mockSurfaceRequest).invalidate();
119119

120120
reset(mockSurfaceRequest);
@@ -286,7 +286,7 @@ TextureRegistry getTextureRegistry() {
286286
// see https://github.com/flutter/flutter/issues/16125. This separate method only exists to scope
287287
// the suppression.
288288
@SuppressWarnings({"deprecation", "removal"})
289-
void simulateSurfaceDestruction(TextureRegistry.SurfaceProducer.Callback producerLifecycle) {
290-
producerLifecycle.onSurfaceDestroyed();
289+
void simulateSurfaceCleanup(TextureRegistry.SurfaceProducer.Callback producerLifecycle) {
290+
producerLifecycle.onSurfaceCleanup();
291291
}
292292
}

packages/camera/camera_android_camerax/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: camera_android_camerax
22
description: Android implementation of the camera plugin using the CameraX library.
33
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
5-
version: 0.6.17
5+
version: 0.6.17+1
66

77
environment:
88
sdk: ^3.7.0

packages/video_player/video_player_android/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.8.5
2+
3+
* Replaces deprecated `onSurfaceDestroyed` with `onSurfaceCleanup`.
4+
* Restores background playback support.
5+
16
## 2.8.4
27

38
* Fixes incorrect width/height swap ([bug](https://github.com/flutter/flutter/issues/166097)). The swap was originally required for the uncorrected width/height of `Format` but was mistakenly retained after [switching to `VideoSize`](https://github.com/flutter/packages/pull/6535), which already accounts for rotation.

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
public abstract class ExoPlayerEventListener implements Player.Listener {
1313
private boolean isBuffering = false;
14-
private boolean isInitialized;
14+
private boolean isInitialized = false;
1515
protected final ExoPlayer exoPlayer;
1616
protected final VideoPlayerCallbacks events;
1717

@@ -42,10 +42,9 @@ public int getDegrees() {
4242
}
4343

4444
public ExoPlayerEventListener(
45-
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events, boolean initialized) {
45+
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events) {
4646
this.exoPlayer = exoPlayer;
4747
this.events = events;
48-
this.isInitialized = initialized;
4948
}
5049

5150
private void setBuffering(boolean buffering) {

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerState.java

Lines changed: 0 additions & 71 deletions
This file was deleted.

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
* <p>It provides methods to control playback, adjust volume, and handle seeking.
2323
*/
2424
public abstract class VideoPlayer {
25-
@NonNull private final ExoPlayerProvider exoPlayerProvider;
26-
@NonNull private final MediaItem mediaItem;
27-
@NonNull private final VideoPlayerOptions options;
2825
@NonNull protected final VideoPlayerCallbacks videoPlayerEvents;
2926
@Nullable protected final SurfaceProducer surfaceProducer;
3027
@NonNull protected ExoPlayer exoPlayer;
@@ -47,22 +44,12 @@ public VideoPlayer(
4744
@Nullable SurfaceProducer surfaceProducer,
4845
@NonNull ExoPlayerProvider exoPlayerProvider) {
4946
this.videoPlayerEvents = events;
50-
this.mediaItem = mediaItem;
51-
this.options = options;
52-
this.exoPlayerProvider = exoPlayerProvider;
5347
this.surfaceProducer = surfaceProducer;
54-
this.exoPlayer = createVideoPlayer();
55-
}
56-
57-
@NonNull
58-
protected ExoPlayer createVideoPlayer() {
59-
ExoPlayer exoPlayer = exoPlayerProvider.get();
48+
exoPlayer = exoPlayerProvider.get();
6049
exoPlayer.setMediaItem(mediaItem);
6150
exoPlayer.prepare();
6251
exoPlayer.addListener(createExoPlayerEventListener(exoPlayer, surfaceProducer));
6352
setAudioAttributes(exoPlayer, options.mixWithOthers);
64-
65-
return exoPlayer;
6653
}
6754

6855
@NonNull

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/platformview/PlatformViewExoPlayerEventListener.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import androidx.annotation.NonNull;
88
import androidx.annotation.OptIn;
9-
import androidx.annotation.VisibleForTesting;
109
import androidx.media3.common.Format;
1110
import androidx.media3.common.util.UnstableApi;
1211
import androidx.media3.exoplayer.ExoPlayer;
@@ -15,15 +14,9 @@
1514
import java.util.Objects;
1615

1716
public final class PlatformViewExoPlayerEventListener extends ExoPlayerEventListener {
18-
@VisibleForTesting
1917
public PlatformViewExoPlayerEventListener(
2018
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events) {
21-
this(exoPlayer, events, false);
22-
}
23-
24-
public PlatformViewExoPlayerEventListener(
25-
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events, boolean initialized) {
26-
super(exoPlayer, events, initialized);
19+
super(exoPlayer, events);
2720
}
2821

2922
@OptIn(markerClass = UnstableApi.class)

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/platformview/PlatformViewVideoPlayer.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ public static PlatformViewVideoPlayer create(
6262
@Override
6363
protected ExoPlayerEventListener createExoPlayerEventListener(
6464
@NonNull ExoPlayer exoPlayer, @Nullable SurfaceProducer surfaceProducer) {
65-
// Platform view video player does not suspend and re-create the exoPlayer, hence initialized
66-
// is always false. It also does not require a reference to the SurfaceProducer.
67-
return new PlatformViewExoPlayerEventListener(exoPlayer, videoPlayerEvents, false);
65+
return new PlatformViewExoPlayerEventListener(exoPlayer, videoPlayerEvents);
6866
}
6967
}

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/texture/TextureExoPlayerEventListener.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import android.os.Build;
88
import androidx.annotation.NonNull;
99
import androidx.annotation.OptIn;
10-
import androidx.annotation.VisibleForTesting;
1110
import androidx.media3.common.Format;
1211
import androidx.media3.common.VideoSize;
1312
import androidx.media3.exoplayer.ExoPlayer;
@@ -18,20 +17,11 @@
1817
public final class TextureExoPlayerEventListener extends ExoPlayerEventListener {
1918
private boolean surfaceProducerHandlesCropAndRotation;
2019

21-
@VisibleForTesting
2220
public TextureExoPlayerEventListener(
2321
@NonNull ExoPlayer exoPlayer,
2422
@NonNull VideoPlayerCallbacks events,
2523
boolean surfaceProducerHandlesCropAndRotation) {
26-
this(exoPlayer, events, surfaceProducerHandlesCropAndRotation, false);
27-
}
28-
29-
public TextureExoPlayerEventListener(
30-
@NonNull ExoPlayer exoPlayer,
31-
@NonNull VideoPlayerCallbacks events,
32-
boolean surfaceProducerHandlesCropAndRotation,
33-
boolean initialized) {
34-
super(exoPlayer, events, initialized);
24+
super(exoPlayer, events);
3525
this.surfaceProducerHandlesCropAndRotation = surfaceProducerHandlesCropAndRotation;
3626
}
3727

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/texture/TextureVideoPlayer.java

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
package io.flutter.plugins.videoplayer.texture;
66

77
import android.content.Context;
8+
import android.view.Surface;
89
import androidx.annotation.NonNull;
910
import androidx.annotation.Nullable;
1011
import androidx.annotation.RestrictTo;
1112
import androidx.annotation.VisibleForTesting;
1213
import androidx.media3.common.MediaItem;
1314
import androidx.media3.exoplayer.ExoPlayer;
1415
import io.flutter.plugins.videoplayer.ExoPlayerEventListener;
15-
import io.flutter.plugins.videoplayer.ExoPlayerState;
1616
import io.flutter.plugins.videoplayer.VideoAsset;
1717
import io.flutter.plugins.videoplayer.VideoPlayer;
1818
import io.flutter.plugins.videoplayer.VideoPlayerCallbacks;
@@ -27,8 +27,8 @@
2727
* the texture.
2828
*/
2929
public final class TextureVideoPlayer extends VideoPlayer implements SurfaceProducer.Callback {
30-
@Nullable private ExoPlayerState savedStateDuring;
31-
30+
// True when the ExoPlayer instance has a null surface.
31+
private boolean needsSurface = true;
3232
/**
3333
* Creates a texture video player.
3434
*
@@ -70,7 +70,9 @@ public TextureVideoPlayer(
7070

7171
surfaceProducer.setCallback(this);
7272

73-
this.exoPlayer.setVideoSurface(surfaceProducer.getSurface());
73+
Surface surface = surfaceProducer.getSurface();
74+
this.exoPlayer.setVideoSurface(surface);
75+
needsSurface = surface == null;
7476
}
7577

7678
@NonNull
@@ -83,44 +85,31 @@ protected ExoPlayerEventListener createExoPlayerEventListener(
8385
}
8486
boolean surfaceProducerHandlesCropAndRotation = surfaceProducer.handlesCropAndRotation();
8587
return new TextureExoPlayerEventListener(
86-
exoPlayer,
87-
videoPlayerEvents,
88-
surfaceProducerHandlesCropAndRotation,
89-
playerHasBeenSuspended());
88+
exoPlayer, videoPlayerEvents, surfaceProducerHandlesCropAndRotation);
9089
}
9190

9291
@RestrictTo(RestrictTo.Scope.LIBRARY)
9392
public void onSurfaceAvailable() {
94-
if (savedStateDuring != null) {
95-
exoPlayer = createVideoPlayer();
93+
if (needsSurface) {
94+
// TextureVideoPlayer must always set a surfaceProducer.
95+
assert surfaceProducer != null;
9696
exoPlayer.setVideoSurface(surfaceProducer.getSurface());
97-
savedStateDuring.restore(exoPlayer);
98-
savedStateDuring = null;
97+
needsSurface = false;
9998
}
10099
}
101100

102101
@RestrictTo(RestrictTo.Scope.LIBRARY)
103-
// TODO(bparrishMines): Replace with onSurfaceCleanup once available on stable. See
104-
// https://github.com/flutter/flutter/issues/161256.
105-
@SuppressWarnings({"deprecation", "removal"})
106-
public void onSurfaceDestroyed() {
107-
// Intentionally do not call pause/stop here, because the surface has already been released
108-
// at this point (see https://github.com/flutter/flutter/issues/156451).
109-
savedStateDuring = ExoPlayerState.save(exoPlayer);
110-
exoPlayer.release();
111-
}
112-
113-
private boolean playerHasBeenSuspended() {
114-
return savedStateDuring != null;
102+
public void onSurfaceCleanup() {
103+
exoPlayer.setVideoSurface(null);
104+
needsSurface = true;
115105
}
116106

117107
public void dispose() {
118108
// Super must be called first to ensure the player is released before the surface.
119109
super.dispose();
120110

111+
// TextureVideoPlayer must always set a surfaceProducer.
112+
assert surfaceProducer != null;
121113
surfaceProducer.release();
122-
// TODO(matanlurey): Remove when embedder no longer calls-back once released.
123-
// https://github.com/flutter/flutter/issues/156434.
124-
surfaceProducer.setCallback(null);
125114
}
126115
}

packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/ExoPlayerEventListenerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public final class ExoPlayerEventListenerTest {
4444
*/
4545
private static final class TestExoPlayerEventListener extends ExoPlayerEventListener {
4646
public TestExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks callbacks) {
47-
super(exoPlayer, callbacks, false);
47+
super(exoPlayer, callbacks);
4848
}
4949

5050
@Override

0 commit comments

Comments
 (0)