Alex
Alex

Reputation: 35118

Open some links with system app / browser in flutter inappwebview?

We have a Flutter app which uses inappwebview to display a webpage that among the main content, contains links to a YouTube video tutorial.

When clicking this link, the video is played in the web view instead of opening a system browser / the YouTube app.

How can we make specific links to open in an external app or browser?

I was thinking about listening to the Navigation event and then call the YouTube app?

EDIT:

The link looks like this:

window.open(tutorialUrl, '_blank', 'location=yes')

So I though I could use this approach:

onCreateWindow: (InAppWebViewController controller,
    CreateWindowAction createWindowAction) {

  if (createWindowAction.request.url != null) {
    launchUrl(createWindowAction.request.url!);
  }

  return Future.value(false);
},

But still the URL is opened inside of the webview.

Upvotes: 0

Views: 6190

Answers (2)

Lorenzo Pichilli
Lorenzo Pichilli

Reputation: 3439

You can use the onCreateWindow event! As the official docs say, you should return true if you handle the new window creation action.

Here is a code example using the current latest version 6 (6.0.0-beta.18):

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (!kIsWeb &&
      kDebugMode &&
      defaultTargetPlatform == TargetPlatform.android) {
    await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
  }
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("InAppWebView test"),
        ),
        body: Column(children: <Widget>[
          Expanded(
            child: InAppWebView(
              key: webViewKey,
              initialData: InAppWebViewInitialData(data: """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="tutorialButton">Open Tutorial Link</button>
    <script>
        document.querySelector('#tutorialButton').addEventListener('click', function(event) {
            window.open('https://www.youtube.com/watch?v=zEdw_1B7JHY', '_blank', 'location=yes')
        });
    </script>
</body>
</html>
                """),
              initialSettings: InAppWebViewSettings(
                  javaScriptCanOpenWindowsAutomatically: true,
                  supportMultipleWindows: true),
              onWebViewCreated: (controller) {
                webViewController = controller;
              },
              onCreateWindow: (controller, createWindowAction) async {
                // create a headless WebView using the createWindowAction.windowId to get the correct URL
                HeadlessInAppWebView? headlessWebView;
                headlessWebView = HeadlessInAppWebView(
                  windowId: createWindowAction.windowId,
                  onLoadStart: (controller, url) async {
                    if (url != null) {
                      InAppBrowser.openWithSystemBrowser(
                          url: url); // to open with the system browser
                      // or use the https://pub.dev/packages/url_launcher plugin
                    }
                    // dispose it immediately
                    await headlessWebView?.dispose();
                    headlessWebView = null;
                  },
                );
                headlessWebView?.run();

                // return true to tell that we are handling the new window creation action
                return true;
              },
            ),
          ),
        ]));
  }
}

Android example iOS example

Upvotes: 1

Alex
Alex

Reputation: 35118

This does work:

      shouldOverrideUrlLoading: (controller, navigationAction) async {
        final uri = navigationAction.request.url!;
        print("uri = " + uri.toString());
        if (uri.toString().startsWith('https://www.youtube.com')) {
          launchUrl(uri);
          return NavigationActionPolicy.CANCEL;
        }
        return NavigationActionPolicy.ALLOW;
      },

But I still would be happy for other answers using the window.open method. Background: If one day we replace the video by a Vimeo link (for example), we would need to update the app, as opposed to just needing to update the underlying website.

Upvotes: 2

Related Questions