Skip to content

Commit b727dff

Browse files
kmod-midoriadsonpleal
authored andcommitted
fix(video_player): buffering state events missing on Android & Web (fixes flutter/flutter#28494) (flutter#2563)
1 parent 4eb91b0 commit b727dff

File tree

7 files changed

+107
-4
lines changed

7 files changed

+107
-4
lines changed

packages/video_player/video_player/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.0-nullsafety.4
2+
3+
* Fixed an issue where `isBuffering` was not updating on Android.
4+
15
## 2.0.0-nullsafety.3
26

37
* Dart null safety requires `2.12`.

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

+16
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,21 @@ public void onCancel(Object o) {
169169

170170
exoPlayer.addListener(
171171
new EventListener() {
172+
private boolean isBuffering = false;
173+
174+
public void setBuffering(boolean buffering) {
175+
if (isBuffering != buffering) {
176+
isBuffering = buffering;
177+
Map<String, Object> event = new HashMap<>();
178+
event.put("event", isBuffering ? "bufferingStart" : "bufferingEnd");
179+
eventSink.success(event);
180+
}
181+
}
172182

173183
@Override
174184
public void onPlaybackStateChanged(final int playbackState) {
175185
if (playbackState == Player.STATE_BUFFERING) {
186+
setBuffering(true);
176187
sendBufferingUpdate();
177188
} else if (playbackState == Player.STATE_READY) {
178189
if (!isInitialized) {
@@ -184,10 +195,15 @@ public void onPlaybackStateChanged(final int playbackState) {
184195
event.put("event", "completed");
185196
eventSink.success(event);
186197
}
198+
199+
if (playbackState != Player.STATE_BUFFERING) {
200+
setBuffering(false);
201+
}
187202
}
188203

189204
@Override
190205
public void onPlayerError(final ExoPlaybackException error) {
206+
setBuffering(false);
191207
if (eventSink != null) {
192208
eventSink.error("VideoError", "Video player had error " + error, null);
193209
}

packages/video_player/video_player/example/integration_test/video_player_test.dart

+54-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
65
// TODO(amirh): Remove this once flutter_driver supports null safety.
76
// https://github.com/flutter/flutter/issues/71379
87
// @dart = 2.9
8+
import 'dart:async';
99

10+
import 'package:flutter/foundation.dart';
1011
import 'package:flutter/material.dart';
1112
import 'package:integration_test/integration_test.dart';
1213
import 'package:flutter_test/flutter_test.dart';
@@ -34,10 +35,58 @@ void main() {
3435
const Duration(seconds: 7, milliseconds: 540));
3536
});
3637

38+
testWidgets(
39+
'reports buffering status',
40+
(WidgetTester tester) async {
41+
VideoPlayerController networkController = VideoPlayerController.network(
42+
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
43+
);
44+
await networkController.initialize();
45+
// Mute to allow playing without DOM interaction on Web.
46+
// See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
47+
await networkController.setVolume(0);
48+
final Completer<void> started = Completer();
49+
final Completer<void> ended = Completer();
50+
bool startedBuffering = false;
51+
bool endedBuffering = false;
52+
networkController.addListener(() {
53+
if (networkController.value.isBuffering && !startedBuffering) {
54+
startedBuffering = true;
55+
started.complete();
56+
}
57+
if (startedBuffering &&
58+
!networkController.value.isBuffering &&
59+
!endedBuffering) {
60+
endedBuffering = true;
61+
ended.complete();
62+
}
63+
});
64+
65+
await networkController.play();
66+
await networkController.seekTo(const Duration(seconds: 5));
67+
await tester.pumpAndSettle(_playDuration);
68+
await networkController.pause();
69+
70+
expect(networkController.value.isPlaying, false);
71+
expect(networkController.value.position,
72+
(Duration position) => position > const Duration(seconds: 0));
73+
74+
await started;
75+
expect(startedBuffering, true);
76+
77+
await ended;
78+
expect(endedBuffering, true);
79+
},
80+
skip: !(kIsWeb || defaultTargetPlatform == TargetPlatform.android),
81+
);
82+
3783
testWidgets(
3884
'can be played',
3985
(WidgetTester tester) async {
4086
await _controller.initialize();
87+
// Mute to allow playing without DOM interaction on Web.
88+
// See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
89+
await _controller.setVolume(0);
4190

4291
await _controller.play();
4392
await tester.pumpAndSettle(_playDuration);
@@ -63,6 +112,9 @@ void main() {
63112
'can be paused',
64113
(WidgetTester tester) async {
65114
await _controller.initialize();
115+
// Mute to allow playing without DOM interaction on Web.
116+
// See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
117+
await _controller.setVolume(0);
66118

67119
// Play for a second, then pause, and then wait a second.
68120
await _controller.play();
@@ -109,6 +161,6 @@ void main() {
109161

110162
await tester.pumpAndSettle();
111163
expect(_controller.value.isPlaying, true);
112-
});
164+
}, skip: kIsWeb); // Web does not support local assets.
113165
});
114166
}

packages/video_player/video_player/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Flutter plugin for displaying inline video with other Flutter
44
# 0.10.y+z is compatible with 1.0.0, if you land a breaking change bump
55
# the version to 2.0.0.
66
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
7-
version: 2.0.0-nullsafety.3
7+
version: 2.0.0-nullsafety.4
88
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
99

1010
flutter:

packages/video_player/video_player_web/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.0-nullsafety.2
2+
3+
* Fixed an issue where `isBuffering` was not updating on Web.
4+
15
## 2.0.0-nullsafety.1
26

37
* Bump Dart SDK to support null safety.

packages/video_player/video_player_web/lib/video_player_web.dart

+27
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,17 @@ class _VideoPlayer {
156156
final int textureId;
157157
late VideoElement videoElement;
158158
bool isInitialized = false;
159+
bool isBuffering = false;
160+
161+
void setBuffering(bool buffering) {
162+
if (isBuffering != buffering) {
163+
isBuffering = buffering;
164+
eventController.add(VideoEvent(
165+
eventType: isBuffering
166+
? VideoEventType.bufferingStart
167+
: VideoEventType.bufferingEnd));
168+
}
169+
}
159170

160171
void initialize() {
161172
videoElement = VideoElement()
@@ -176,10 +187,25 @@ class _VideoPlayer {
176187
isInitialized = true;
177188
sendInitialized();
178189
}
190+
setBuffering(false);
191+
});
192+
193+
videoElement.onCanPlayThrough.listen((dynamic _) {
194+
setBuffering(false);
195+
});
196+
197+
videoElement.onPlaying.listen((dynamic _) {
198+
setBuffering(false);
199+
});
200+
201+
videoElement.onWaiting.listen((dynamic _) {
202+
setBuffering(true);
203+
sendBufferingUpdate();
179204
});
180205

181206
// The error event fires when some form of error occurs while attempting to load or perform the media.
182207
videoElement.onError.listen((Event _) {
208+
setBuffering(false);
183209
// The Event itself (_) doesn't contain info about the actual error.
184210
// We need to look at the HTMLMediaElement.error.
185211
// See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error
@@ -192,6 +218,7 @@ class _VideoPlayer {
192218
});
193219

194220
videoElement.onEnded.listen((dynamic _) {
221+
setBuffering(false);
195222
eventController.add(VideoEvent(eventType: VideoEventType.completed));
196223
});
197224
}

packages/video_player/video_player_web/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/v
44
# 0.1.y+z is compatible with 1.0.0, if you land a breaking change bump
55
# the version to 2.0.0.
66
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
7-
version: 2.0.0-nullsafety.1
7+
version: 2.0.0-nullsafety.2
88

99
flutter:
1010
plugin:

0 commit comments

Comments
 (0)