fix(video_player): buffering state events missing on Android & Web (fixes flutter/flutter#28494) (#2563)
diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md
index 14eaae3..e2bca40 100644
--- a/packages/video_player/video_player/CHANGELOG.md
+++ b/packages/video_player/video_player/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.0.0-nullsafety.4
+
+* Fixed an issue where `isBuffering` was not updating on Android.
+
## 2.0.0-nullsafety.3
* Dart null safety requires `2.12`.
diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java
index 33c2f42..6565750 100644
--- a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java
+++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java
@@ -169,10 +169,21 @@
exoPlayer.addListener(
new EventListener() {
+ private boolean isBuffering = false;
+
+ public void setBuffering(boolean buffering) {
+ if (isBuffering != buffering) {
+ isBuffering = buffering;
+ Map<String, Object> event = new HashMap<>();
+ event.put("event", isBuffering ? "bufferingStart" : "bufferingEnd");
+ eventSink.success(event);
+ }
+ }
@Override
public void onPlaybackStateChanged(final int playbackState) {
if (playbackState == Player.STATE_BUFFERING) {
+ setBuffering(true);
sendBufferingUpdate();
} else if (playbackState == Player.STATE_READY) {
if (!isInitialized) {
@@ -184,10 +195,15 @@
event.put("event", "completed");
eventSink.success(event);
}
+
+ if (playbackState != Player.STATE_BUFFERING) {
+ setBuffering(false);
+ }
}
@Override
public void onPlayerError(final ExoPlaybackException error) {
+ setBuffering(false);
if (eventSink != null) {
eventSink.error("VideoError", "Video player had error " + error, null);
}
diff --git a/packages/video_player/video_player/example/integration_test/video_player_test.dart b/packages/video_player/video_player/example/integration_test/video_player_test.dart
index 7ef1cf6..9e273e0 100644
--- a/packages/video_player/video_player/example/integration_test/video_player_test.dart
+++ b/packages/video_player/video_player/example/integration_test/video_player_test.dart
@@ -2,11 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-
// TODO(amirh): Remove this once flutter_driver supports null safety.
// https://github.com/flutter/flutter/issues/71379
// @dart = 2.9
+import 'dart:async';
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:integration_test/integration_test.dart';
import 'package:flutter_test/flutter_test.dart';
@@ -35,9 +36,57 @@
});
testWidgets(
+ 'reports buffering status',
+ (WidgetTester tester) async {
+ VideoPlayerController networkController = VideoPlayerController.network(
+ 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
+ );
+ await networkController.initialize();
+ // Mute to allow playing without DOM interaction on Web.
+ // See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
+ await networkController.setVolume(0);
+ final Completer<void> started = Completer();
+ final Completer<void> ended = Completer();
+ bool startedBuffering = false;
+ bool endedBuffering = false;
+ networkController.addListener(() {
+ if (networkController.value.isBuffering && !startedBuffering) {
+ startedBuffering = true;
+ started.complete();
+ }
+ if (startedBuffering &&
+ !networkController.value.isBuffering &&
+ !endedBuffering) {
+ endedBuffering = true;
+ ended.complete();
+ }
+ });
+
+ await networkController.play();
+ await networkController.seekTo(const Duration(seconds: 5));
+ await tester.pumpAndSettle(_playDuration);
+ await networkController.pause();
+
+ expect(networkController.value.isPlaying, false);
+ expect(networkController.value.position,
+ (Duration position) => position > const Duration(seconds: 0));
+
+ await started;
+ expect(startedBuffering, true);
+
+ await ended;
+ expect(endedBuffering, true);
+ },
+ skip: !(kIsWeb || defaultTargetPlatform == TargetPlatform.android),
+ );
+
+ testWidgets(
'can be played',
(WidgetTester tester) async {
await _controller.initialize();
+ // Mute to allow playing without DOM interaction on Web.
+ // See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
+ await _controller.setVolume(0);
await _controller.play();
await tester.pumpAndSettle(_playDuration);
@@ -63,6 +112,9 @@
'can be paused',
(WidgetTester tester) async {
await _controller.initialize();
+ // Mute to allow playing without DOM interaction on Web.
+ // See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
+ await _controller.setVolume(0);
// Play for a second, then pause, and then wait a second.
await _controller.play();
@@ -109,6 +161,6 @@
await tester.pumpAndSettle();
expect(_controller.value.isPlaying, true);
- });
+ }, skip: kIsWeb); // Web does not support local assets.
});
}
diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml
index cfbc4c6..6e48332 100644
--- a/packages/video_player/video_player/pubspec.yaml
+++ b/packages/video_player/video_player/pubspec.yaml
@@ -4,7 +4,7 @@
# 0.10.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
-version: 2.0.0-nullsafety.3
+version: 2.0.0-nullsafety.4
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player
flutter:
diff --git a/packages/video_player/video_player_web/CHANGELOG.md b/packages/video_player/video_player_web/CHANGELOG.md
index 52c2042..2becf5b 100644
--- a/packages/video_player/video_player_web/CHANGELOG.md
+++ b/packages/video_player/video_player_web/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.0.0-nullsafety.2
+
+* Fixed an issue where `isBuffering` was not updating on Web.
+
## 2.0.0-nullsafety.1
* Bump Dart SDK to support null safety.
diff --git a/packages/video_player/video_player_web/lib/video_player_web.dart b/packages/video_player/video_player_web/lib/video_player_web.dart
index de8f6a7..9132a08 100644
--- a/packages/video_player/video_player_web/lib/video_player_web.dart
+++ b/packages/video_player/video_player_web/lib/video_player_web.dart
@@ -156,6 +156,17 @@
final int textureId;
late VideoElement videoElement;
bool isInitialized = false;
+ bool isBuffering = false;
+
+ void setBuffering(bool buffering) {
+ if (isBuffering != buffering) {
+ isBuffering = buffering;
+ eventController.add(VideoEvent(
+ eventType: isBuffering
+ ? VideoEventType.bufferingStart
+ : VideoEventType.bufferingEnd));
+ }
+ }
void initialize() {
videoElement = VideoElement()
@@ -176,10 +187,25 @@
isInitialized = true;
sendInitialized();
}
+ setBuffering(false);
+ });
+
+ videoElement.onCanPlayThrough.listen((dynamic _) {
+ setBuffering(false);
+ });
+
+ videoElement.onPlaying.listen((dynamic _) {
+ setBuffering(false);
+ });
+
+ videoElement.onWaiting.listen((dynamic _) {
+ setBuffering(true);
+ sendBufferingUpdate();
});
// The error event fires when some form of error occurs while attempting to load or perform the media.
videoElement.onError.listen((Event _) {
+ setBuffering(false);
// The Event itself (_) doesn't contain info about the actual error.
// We need to look at the HTMLMediaElement.error.
// See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error
@@ -192,6 +218,7 @@
});
videoElement.onEnded.listen((dynamic _) {
+ setBuffering(false);
eventController.add(VideoEvent(eventType: VideoEventType.completed));
});
}
diff --git a/packages/video_player/video_player_web/pubspec.yaml b/packages/video_player/video_player_web/pubspec.yaml
index dc1af16..9333ac0 100644
--- a/packages/video_player/video_player_web/pubspec.yaml
+++ b/packages/video_player/video_player_web/pubspec.yaml
@@ -4,7 +4,7 @@
# 0.1.y+z is compatible with 1.0.0, if you land a breaking change bump
# the version to 2.0.0.
# See more details: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0
-version: 2.0.0-nullsafety.1
+version: 2.0.0-nullsafety.2
flutter:
plugin: