2
2
// Use of this source code is governed by a BSD-style license that can be
3
3
// found in the LICENSE file.
4
4
5
- import 'dart:async' ;
6
5
import 'dart:io' ;
7
6
import 'dart:typed_data' ;
8
7
@@ -11,16 +10,9 @@ import 'package:flutter_test/flutter_test.dart';
11
10
import 'package:integration_test/integration_test.dart' ;
12
11
import 'package:path_provider/path_provider.dart' ;
13
12
import 'package:video_player_android/video_player_android.dart' ;
14
- // TODO(stuartmorgan): Remove the use of MiniController in tests, as that is
15
- // testing test code; tests should instead be written directly against the
16
- // platform interface. (These tests were copied from the app-facing package
17
- // during federation and minimally modified, which is why they currently use the
18
- // controller.)
19
- import 'package:video_player_example/mini_controller.dart' ;
20
13
import 'package:video_player_platform_interface/video_player_platform_interface.dart' ;
21
14
22
15
const Duration _playDuration = Duration (seconds: 1 );
23
-
24
16
const String _videoAssetKey = 'assets/Butterfly-209.mp4' ;
25
17
26
18
// Returns the URL to load an asset from this example app as a network source.
@@ -38,132 +30,139 @@ String getUrlForAssetAsNetworkSource(String assetKey) {
38
30
39
31
void main () {
40
32
IntegrationTestWidgetsFlutterBinding .ensureInitialized ();
33
+ late AndroidVideoPlayer player;
34
+
35
+ setUp (() async {
36
+ player = AndroidVideoPlayer ();
37
+ await player.init ();
38
+ });
41
39
42
- late MiniController controller;
43
- tearDown (() async => controller.dispose ());
40
+ testWidgets ('registers expected implementation' , (_) async {
41
+ AndroidVideoPlayer .registerWith ();
42
+ expect (VideoPlayerPlatform .instance, isA <AndroidVideoPlayer >());
43
+ });
44
+
45
+ testWidgets ('initializes at the start' , (_) async {
46
+ final int textureId = (await player.create (DataSource (
47
+ sourceType: DataSourceType .asset,
48
+ asset: _videoAssetKey,
49
+ )))! ;
44
50
45
- group ( 'asset videos' , () {
46
- setUp (() {
47
- controller = MiniController . asset (_videoAssetKey);
48
- } );
51
+ expect (
52
+ await _getDuration (player, textureId),
53
+ const Duration (seconds : 7 , milliseconds : 540 ),
54
+ );
49
55
50
- testWidgets ('registers expected implementation' ,
51
- (WidgetTester tester) async {
52
- AndroidVideoPlayer .registerWith ();
53
- expect (VideoPlayerPlatform .instance, isA <AndroidVideoPlayer >());
54
- });
56
+ await player.dispose (textureId);
57
+ });
55
58
56
- testWidgets ('can be initialized' , (WidgetTester tester) async {
57
- await controller.initialize ();
59
+ testWidgets ('can be played' , (WidgetTester tester) async {
60
+ final int textureId = (await player.create (DataSource (
61
+ sourceType: DataSourceType .asset,
62
+ asset: _videoAssetKey,
63
+ )))! ;
58
64
59
- expect (controller.value.isInitialized, true );
60
- expect (await controller.position, Duration .zero);
61
- expect (controller.value.duration,
62
- const Duration (seconds: 7 , milliseconds: 540 ));
63
- });
65
+ await player.play (textureId);
66
+ await tester.pumpAndSettle (_playDuration);
64
67
65
- testWidgets ('can be played' , (WidgetTester tester) async {
66
- await controller.initialize ();
68
+ expect (await player.getPosition (textureId), greaterThan (Duration .zero));
69
+ await player.dispose (textureId);
70
+ });
67
71
68
- await controller.play ();
69
- await tester.pumpAndSettle (_playDuration);
72
+ testWidgets ('can seek' , (WidgetTester tester) async {
73
+ final int textureId = (await player.create (DataSource (
74
+ sourceType: DataSourceType .asset,
75
+ asset: _videoAssetKey,
76
+ )))! ;
70
77
71
- expect ( await controller.position, greaterThan ( Duration .zero ));
72
- } );
78
+ await player. seekTo (textureId, const Duration (seconds : 3 ));
79
+ await tester. pumpAndSettle (_playDuration );
73
80
74
- testWidgets ('can seek' , (WidgetTester tester) async {
75
- await controller.initialize ();
81
+ expect (
82
+ await player.getPosition (textureId),
83
+ greaterThanOrEqualTo (const Duration (seconds: 3 )),
84
+ );
85
+ await player.dispose (textureId);
86
+ });
76
87
77
- await controller.seekTo (const Duration (seconds: 3 ));
88
+ testWidgets ('can pause' , (WidgetTester tester) async {
89
+ final int textureId = (await player.create (DataSource (
90
+ sourceType: DataSourceType .asset,
91
+ asset: _videoAssetKey,
92
+ )))! ;
78
93
79
- expect ( await controller.position, const Duration (seconds : 3 ) );
80
- } );
94
+ await player. play (textureId );
95
+ await tester. pumpAndSettle (_playDuration );
81
96
82
- testWidgets ('can be paused' , (WidgetTester tester) async {
83
- await controller.initialize ();
97
+ await player.pause (textureId);
98
+ final Duration pausedDuration = await player.getPosition (textureId);
99
+ await tester.pumpAndSettle (_playDuration);
84
100
85
- // Play for a second, then pause, and then wait a second.
86
- await controller.play ();
87
- await tester.pumpAndSettle (_playDuration);
88
- await controller.pause ();
89
- await tester.pumpAndSettle (_playDuration);
90
- final Duration pausedPosition = (await controller.position)! ;
91
- await tester.pumpAndSettle (_playDuration);
101
+ expect (await player.getPosition (textureId), pausedDuration);
102
+ await player.dispose (textureId);
103
+ });
92
104
93
- // Verify that we stopped playing after the pause.
94
- expect (await controller.position, pausedPosition);
95
- });
105
+ testWidgets ('can play a video from a file' , (WidgetTester tester) async {
106
+ final Directory directory = await getTemporaryDirectory ();
107
+ final File file = File ('${directory .path }/video.mp4' );
108
+ await file.writeAsBytes (
109
+ Uint8List .fromList (
110
+ (await rootBundle.load (_videoAssetKey)).buffer.asUint8List (),
111
+ ),
112
+ );
113
+
114
+ final int textureId = (await player.create (DataSource (
115
+ sourceType: DataSourceType .file,
116
+ uri: file.path,
117
+ )))! ;
118
+
119
+ await player.play (textureId);
120
+ await tester.pumpAndSettle (_playDuration);
121
+
122
+ expect (await player.getPosition (textureId), greaterThan (Duration .zero));
123
+ await directory.delete (recursive: true );
124
+ await player.dispose (textureId);
96
125
});
97
126
98
- group ( 'file-based videos ' , () {
99
- setUp (() async {
100
- // Load the data from the asset.
101
- final String tempDir = ( await getTemporaryDirectory ()).path;
102
- final ByteData bytes = await rootBundle. load (_videoAssetKey) ;
127
+ testWidgets ( 'can play a video from network ' , (WidgetTester tester) async {
128
+ final int textureId = ( await player. create ( DataSource (
129
+ sourceType : DataSourceType .network,
130
+ uri : getUrlForAssetAsNetworkSource (_videoAssetKey),
131
+ ))) ! ;
103
132
104
- // Write it to a file to use as a source.
105
- final String filename = _videoAssetKey. split ( '/' ).last ;
106
- final File file = File ( '$ tempDir /$ filename ' );
107
- await file. writeAsBytes (bytes.buffer. asInt8List () );
133
+ await player. play (textureId);
134
+ await player. seekTo (textureId, const Duration (seconds : 5 )) ;
135
+ await tester. pumpAndSettle (_playDuration );
136
+ await player. pause (textureId );
108
137
109
- controller = MiniController .file (file);
110
- });
138
+ expect (await player.getPosition (textureId), greaterThan (Duration .zero));
111
139
112
- testWidgets ( 'test video player using static file() method as constructor' ,
113
- ( WidgetTester tester) async {
114
- await controller. initialize ( );
140
+ final DurationRange range = await _getBufferingRange (player, textureId);
141
+ expect (range.start, Duration .zero);
142
+ expect (range.end, greaterThan ( Duration .zero) );
115
143
116
- await controller.play ();
117
- await tester.pumpAndSettle (_playDuration);
144
+ await player.dispose (textureId);
145
+ });
146
+ }
118
147
119
- expect (await controller.position, greaterThan (Duration .zero));
120
- });
148
+ Future <Duration > _getDuration (
149
+ AndroidVideoPlayer player,
150
+ int textureId,
151
+ ) {
152
+ return player.videoEventsFor (textureId).firstWhere ((VideoEvent event) {
153
+ return event.eventType == VideoEventType .initialized;
154
+ }).then ((VideoEvent event) {
155
+ return event.duration! ;
121
156
});
157
+ }
122
158
123
- group ('network videos' , () {
124
- setUp (() {
125
- final String videoUrl = getUrlForAssetAsNetworkSource (_videoAssetKey);
126
- controller = MiniController .network (videoUrl);
127
- });
128
-
129
- testWidgets ('reports buffering status' , (WidgetTester tester) async {
130
- await controller.initialize ();
131
-
132
- final Completer <void > started = Completer <void >();
133
- final Completer <void > ended = Completer <void >();
134
- controller.addListener (() {
135
- if (! started.isCompleted && controller.value.isBuffering) {
136
- started.complete ();
137
- }
138
- if (started.isCompleted &&
139
- ! controller.value.isBuffering &&
140
- ! ended.isCompleted) {
141
- ended.complete ();
142
- }
143
- });
144
-
145
- await controller.play ();
146
- await controller.seekTo (const Duration (seconds: 5 ));
147
- await tester.pumpAndSettle (_playDuration);
148
- await controller.pause ();
149
-
150
- expect (await controller.position, greaterThan (Duration .zero));
151
-
152
- await expectLater (started.future, completes);
153
- await expectLater (ended.future, completes);
154
- });
155
-
156
- testWidgets ('live stream duration != 0' , (WidgetTester tester) async {
157
- final MiniController livestreamController = MiniController .network (
158
- 'https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8' ,
159
- );
160
- await livestreamController.initialize ();
161
-
162
- expect (livestreamController.value.isInitialized, true );
163
- // Live streams should have either a positive duration or C.TIME_UNSET if the duration is unknown
164
- // See https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#getDuration--
165
- expect (livestreamController.value.duration,
166
- (Duration duration) => duration != Duration .zero);
167
- });
159
+ Future <DurationRange > _getBufferingRange (
160
+ AndroidVideoPlayer player,
161
+ int textureId,
162
+ ) {
163
+ return player.videoEventsFor (textureId).firstWhere ((VideoEvent event) {
164
+ return event.eventType == VideoEventType .bufferingUpdate;
165
+ }).then ((VideoEvent event) {
166
+ return event.buffered! .first;
168
167
});
169
168
}
0 commit comments