Skip to content

Commit

Permalink
fix(video_player): buffering state events missing on Android & Web (f…
Browse files Browse the repository at this point in the history
  • Loading branch information
kmod-midori authored Dec 17, 2020
1 parent 05879a3 commit b2e9ca5
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 4 deletions.
4 changes: 4 additions & 0 deletions packages/video_player/video_player/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,21 @@ public void onCancel(Object o) {

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) {
Expand All @@ -184,10 +195,15 @@ public void onPlaybackStateChanged(final int playbackState) {
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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -34,10 +35,58 @@ void main() {
const Duration(seconds: 7, milliseconds: 540));
});

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);
Expand All @@ -63,6 +112,9 @@ void main() {
'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();
Expand Down Expand Up @@ -109,6 +161,6 @@ void main() {

await tester.pumpAndSettle();
expect(_controller.value.isPlaying, true);
});
}, skip: kIsWeb); // Web does not support local assets.
});
}
2 changes: 1 addition & 1 deletion packages/video_player/video_player/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Flutter plugin for displaying inline video with other Flutter
# 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:
Expand Down
4 changes: 4 additions & 0 deletions packages/video_player/video_player_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
27 changes: 27 additions & 0 deletions packages/video_player/video_player_web/lib/video_player_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ class _VideoPlayer {
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()
Expand All @@ -176,10 +187,25 @@ class _VideoPlayer {
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
Expand All @@ -192,6 +218,7 @@ class _VideoPlayer {
});

videoElement.onEnded.listen((dynamic _) {
setBuffering(false);
eventController.add(VideoEvent(eventType: VideoEventType.completed));
});
}
Expand Down
2 changes: 1 addition & 1 deletion packages/video_player/video_player_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/v
# 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:
Expand Down

0 comments on commit b2e9ca5

Please sign in to comment.