0

I use webview_flutter plugin in my flutter app. How can I add header parameter when url changes and how can I and how can I track url change? That's my code. I tried to do it using a loadurl in navigationDelegate, but it doesn't work. How can I do that? Please, help

String URL = 'https://...../login-app?authkey=${globals.authkey}&test=1';
  WebViewController _webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(),
body: WebView(
        // initialUrl: 'https://...../login-app?authkey=${globals.authkey}',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          _controller.complete(webViewController);
          webViewController.loadUrl(URL,headers: {"SB-app": "iphone"},);
        },
        navigationDelegate: (NavigationRequest request) async {
          print('allowing navigation to $request');
          if(request.url.contains('driver/chat') || request.url.contains('driver/on-map') || request.url.contains('driver/passanger-form') || request.url.contains('driver/login')) {
            _webViewController.loadUrl(request.url, headers: {"SB-app": "iphone"});
          }
          return NavigationDecision.navigate;
        },
        onPageStarted: (String url) async {
          print('Page started loading: $url');
        },
        onPageFinished: (String url) async {
          print('Page finished loading: $url');
        },
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Tom
  • 93
  • 3
  • 10

2 Answers2

1

You should return NavigationDecision.prevent inside your if statement of the navigationDelegate event in order to prevent the current navigation and for allowing your new navigation request with that header value. However, this won't work on iOS, because using the webview_plugin plugin, the NavigationRequest doesn't have info about the request headers, so you will end up in a loop cycle because you don't know if, for that request, your header has been already set or not.

So, for your use case, you can use my flutter_inappwebview plugin using the shouldOverrideUrlLoading event (that is the same navigationDelegate  event for webview_flutter) which contains much more info about the request and not just the URL String. To be able to listen this event, you need to set the useShouldOverrideUrlLoading: true WebView option.

Here is a simple example using https://github.com/flutter as URL. Try, with both Android and iOS, to navigate to the main flutter repository, the samples repository, or the plugins repository:

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (Platform.isAndroid) {
    await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
  }

  runApp(MaterialApp(home: new MyApp()));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
    crossPlatform: InAppWebViewOptions(
      useShouldOverrideUrlLoading: true
    ),
    android: AndroidInAppWebViewOptions(
      useHybridComposition: true,
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("InAppWebView Example")),
        body: SafeArea(
          child: Column(children: <Widget>[
            Expanded(
              child: Stack(
                children: [
                  InAppWebView(
                    initialUrlRequest: URLRequest(url: Uri.parse("https://github.com/flutter")),
                    initialOptions: options,
                    shouldOverrideUrlLoading: (controller, navigationAction) async {
                      var request = navigationAction.request;
                      var url = request.url;
                      var isUrlMatching = url != null && (url.path.contains('flutter/flutter') || url.path.contains('flutter/samples') || url.path.contains('flutter/plugins'));

                      if(isUrlMatching) {

                        if (request.headers != null && request.headers!["SB-app"] != null) {
                          print('header already set! Allow the current navigation request');
                          return NavigationActionPolicy.ALLOW;
                        }
                        else {
                          if (request.headers == null) {
                            request.headers = {};
                          }
                          print('Header not found! Set the "SB-app" header');
                          request.headers!["SB-app"] = "iphone";
                          print('Make load request with "SB-app" header');
                          controller.loadUrl(urlRequest: request);

                          print('and cancel the current navigation request');
                          return NavigationActionPolicy.CANCEL;
                        }

                      }

                      // always allow all the other requests
                      return NavigationActionPolicy.ALLOW;
                    },
                  ),
                ],
              ),
            ),
        ])));
  }
}
Lorenzo Pichilli
  • 2,896
  • 1
  • 27
  • 50
0

With this solution I can pass a basic auth to every url I visit.

return InAppWebView(
  initialUrlRequest: URLRequest(
     url: Uri.parse("https://your-url.com"),
  ),
  initialOptions: options,
  onWebViewCreated: (controller) {
    _webview_controller = controller;
  },
  onReceivedHttpAuthRequest: (InAppWebViewController controller,  challenge) async {
  return HttpAuthResponse(username: "username", password: "password", action: HttpAuthResponseAction.PROCEED);
                    },
);