diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index 58fa0844bbe7..501651126f1b 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.3.0 + +* Adds `allowBackgroundPlayback` to `VideoPlayerOptions`. + ## 2.2.13 * Fixes persisting of hasError even after successful initialize. diff --git a/packages/video_player/video_player/example/pubspec.yaml b/packages/video_player/video_player/example/pubspec.yaml index eef6eb7ab63b..e5a18875a1c2 100644 --- a/packages/video_player/video_player/example/pubspec.yaml +++ b/packages/video_player/video_player/example/pubspec.yaml @@ -17,6 +17,11 @@ dependencies: # the parent directory to use the current plugin's version. path: ../ +dependency_overrides: + video_player_platform_interface: + path: + ../../video_player_platform_interface + dev_dependencies: flutter_test: sdk: flutter diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index 3d4e1c6aa599..e7b2e4deb5a4 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -285,7 +285,7 @@ class VideoPlayerController extends ValueNotifier { bool _isDisposed = false; Completer? _creatingCompleter; StreamSubscription? _eventSubscription; - late _VideoAppLifeCycleObserver _lifeCycleObserver; + _VideoAppLifeCycleObserver? _lifeCycleObserver; /// The id of a texture that hasn't been initialized. @visibleForTesting @@ -299,8 +299,12 @@ class VideoPlayerController extends ValueNotifier { /// Attempts to open the given [dataSource] and load metadata about the video. Future initialize() async { - _lifeCycleObserver = _VideoAppLifeCycleObserver(this); - _lifeCycleObserver.initialize(); + final allowBackgroundPlayback = + videoPlayerOptions?.allowBackgroundPlayback ?? false; + if (!allowBackgroundPlayback) { + _lifeCycleObserver = _VideoAppLifeCycleObserver(this); + } + _lifeCycleObserver?.initialize(); _creatingCompleter = Completer(); late DataSource dataSourceDescription; @@ -415,7 +419,7 @@ class VideoPlayerController extends ValueNotifier { await _eventSubscription?.cancel(); await _videoPlayerPlatform.dispose(_textureId); } - _lifeCycleObserver.dispose(); + _lifeCycleObserver?.dispose(); } _isDisposed = true; super.dispose(); diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index 98c9b950871b..db884297b611 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -3,7 +3,8 @@ description: Flutter plugin for displaying inline video with other Flutter widgets on Android, iOS, and web. repository: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.2.13 + +version: 2.3.0 environment: sdk: ">=2.14.0 <3.0.0" @@ -23,10 +24,17 @@ flutter: dependencies: flutter: sdk: flutter - video_player_platform_interface: ">=4.2.0 <6.0.0" + video_player_platform_interface: + path: + ../video_player_platform_interface video_player_web: ^2.0.0 html: ^0.15.0 +dependency_overrides: + video_player_platform_interface: + path: + ../video_player_platform_interface + dev_dependencies: flutter_test: sdk: flutter diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index 08eecb618f41..82e0005799d8 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -95,6 +95,22 @@ class _FakeClosedCaptionFile extends ClosedCaptionFile { } void main() { + void verifyAppLifeCycle( + VideoPlayerController controller, { + required bool isObserving, + }) { + final wasPlayingBeforePause = controller.value.isPlaying; + WidgetsBinding.instance! + .handleAppLifecycleStateChanged(AppLifecycleState.paused); + expect( + controller.value.isPlaying, + isObserving ? false : wasPlayingBeforePause, + ); + WidgetsBinding.instance! + .handleAppLifecycleStateChanged(AppLifecycleState.resumed); + expect(controller.value.isPlaying, wasPlayingBeforePause); + } + testWidgets('update texture', (WidgetTester tester) async { final FakeController controller = FakeController(); await tester.pumpWidget(VideoPlayer(controller)); @@ -189,6 +205,15 @@ void main() { }); group('initialize', () { + test('started app lifecycle observing', () async { + final VideoPlayerController controller = VideoPlayerController.network( + 'https://127.0.0.1', + ); + await controller.initialize(); + await controller.play(); + verifyAppLifeCycle(controller, isObserving: true); + }); + test('asset', () async { final VideoPlayerController controller = VideoPlayerController.asset( 'a.avi', @@ -810,6 +835,30 @@ void main() { }); }); + group('VideoPlayerOptions', () { + test('setMixWithOthers', () async { + final VideoPlayerController controller = VideoPlayerController.file( + File(''), + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true)); + await controller.initialize(); + expect(controller.videoPlayerOptions!.mixWithOthers, true); + }); + + [true, false].forEach((allowBackgroundPlayback) { + test('allowBackgroundPlayback is $allowBackgroundPlayback', () async { + final VideoPlayerController controller = VideoPlayerController.file( + File(''), + videoPlayerOptions: VideoPlayerOptions( + allowBackgroundPlayback: allowBackgroundPlayback, + ), + ); + await controller.initialize(); + await controller.play(); + verifyAppLifeCycle(controller, isObserving: !allowBackgroundPlayback); + }); + }); + }); + test('VideoProgressColors', () { const Color playedColor = Color.fromRGBO(0, 0, 255, 0.75); const Color bufferedColor = Color.fromRGBO(0, 255, 0, 0.5); @@ -824,14 +873,6 @@ void main() { expect(colors.bufferedColor, bufferedColor); expect(colors.backgroundColor, backgroundColor); }); - - test('setMixWithOthers', () async { - final VideoPlayerController controller = VideoPlayerController.file( - File(''), - videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true)); - await controller.initialize(); - expect(controller.videoPlayerOptions!.mixWithOthers, true); - }); } class FakeVideoPlayerPlatform extends VideoPlayerPlatform { diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index bf51960bcb40..cf2ffda1b2fb 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.0 + +* Adds `allowBackgroundPlayback` to `VideoPlayerOptions`. + ## 5.0.1 * Update to use the `verify` method introduced in platform_plugin_interface 2.1.0. diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 451537ad1f12..e87185ac481b 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -329,6 +329,10 @@ class DurationRange { /// [VideoPlayerOptions] can be optionally used to set additional player settings class VideoPlayerOptions { + /// Set this to true to keep playing video in background, when app goes in background. + /// The default value is false. + final bool allowBackgroundPlayback; + /// Set this to true to mix the video players audio with other audio sources. /// The default value is false /// @@ -337,5 +341,8 @@ class VideoPlayerOptions { final bool mixWithOthers; /// set additional optional player settings - VideoPlayerOptions({this.mixWithOthers = false}); + VideoPlayerOptions({ + this.mixWithOthers = false, + this.allowBackgroundPlayback = false, + }); } diff --git a/packages/video_player/video_player_platform_interface/pubspec.yaml b/packages/video_player/video_player_platform_interface/pubspec.yaml index 986ca913be62..9fedc5b09756 100644 --- a/packages/video_player/video_player_platform_interface/pubspec.yaml +++ b/packages/video_player/video_player_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/plugins/tree/master/packages/video_player issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 5.0.1 +version: 5.1.0 environment: sdk: ">=2.12.0 <3.0.0"