[url_launcher] Error handling when URL cannot be parsed with Uri.parse (#4365)

diff --git a/packages/url_launcher/url_launcher/CHANGELOG.md b/packages/url_launcher/url_launcher/CHANGELOG.md
index 4b52a8d..fff325e 100644
--- a/packages/url_launcher/url_launcher/CHANGELOG.md
+++ b/packages/url_launcher/url_launcher/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 6.0.12
+
+* Fixed an error where 'launch' method of url_launcher would cause an error if the provided URL was not valid by RFC 3986.
+
 ## 6.0.11
 
 * Update minimum Flutter SDK to 2.5 and iOS deployment target to 9.0.
diff --git a/packages/url_launcher/url_launcher/lib/url_launcher.dart b/packages/url_launcher/url_launcher/lib/url_launcher.dart
index 239e3c4..300f96f 100644
--- a/packages/url_launcher/url_launcher/lib/url_launcher.dart
+++ b/packages/url_launcher/url_launcher/lib/url_launcher.dart
@@ -71,8 +71,10 @@
   Brightness? statusBarBrightness,
   String? webOnlyWindowName,
 }) async {
-  final Uri url = Uri.parse(urlString.trimLeft());
-  final bool isWebURL = url.scheme == 'http' || url.scheme == 'https';
+  final Uri? url = Uri.tryParse(urlString.trimLeft());
+  final bool isWebURL =
+      url != null && (url.scheme == 'http' || url.scheme == 'https');
+
   if ((forceSafariVC == true || forceWebView == true) && !isWebURL) {
     throw PlatformException(
         code: 'NOT_A_WEB_SCHEME',
diff --git a/packages/url_launcher/url_launcher/pubspec.yaml b/packages/url_launcher/url_launcher/pubspec.yaml
index c90d2fe..8edb9e2 100644
--- a/packages/url_launcher/url_launcher/pubspec.yaml
+++ b/packages/url_launcher/url_launcher/pubspec.yaml
@@ -3,7 +3,7 @@
   web, phone, SMS, and email schemes.
 repository: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
-version: 6.0.11
+version: 6.0.12
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/url_launcher/url_launcher/test/url_launcher_test.dart b/packages/url_launcher/url_launcher/test/url_launcher_test.dart
index 04f727a..a038746 100644
--- a/packages/url_launcher/url_launcher/test/url_launcher_test.dart
+++ b/packages/url_launcher/url_launcher/test/url_launcher_test.dart
@@ -281,6 +281,42 @@
       await launchResult;
       expect(binding.renderView.automaticSystemUiAdjustment, true);
     });
+
+    test('open non-parseable url', () async {
+      mock
+        ..setLaunchExpectations(
+          url:
+              'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1',
+          useSafariVC: false,
+          useWebView: false,
+          enableJavaScript: false,
+          enableDomStorage: false,
+          universalLinksOnly: false,
+          headers: <String, String>{},
+          webOnlyWindowName: null,
+        )
+        ..setResponse(true);
+      expect(
+          await launch(
+              'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1'),
+          isTrue);
+    });
+
+    test('cannot open non-parseable url with forceSafariVC: true', () async {
+      expect(
+          () async => await launch(
+              'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1',
+              forceSafariVC: true),
+          throwsA(isA<PlatformException>()));
+    });
+
+    test('cannot open non-parseable url with forceWebView: true', () async {
+      expect(
+          () async => await launch(
+              'rdp://full%20address=s:mypc:3389&audiomode=i:2&disable%20themes=i:1',
+              forceWebView: true),
+          throwsA(isA<PlatformException>()));
+    });
   });
 }