-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[iOS] shouldOverrideUrLoading issue with intercepting link to open a new window using url launcher #2089
Comments
👋 @gd46 NOTE: This comment is auto-generated. Are you sure you have already searched for the same problem? Some people open new issues but they didn't search for something similar or for the same issue. Please, search for it using the GitHub issue search box or on the official inappwebview.dev website, or, also, using Google, StackOverflow, etc. before posting a new one. You may already find an answer to your problem! If this is really a new issue, then thank you for raising it. I will investigate it and get back to you as soon as possible. Please, make sure you have given me as much context as possible! Also, if you didn't already, post a code example that can replicate this issue. In the meantime, you can already search for some possible solutions online! Because this plugin uses native WebView, you can search online for the same issue adding Following these steps can save you, me, and other people a lot of time, thanks! |
See below example of the issue. Where you see UrlLauncherService see
This url launcher is another package that when we intercept a path in shouldOverrideUrlloading we tell it when to allow opening an external browser, or telephone functionality.
|
I cannot reproduce the issue using the latest plugin version. Registrazione.schermo.2024-10-01.alle.10.32.59.mp4Here is my test code: import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:developer' as developer;
WebViewEnvironment? webViewEnvironment;
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
PlatformInAppWebViewController.debugLoggingSettings.enabled = false;
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows) {
final availableVersion = await WebViewEnvironment.getAvailableVersion();
assert(availableVersion != null,
'Failed to find an installed WebView2 Runtime or non-stable Microsoft Edge installation.');
webViewEnvironment = await WebViewEnvironment.create(
settings:
WebViewEnvironmentSettings(userDataFolder: 'YOUR_CUSTOM_PATH'));
}
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
}
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
InAppWebViewSettings settings = InAppWebViewSettings(
isInspectable: true,
allowFileAccessFromFileURLs: true,
allowUniversalAccessFromFileURLs: true,
mediaPlaybackRequiresUserGesture: false,
applicationNameForUserAgent: "Test", // JUST FOR TESTING
transparentBackground: true,
useHybridComposition: true,
forceDark: ForceDark.AUTO,
allowsInlineMediaPlayback: true,
disallowOverScroll: true,
sharedCookiesEnabled: true,
allowsBackForwardNavigationGestures: false);
String url = "";
double progress = 0;
final urlController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Official InAppWebView website")),
body: SafeArea(
child: Column(children: <Widget>[
TextField(
decoration: const InputDecoration(prefixIcon: Icon(Icons.search)),
controller: urlController,
keyboardType: TextInputType.url,
onSubmitted: (value) {
var url = WebUri(value);
if (url.scheme.isEmpty) {
url = WebUri("https://www.google.com/search?q=$value");
}
webViewController?.loadUrl(urlRequest: URLRequest(url: url));
},
),
Expanded(
child: Stack(
children: [
InAppWebView(
key: webViewKey,
webViewEnvironment: webViewEnvironment,
initialUrlRequest: // JUST FOR TESTING
URLRequest(url: WebUri("https://inappwebview.dev/")),
initialSettings: settings,
onWebViewCreated: (controller) {
webViewController = controller;
},
shouldOverrideUrlLoading:
(controller, navigationAction) async {
developer.log(
'shouldOverrideUrlLoading: $navigationAction',
stackTrace: StackTrace.current,
);
bool allowNavigation = false;
Uri? url = navigationAction.request.url;
if (url?.scheme == 'blob') {
developer.log('download request.url $url',
stackTrace: StackTrace.current);
} else if (url?.scheme == 'https') {
if (url != null &&
(url.host == 'inappwebview.dev' || // JUST FOR TESTING
url.host == 'www.youtube.com' ||
url.host.endsWith('.plaid.com') ||
url.host.endsWith('.driftt.com'))) {
allowNavigation = true;
} else {
developer.log(
'BLOCKED navigating within app, url: $url',
stackTrace: StackTrace.current);
launchUrl(url!);
}
} else if (url?.scheme == 'tel') {
launchUrl(url!);
} else if (url?.toString() == 'about:blank') {
allowNavigation = true;
} else {
developer.log('BLOCKED navigating within app, url: $url',
stackTrace: StackTrace.current);
}
return allowNavigation == true
? NavigationActionPolicy.ALLOW
: NavigationActionPolicy.CANCEL;
},
onProgressChanged: (controller, progress) {
setState(() {
this.progress = progress / 100;
urlController.text = url;
});
},
onLoadStop: (controller, url) async {
// JUST FOR TESTING
await Future.delayed(Duration(seconds: 1));
await controller.evaluateJavascript(
source:
'''window.open('https://google.com', '_blank');''');
},
),
progress < 1.0
? LinearProgressIndicator(value: progress)
: Container(),
],
),
),
ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
child: const Icon(Icons.arrow_back),
onPressed: () {
webViewController?.goBack();
},
),
ElevatedButton(
child: const Icon(Icons.arrow_forward),
onPressed: () {
webViewController?.goForward();
},
),
ElevatedButton(
child: const Icon(Icons.refresh),
onPressed: () {
webViewController?.reload();
},
),
],
),
])));
}
} |
Environment
Issue was introduced on v6.0.0-beta.26 by this commit
e62348a
Last worked on v6.0.0-beta.25
Device information: iPhone 15
When shouldOverrideUrlLoading intercepts a link to launch using url launcher package the windowId here is not always null and then never executes the runCallback causing the link to not open. In testing introducing a delay around the following piece caused the issue to happen more frequently:
Expected behavior:
shouldOverrideUrlLoading should execute every time so that the url launcher can open the link
Current behavior:
runCallback is never executed(because windowId is not null, and windowBeforeCreatedCallbacks adds the runCallback but is not executed until webview is destroyed). so the link does not open. The windowId gets removed / reset when the webview is destroyed.
Steps to reproduce
3.1. Another option is to update the runCallback check in a delay which increases the problem:
The text was updated successfully, but these errors were encountered: