[video_player] Add a `Uri`-typed factory method (#3513)

This PR improves VideoPlayerController network constructor with the datasource type. The solution follows the comments on the issue [#121927](https://github.com/flutter/flutter/issues/121927).

Fixes [#121927](https://github.com/flutter/flutter/issues/121927)
diff --git a/packages/camera/camera/example/lib/main.dart b/packages/camera/camera/example/lib/main.dart
index 6dad1eb..d6bf55f 100644
--- a/packages/camera/camera/example/lib/main.dart
+++ b/packages/camera/camera/example/lib/main.dart
@@ -994,6 +994,10 @@
     }
 
     final VideoPlayerController vController = kIsWeb
+        // TODO(gabrielokura): remove the ignore once the following line can migrate to
+        // use VideoPlayerController.networkUrl after the issue is resolved.
+        // https://github.com/flutter/flutter/issues/121927
+        // ignore: deprecated_member_use
         ? VideoPlayerController.network(videoFile!.path)
         : VideoPlayerController.file(File(videoFile!.path));
 
diff --git a/packages/camera/camera_android/example/lib/main.dart b/packages/camera/camera_android/example/lib/main.dart
index 5162d3a..56297bc 100644
--- a/packages/camera/camera_android/example/lib/main.dart
+++ b/packages/camera/camera_android/example/lib/main.dart
@@ -1002,6 +1002,10 @@
     }
 
     final VideoPlayerController vController = kIsWeb
+        // TODO(gabrielokura): remove the ignore once the following line can migrate to
+        // use VideoPlayerController.networkUrl after the issue is resolved.
+        // https://github.com/flutter/flutter/issues/121927
+        // ignore: deprecated_member_use
         ? VideoPlayerController.network(videoFile!.path)
         : VideoPlayerController.file(File(videoFile!.path));
 
diff --git a/packages/camera/camera_android_camerax/example/lib/main.dart b/packages/camera/camera_android_camerax/example/lib/main.dart
index 1e051d4..32768fa 100644
--- a/packages/camera/camera_android_camerax/example/lib/main.dart
+++ b/packages/camera/camera_android_camerax/example/lib/main.dart
@@ -979,6 +979,10 @@
     }
 
     final VideoPlayerController vController = kIsWeb
+        // TODO(gabrielokura): remove the ignore once the following line can migrate to
+        // use VideoPlayerController.networkUrl after the issue is resolved.
+        // https://github.com/flutter/flutter/issues/121927
+        // ignore: deprecated_member_use
         ? VideoPlayerController.network(videoFile!.path)
         : VideoPlayerController.file(File(videoFile!.path));
 
diff --git a/packages/camera/camera_avfoundation/example/lib/main.dart b/packages/camera/camera_avfoundation/example/lib/main.dart
index 5162d3a..56297bc 100644
--- a/packages/camera/camera_avfoundation/example/lib/main.dart
+++ b/packages/camera/camera_avfoundation/example/lib/main.dart
@@ -1002,6 +1002,10 @@
     }
 
     final VideoPlayerController vController = kIsWeb
+        // TODO(gabrielokura): remove the ignore once the following line can migrate to
+        // use VideoPlayerController.networkUrl after the issue is resolved.
+        // https://github.com/flutter/flutter/issues/121927
+        // ignore: deprecated_member_use
         ? VideoPlayerController.network(videoFile!.path)
         : VideoPlayerController.file(File(videoFile!.path));
 
diff --git a/packages/image_picker/image_picker/example/lib/main.dart b/packages/image_picker/image_picker/example/lib/main.dart
index b1431c5..3cf07af 100755
--- a/packages/image_picker/image_picker/example/lib/main.dart
+++ b/packages/image_picker/image_picker/example/lib/main.dart
@@ -62,6 +62,10 @@
       await _disposeVideoController();
       late VideoPlayerController controller;
       if (kIsWeb) {
+        // TODO(gabrielokura): remove the ignore once the following line can migrate to
+        // use VideoPlayerController.networkUrl after the issue is resolved.
+        // https://github.com/flutter/flutter/issues/121927
+        // ignore: deprecated_member_use
         controller = VideoPlayerController.network(file.path);
       } else {
         controller = VideoPlayerController.file(File(file.path));
diff --git a/packages/video_player/video_player/AUTHORS b/packages/video_player/video_player/AUTHORS
index e57e00b..867027d 100644
--- a/packages/video_player/video_player/AUTHORS
+++ b/packages/video_player/video_player/AUTHORS
@@ -65,4 +65,6 @@
 Alex Li <google@alexv525.com>
 Rahul Raj <64.rahulraj@gmail.com>
 Koen Van Looveren <vanlooverenkoen.dev@gmail.com>
+Gabriel Motelevicz Okura <gabriellevicz@gmail.com>
+Idowu Tomiwa <tommydprogrammer@gmail.com>
 Márton Matuz <matuzmarci@gmail.com>
diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md
index 7f24a73..9754a6b 100644
--- a/packages/video_player/video_player/CHANGELOG.md
+++ b/packages/video_player/video_player/CHANGELOG.md
@@ -1,7 +1,9 @@
-## NEXT
+## 2.7.0
 
+* Adds an `Uri` typed factory method `VideoPlayerController.networkUrl` to avoid common mistakes with `String` URIs. The method
+receives an`Uri` instead of a `String` url.
+* Deprecates `VideoPlayerController.network` factory method.
 * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18.
-
 ## 2.6.1
 
 * Synchronizes `VideoPlayerValue.isPlaying` with underlying video player.
diff --git a/packages/video_player/video_player/README.md b/packages/video_player/video_player/README.md
index 5e4d567..cfe164c 100644
--- a/packages/video_player/video_player/README.md
+++ b/packages/video_player/video_player/README.md
@@ -73,8 +73,8 @@
   @override
   void initState() {
     super.initState();
-    _controller = VideoPlayerController.network(
-        'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4')
+    _controller = VideoPlayerController.networkUrl(Uri.parse(
+        'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'))
       ..initialize().then((_) {
         // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
         setState(() {});
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 5f48d08..6ca4de9 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
@@ -57,8 +57,9 @@
       'live stream duration != 0',
       (WidgetTester tester) async {
         final VideoPlayerController networkController =
-            VideoPlayerController.network(
-          'https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8',
+            VideoPlayerController.networkUrl(
+          Uri.parse(
+              'https://flutter.github.io/assets-for-api-docs/assets/videos/hls/bee.m3u8'),
         );
         await networkController.initialize();
 
@@ -230,8 +231,8 @@
 
   group('network videos', () {
     setUp(() {
-      controller = VideoPlayerController.network(
-          getUrlForAssetAsNetworkSource(_videoAssetKey));
+      controller = VideoPlayerController.networkUrl(
+          Uri.parse(getUrlForAssetAsNetworkSource(_videoAssetKey)));
     });
 
     testWidgets(
diff --git a/packages/video_player/video_player/example/lib/basic.dart b/packages/video_player/video_player/example/lib/basic.dart
index 60191b5..af42187 100644
--- a/packages/video_player/video_player/example/lib/basic.dart
+++ b/packages/video_player/video_player/example/lib/basic.dart
@@ -27,8 +27,8 @@
   @override
   void initState() {
     super.initState();
-    _controller = VideoPlayerController.network(
-        'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4')
+    _controller = VideoPlayerController.networkUrl(Uri.parse(
+        'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'))
       ..initialize().then((_) {
         // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
         setState(() {});
diff --git a/packages/video_player/video_player/example/lib/main.dart b/packages/video_player/video_player/example/lib/main.dart
index cda8a39..2691fc2 100644
--- a/packages/video_player/video_player/example/lib/main.dart
+++ b/packages/video_player/video_player/example/lib/main.dart
@@ -217,8 +217,9 @@
   @override
   void initState() {
     super.initState();
-    _controller = VideoPlayerController.network(
-      'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
+    _controller = VideoPlayerController.networkUrl(
+      Uri.parse(
+          'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'),
       closedCaptionFile: _loadCaptions(),
       videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
     );
diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart
index b2105e9..b0e5b7b 100644
--- a/packages/video_player/video_player/lib/video_player.dart
+++ b/packages/video_player/video_player/lib/video_player.dart
@@ -262,15 +262,16 @@
         httpHeaders = const <String, String>{},
         super(const VideoPlayerValue(duration: Duration.zero));
 
-  /// Constructs a [VideoPlayerController] playing a video from obtained from
-  /// the network.
+  /// Constructs a [VideoPlayerController] playing a network video.
   ///
-  /// The URI for the video is given by the [dataSource] argument and must not be
-  /// null.
+  /// The URI for the video is given by the [dataSource] argument.
+  ///
   /// **Android only**: The [formatHint] option allows the caller to override
   /// the video format detection code.
-  /// [httpHeaders] option allows to specify HTTP headers.
+  ///
+  /// [httpHeaders] option allows to specify HTTP headers
   /// for the request to the [dataSource].
+  @Deprecated('Use VideoPlayerController.networkUrl instead')
   VideoPlayerController.network(
     this.dataSource, {
     this.formatHint,
@@ -282,6 +283,27 @@
         package = null,
         super(const VideoPlayerValue(duration: Duration.zero));
 
+  /// Constructs a [VideoPlayerController] playing a network video.
+  ///
+  /// The URI for the video is given by the [dataSource] argument.
+  ///
+  /// **Android only**: The [formatHint] option allows the caller to override
+  /// the video format detection code.
+  ///
+  /// [httpHeaders] option allows to specify HTTP headers
+  /// for the request to the [dataSource].
+  VideoPlayerController.networkUrl(
+    Uri url, {
+    this.formatHint,
+    Future<ClosedCaptionFile>? closedCaptionFile,
+    this.videoPlayerOptions,
+    this.httpHeaders = const <String, String>{},
+  })  : _closedCaptionFileFuture = closedCaptionFile,
+        dataSource = url.toString(),
+        dataSourceType = DataSourceType.network,
+        package = null,
+        super(const VideoPlayerValue(duration: Duration.zero));
+
   /// Constructs a [VideoPlayerController] playing a video from a file.
   ///
   /// This will load the file from a file:// URI constructed from [file]'s path.
diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml
index f33a272..81095f6 100644
--- a/packages/video_player/video_player/pubspec.yaml
+++ b/packages/video_player/video_player/pubspec.yaml
@@ -3,7 +3,7 @@
   widgets on Android, iOS, and web.
 repository: https://github.com/flutter/packages/tree/main/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.6.1
+version: 2.7.0
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
diff --git a/packages/video_player/video_player/test/video_player_initialization_test.dart b/packages/video_player/video_player/test/video_player_initialization_test.dart
index af0886f..38cf71f 100644
--- a/packages/video_player/video_player/test/video_player_initialization_test.dart
+++ b/packages/video_player/video_player/test/video_player_initialization_test.dart
@@ -17,8 +17,8 @@
         FakeVideoPlayerPlatform();
     VideoPlayerPlatform.instance = fakeVideoPlayerPlatform;
 
-    final VideoPlayerController controller = VideoPlayerController.network(
-      'https://127.0.0.1',
+    final VideoPlayerController controller = VideoPlayerController.networkUrl(
+      Uri.parse('https://127.0.0.1'),
     );
     await controller.initialize();
     expect(fakeVideoPlayerPlatform.calls.first, 'init');
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 bef0298..040cd5c 100644
--- a/packages/video_player/video_player/test/video_player_test.dart
+++ b/packages/video_player/video_player/test/video_player_test.dart
@@ -14,6 +14,9 @@
 import 'package:video_player/video_player.dart';
 import 'package:video_player_platform_interface/video_player_platform_interface.dart';
 
+const String _localhost = 'https://127.0.0.1';
+final Uri _localhostUri = Uri.parse(_localhost);
+
 class FakeController extends ValueNotifier<VideoPlayerValue>
     implements VideoPlayerController {
   FakeController() : super(const VideoPlayerValue(duration: Duration.zero));
@@ -243,27 +246,7 @@
   });
 
   group('VideoPlayerController', () {
-    group('initialize', () {
-      test('started app lifecycle observing', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
-        await controller.initialize();
-        await controller.play();
-        verifyPlayStateRespondsToLifecycle(controller,
-            shouldPlayInBackground: false);
-      });
-
-      test('asset', () async {
-        final VideoPlayerController controller = VideoPlayerController.asset(
-          'a.avi',
-        );
-        await controller.initialize();
-
-        expect(fakeVideoPlayerPlatform.dataSources[0].asset, 'a.avi');
-        expect(fakeVideoPlayerPlatform.dataSources[0].package, null);
-      });
-
+    group('legacy initialize', () {
       test('network', () async {
         final VideoPlayerController controller = VideoPlayerController.network(
           'https://127.0.0.1',
@@ -325,11 +308,99 @@
           <String, String>{'Authorization': 'Bearer token'},
         );
       });
-
-      test('init errors', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'http://testing.com/invalid_url',
+    });
+    group('initialize', () {
+      test('started app lifecycle observing', () async {
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          Uri.parse('https://127.0.0.1'),
         );
+        await controller.initialize();
+        await controller.play();
+        verifyPlayStateRespondsToLifecycle(controller,
+            shouldPlayInBackground: false);
+      });
+
+      test('asset', () async {
+        final VideoPlayerController controller = VideoPlayerController.asset(
+          'a.avi',
+        );
+        await controller.initialize();
+
+        expect(fakeVideoPlayerPlatform.dataSources[0].asset, 'a.avi');
+        expect(fakeVideoPlayerPlatform.dataSources[0].package, null);
+      });
+
+      test('network url', () async {
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(Uri.parse('https://127.0.0.1'));
+        await controller.initialize();
+
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].uri,
+          'https://127.0.0.1',
+        );
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].formatHint,
+          null,
+        );
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].httpHeaders,
+          <String, String>{},
+        );
+      });
+
+      test('network url with hint', () async {
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          Uri.parse('https://127.0.0.1'),
+          formatHint: VideoFormat.dash,
+        );
+        await controller.initialize();
+
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].uri,
+          'https://127.0.0.1',
+        );
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].formatHint,
+          VideoFormat.dash,
+        );
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].httpHeaders,
+          <String, String>{},
+        );
+      });
+
+      test('network url with some headers', () async {
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          Uri.parse('https://127.0.0.1'),
+          httpHeaders: <String, String>{'Authorization': 'Bearer token'},
+        );
+        await controller.initialize();
+
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].uri,
+          'https://127.0.0.1',
+        );
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].formatHint,
+          null,
+        );
+        expect(
+          fakeVideoPlayerPlatform.dataSources[0].httpHeaders,
+          <String, String>{'Authorization': 'Bearer token'},
+        );
+      });
+
+      test(
+          'when controller is initialized with invalid url it should throw VideoError',
+          () async {
+        final Uri invalidUrl = Uri.parse('http://testing.com/invalid_url');
+
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(invalidUrl);
 
         late Object error;
         fakeVideoPlayerPlatform.forceInitError = true;
@@ -387,6 +458,20 @@
         await controller.initialize();
         expect(controller.value.hasError, equals(false));
       });
+
+      test(
+          'given controller with error when initialization succeeds it should clear error',
+          () async {
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
+        fakeVideoPlayerPlatform.forceInitError = true;
+        await controller.initialize().catchError((dynamic e) {});
+        expect(controller.value.hasError, equals(true));
+        fakeVideoPlayerPlatform.forceInitError = false;
+        await controller.initialize();
+        expect(controller.value.hasError, equals(false));
+      });
     });
 
     test('contentUri', () async {
@@ -398,9 +483,9 @@
     });
 
     test('dispose', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(_localhostUri);
+
       expect(
           controller.textureId, VideoPlayerController.kUninitializedTextureId);
       expect(await controller.position, Duration.zero);
@@ -413,9 +498,8 @@
     });
 
     test('calling dispose() on disposed controller does not throw', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(_localhostUri);
 
       await controller.initialize();
       await controller.dispose();
@@ -424,9 +508,9 @@
     });
 
     test('play', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(Uri.parse('https://127.0.0.1'));
+
       await controller.initialize();
       expect(controller.value.isPlaying, isFalse);
       await controller.play();
@@ -443,9 +527,9 @@
     });
 
     test('play before initialized does not call platform', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(_localhostUri);
+
       expect(controller.value.isInitialized, isFalse);
 
       await controller.play();
@@ -454,9 +538,9 @@
     });
 
     test('play restarts from beginning if video is at end', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(_localhostUri);
+
       await controller.initialize();
       const Duration nonzeroDuration = Duration(milliseconds: 100);
       controller.value = controller.value.copyWith(duration: nonzeroDuration);
@@ -471,9 +555,9 @@
     });
 
     test('setLooping', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(_localhostUri);
+
       await controller.initialize();
       expect(controller.value.isLooping, isFalse);
       await controller.setLooping(true);
@@ -482,9 +566,9 @@
     });
 
     test('pause', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
-      );
+      final VideoPlayerController controller =
+          VideoPlayerController.networkUrl(_localhostUri);
+
       await controller.initialize();
       await controller.play();
       expect(controller.value.isPlaying, isTrue);
@@ -497,9 +581,9 @@
 
     group('seekTo', () {
       test('works', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         expect(await controller.position, Duration.zero);
 
@@ -509,9 +593,9 @@
       });
 
       test('before initialized does not call platform', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         expect(controller.value.isInitialized, isFalse);
 
         await controller.seekTo(const Duration(milliseconds: 500));
@@ -520,9 +604,9 @@
       });
 
       test('clamps values that are too high or low', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         expect(await controller.position, Duration.zero);
 
@@ -536,9 +620,9 @@
 
     group('setVolume', () {
       test('works', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         expect(controller.value.volume, 1.0);
 
@@ -549,9 +633,9 @@
       });
 
       test('clamps values that are too high or low', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         expect(controller.value.volume, 1.0);
 
@@ -565,9 +649,9 @@
 
     group('setPlaybackSpeed', () {
       test('works', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         expect(controller.value.playbackSpeed, 1.0);
 
@@ -578,9 +662,9 @@
       });
 
       test('rejects negative values', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         expect(controller.value.playbackSpeed, 1.0);
 
@@ -591,9 +675,9 @@
     group('scrubbing', () {
       testWidgets('restarts on release if already playing',
           (WidgetTester tester) async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         final VideoProgressIndicator progressWidget =
             VideoProgressIndicator(controller, allowScrubbing: true);
@@ -618,9 +702,9 @@
 
       testWidgets('does not restart when dragging to end',
           (WidgetTester tester) async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-        );
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(_localhostUri);
+
         await controller.initialize();
         final VideoProgressIndicator progressWidget =
             VideoProgressIndicator(controller, allowScrubbing: true);
@@ -644,8 +728,9 @@
 
     group('caption', () {
       test('works when seeking', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
           closedCaptionFile: _loadClosedCaption(),
         );
 
@@ -676,8 +761,9 @@
       });
 
       test('works when seeking with captionOffset positive', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
           closedCaptionFile: _loadClosedCaption(),
         );
 
@@ -712,8 +798,9 @@
       });
 
       test('works when seeking with captionOffset negative', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
           closedCaptionFile: _loadClosedCaption(),
         );
 
@@ -751,8 +838,9 @@
       });
 
       test('setClosedCaptionFile loads caption file', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
         );
 
         await controller.initialize();
@@ -766,8 +854,9 @@
       });
 
       test('setClosedCaptionFile removes/changes caption file', () async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
           closedCaptionFile: _loadClosedCaption(),
         );
 
@@ -784,9 +873,11 @@
 
     group('Platform callbacks', () {
       testWidgets('playing completed', (WidgetTester tester) async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
         );
+
         await controller.initialize();
         const Duration nonzeroDuration = Duration(milliseconds: 100);
         controller.value = controller.value.copyWith(duration: nonzeroDuration);
@@ -806,7 +897,7 @@
 
       testWidgets('playback status', (WidgetTester tester) async {
         final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+          'https://.0.0.1',
         );
         await controller.initialize();
         expect(controller.value.isPlaying, isFalse);
@@ -829,9 +920,11 @@
       });
 
       testWidgets('buffering status', (WidgetTester tester) async {
-        final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
+        final VideoPlayerController controller =
+            VideoPlayerController.networkUrl(
+          _localhostUri,
         );
+
         await controller.initialize();
         expect(controller.value.isBuffering, false);
         expect(controller.value.buffered, isEmpty);
@@ -1057,20 +1150,23 @@
 
   group('VideoPlayerOptions', () {
     test('setMixWithOthers', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-          'https://127.0.0.1',
-          videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true));
+      final VideoPlayerController controller = VideoPlayerController.networkUrl(
+        _localhostUri,
+        videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
+      );
+
       await controller.initialize();
       expect(controller.videoPlayerOptions!.mixWithOthers, true);
     });
 
     test('true allowBackgroundPlayback continues playback', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
+      final VideoPlayerController controller = VideoPlayerController.networkUrl(
+        _localhostUri,
         videoPlayerOptions: VideoPlayerOptions(
           allowBackgroundPlayback: true,
         ),
       );
+
       await controller.initialize();
       await controller.play();
       verifyPlayStateRespondsToLifecycle(
@@ -1080,10 +1176,11 @@
     });
 
     test('false allowBackgroundPlayback pauses playback', () async {
-      final VideoPlayerController controller = VideoPlayerController.network(
-        'https://127.0.0.1',
+      final VideoPlayerController controller = VideoPlayerController.networkUrl(
+        _localhostUri,
         videoPlayerOptions: VideoPlayerOptions(),
       );
+
       await controller.initialize();
       await controller.play();
       verifyPlayStateRespondsToLifecycle(