Site icon Flutter Packages | Pub dev Packages – Flutter Mobile App World

Flutter InAppWebView Plugin

Info: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.

Flutter InAppWebView Plugin

A Flutter plugin that allows you to add an inline webview or open an in-app browser window.

Requirements

IMPORTANT Note for Android

If you are starting a new fresh app, you need to create the Flutter App with flutter create --androidx -i swift to add support for androidx, otherwise it won’t work (see AndroidX Migration to migrate an existing app).

During the build, if Android fails with Error: uses-sdk:minSdkVersion 16 cannot be smaller than version 17 declared in library, it means that you need to update the minSdkVersion of your android/app/build.gradle file to at least 17.

Also, you need to add <uses-permission android:name="android.permission.INTERNET"/> in the android/app/src/main/AndroidManifest.xml file in order to give minimum permission to perform network operations in your application.

Because of Flutter AndroidX compatibility, the latest version that doesn’t use AndroidX is 0.6.0.

IMPORTANT Note for iOS

If you are starting a new fresh app, you need to create the Flutter App with flutter create --androidx -i swift (see flutter/flutter#13422 (comment)), otherwise, you will get this message:

=== BUILD TARGET flutter_inappwebview OF PROJECT Pods WITH CONFIGURATION Debug ===
The “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift. Supported values are: 3.0, 4.0, 4.2, 5.0. This setting can be set in the build settings editor.

If you still have this problem, try to edit iOS Podfile like this (see #15):

target 'Runner' do
  use_frameworks!  # required by simple_permission
  ...
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['SWIFT_VERSION'] = '5.0'  # required by simple_permission
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end
end

Instead, if you have already a non-swift project, you can check this issue to solve the problem: Friction adding swift plugin to objective-c project.

Getting Started

For help getting started with Flutter, view our online documentation.

For help on editing plugin code, view the documentation.

Installation

First, add flutter_inappwebview as a dependency in your pubspec.yaml file.

Usage

Classes:

API Reference

See the online API Reference to get the full documentation.

The API showed in this README.md file shows only a part of the documentation that conforms to the master branch only. So, here you could have methods, options, and events that aren’t published yet. If you need a specific version, change the GitHub branch to your version or use the online API Reference (recommended).

Load a file inside assets folder

To be able to load your local files (assets, js, css, etc.), you need to add them in the assets section of the pubspec.yaml file, otherwise they cannot be found!

Example of a pubspec.yaml file:

...

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  assets:
    - assets/index.html
    - assets/css/
    - assets/images/

...

InAppWebView class

Flutter Widget for adding an inline native WebView integrated into the flutter widget tree.

The plugin relies on Flutter’s mechanism (in developers preview) for embedding Android and iOS native views: AndroidView and UiKitView. Known issues are tagged with the platform-views label in the Flutter official repo. Keyboard support within webviews is also experimental.

To use InAppWebView class on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app’s Info.plist file, with the key io.flutter.embedded_views_preview and the value YES.

Use InAppWebViewController to control the WebView instance. Example:

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

Future main() async {
  runApp(new MyApp());
}

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

class _MyAppState extends State<MyApp> {

  InAppWebViewController webView;
  String url = "";
  double progress = 0;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('InAppWebView Example'),
        ),
        body: Container(
          child: Column(children: <Widget>[
            Container(
              padding: EdgeInsets.all(20.0),
              child: Text(
                  "CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
            ),
            Container(
                padding: EdgeInsets.all(10.0),
                child: progress < 1.0
                    ? LinearProgressIndicator(value: progress)
                    : Container()),
            Expanded(
              child: Container(
                margin: const EdgeInsets.all(10.0),
                decoration:
                    BoxDecoration(border: Border.all(color: Colors.blueAccent)),
                child: InAppWebView(
                  initialUrl: "https://flutter.dev/",
                  initialHeaders: {},
                  initialOptions: InAppWebViewWidgetOptions(
                    crossPlatform: InAppWebViewOptions(
                        debuggingEnabled: true,
                    )
                  ),
                  onWebViewCreated: (InAppWebViewController controller) {
                    webView = controller;
                  },
                  onLoadStart: (InAppWebViewController controller, String url) {
                    setState(() {
                      this.url = url;
                    });
                  },
                  onLoadStop: (InAppWebViewController controller, String url) async {
                    setState(() {
                      this.url = url;
                    });
                  },
                  onProgressChanged: (InAppWebViewController controller, int progress) {
                    setState(() {
                      this.progress = progress / 100;
                    });
                  },
                ),
              ),
            ),
            ButtonBar(
              alignment: MainAxisAlignment.center,
              children: <Widget>[
                RaisedButton(
                  child: Icon(Icons.arrow_back),
                  onPressed: () {
                    if (webView != null) {
                      webView.goBack();
                    }
                  },
                ),
                RaisedButton(
                  child: Icon(Icons.arrow_forward),
                  onPressed: () {
                    if (webView != null) {
                      webView.goForward();
                    }
                  },
                ),
                RaisedButton(
                  child: Icon(Icons.refresh),
                  onPressed: () {
                    if (webView != null) {
                      webView.reload();
                    }
                  },
                ),
              ],
            ),
        ])),
      ),
    );
  }
}

Screenshots:

InAppWebViewController Methods

InAppWebViewController Cross-platform methods
InAppWebViewController Android-specific methods

Android-specific methods can be called using the InAppWebViewController.android attribute.

InAppWebViewController iOS-specific methods

iOS-specific methods can be called using the InAppWebViewController.ios attribute.

About the JavaScript handler

The android implementation uses addJavascriptInterface. The iOS implementation uses addScriptMessageHandler

The JavaScript function that can be used to call the handler is window.flutter_inappwebview.callHandler(handlerName <String>, ...args), where args are rest parameters. The args will be stringified automatically using JSON.stringify(args) method and then they will be decoded on the Dart side.

In order to call window.flutter_inappwebview.callHandler(handlerName <String>, ...args) properly, you need to wait and listen the JavaScript event flutterInAppWebViewPlatformReady. This event will be dispatched as soon as the platform (Android or iOS) is ready to handle the callHandler method.

   window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
     console.log("ready");
   });

window.flutter_inappwebview.callHandler returns a JavaScript Promise that can be used to get the json result returned by [JavaScriptHandlerCallback]. In this case, simply return data that you want to send and it will be automatically json encoded using [jsonEncode] from the dart:convert library.

So, on the JavaScript side, to get data coming from the Dart side, you will use:

<script>
   window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
     window.flutter_inappwebview.callHandler('handlerFoo').then(function(result) {
       console.log(result);
     });

     window.flutter_inappwebview.callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}).then(function(result) {
       console.log(result);
     });
   });
</script>

Instead, on the onLoadStop WebView event, you can use callHandler directly:

  // Inject JavaScript that will receive data back from Flutter
  inAppWebViewController.evaluateJavascript(source: """
    window.flutter_inappwebview.callHandler('test', 'Text from Javascript').then(function(result) {
      console.log(result);
    });
  """);

InAppWebView options

InAppWebView Cross-platform options
InAppWebView Android-specific options
InAppWebView iOS-specific options

InAppWebView Events

Event names that starts with android or ios are events platform-specific.

InAppBrowser class

In-App Browser using native WebView.

inAppBrowser.webViewController can be used to access the InAppWebView API.

Create a Class that extends the InAppBrowser Class in order to override the callbacks to manage the browser events. Example:

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

class MyInAppBrowser extends InAppBrowser {
  @override
  Future onBrowserCreated() async {
    print("\n\nBrowser Created!\n\n");
  }

  @override
  Future onLoadStart(String url) async {
    print("\n\nStarted $url\n\n");
  }

  @override
  Future onLoadStop(String url) async {
    print("\n\nStopped $url\n\n");
  }

  @override
  void onLoadError(String url, int code, String message) {
    print("Can't load $url.. Error: $message");
  }

  @override
  void onProgressChanged(int progress) {
    print("Progress: $progress");
  }

  @override
  void onExit() {
    print("\n\nBrowser closed!\n\n");
  }

  @override
  Future<ShouldOverrideUrlLoadingAction> shouldOverrideUrlLoading(ShouldOverrideUrlLoadingRequest shouldOverrideUrlLoadingRequest) async {
    print("\n\n override ${shouldOverrideUrlLoadingRequest.url}\n\n");
    this.webViewController.loadUrl(url: shouldOverrideUrlLoadingRequest.url);
    return ShouldOverrideUrlLoadingAction.CANCEL;
  }

  @override
  void onLoadResource(LoadedResource response) {
    print("Started at: " +
        response.startTime.toString() +
        "ms ---> duration: " +
        response.duration.toString() +
        "ms " +
        response.url);
  }

  @override
  void onConsoleMessage(ConsoleMessage consoleMessage) {
    print("""
    console output:
      message: ${consoleMessage.message}
      messageLevel: ${consoleMessage.messageLevel.toValue()}
   """);
  }
}

void main() => runApp(new MyApp());

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

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('InAppBrowser Example'),
        ),
        body: Center(
          child: RaisedButton(
              onPressed: () {
                widget.browser.openFile(
                    assetFilePath: "assets/index.html",
                    options: InAppBrowserClassOptions(
                        inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
                            crossPlatform: InAppWebViewOptions(
                              useShouldOverrideUrlLoading: true,
                              useOnLoadResource: true,
                            ))));
              },
              child: Text("Open InAppBrowser")),
        ),
      ),
    );
  }
}

Screenshots:

InAppBrowser Methods

InAppBrowser options

They are the same of the InAppWebView class. Specific options of the InAppBrowser class are:

InAppBrowser Cross-platform options
InAppBrowser Android-specific options
InAppBrowser iOS-specific options

InAppBrowser Events

They are the same of the InAppWebView class, except for InAppWebView.onWebViewCreated event. Specific events of the InAppBrowser class are:

ChromeSafariBrowser class

Chrome Custom Tabs on Android / SFSafariViewController on iOS.

You can initialize the ChromeSafariBrowser instance with an InAppBrowser fallback instance.

Create a Class that extends the ChromeSafariBrowser Class in order to override the callbacks to manage the browser events. Example:

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

class MyInAppBrowser extends InAppBrowser {

  @override
  Future onLoadStart(String url) async {
    print("\n\nStarted $url\n\n");
  }

  @override
  Future onLoadStop(String url) async {
    print("\n\nStopped $url\n\n");
  }

  @override
  void onLoadError(String url, int code, String message) {
    print("\n\nCan't load $url.. Error: $message\n\n");
  }

  @override
  void onExit() {
    print("\n\nBrowser closed!\n\n");
  }

}

class MyChromeSafariBrowser extends ChromeSafariBrowser {
  
  MyChromeSafariBrowser(browserFallback) : super(bFallback: browserFallback);

  @override
  void onOpened() {
    print("ChromeSafari browser opened");
  }

  @override
  void onLoaded() {
    print("ChromeSafari browser loaded");
  }

  @override
  void onClosed() {
    print("ChromeSafari browser closed");
  }
}

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  final ChromeSafariBrowser browser = new MyChromeSafariBrowser(new MyInAppBrowser());
  
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('ChromeSafariBrowser Example'),
        ),
        body: Center(
          child: RaisedButton(
              onPressed: () async {
                await widget.browser.open(
                    url: "https://flutter.dev/",
                    options: ChromeSafariBrowserClassOptions(
                        android: AndroidChromeCustomTabsOptions(addShareButton: false),
                        ios: IosSafariOptions(barCollapsingEnabled: true)));
              },
              child: Text("Open Chrome Safari Browser")),
        ),
      ),
    );
  }
}

Screenshots:

ChromeSafariBrowser Methods

ChromeSafariBrowser options

ChromeSafariBrowser Android-specific options
ChromeSafariBrowser iOS-specific options

ChromeSafariBrowser Events

InAppLocalhostServer class

This class allows you to create a simple server on http://localhost:[port]/ in order to be able to load your assets file on a server. The default port value is 8080.

Example:

// ...

InAppLocalhostServer localhostServer = new InAppLocalhostServer();

Future main() async {
  await localhostServer.start();
  runApp(new MyApp());
}

// ...

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('InAppWebView Example'),
        ),
        body: Container(
          child: Column(children: <Widget>[
            Expanded(
              child: Container(
                child: InAppWebView(
                  initialUrl: "http://localhost:8080/assets/index.html",
                  initialHeaders: {},
                  initialOptions: InAppWebViewWidgetOptions(
                      inAppWebViewOptions: InAppWebViewOptions(
                        debuggingEnabled: true,
                      )
                  ),
                  onWebViewCreated: (InAppWebViewController controller) {
  
                  },
                  onLoadStart: (InAppWebViewController controller, String url) {
  
                  },
                  onLoadStop: (InAppWebViewController controller, String url) {
  
                  },
                ),
              ),
            )]
          )
        ),
      ),
    );
  }

// ...

InAppLocalhostServer methods

CookieManager class

This class implements a singleton object (shared instance) which manages the cookies used by WebView instances.

NOTE for iOS: available from iOS 11.0+.

CookieManager methods

HttpAuthCredentialDatabase class

This class implements a singleton object (shared instance) which manages the shared HTTP auth credentials cache. On iOS, this class uses the URLCredentialStorage class. On Android, this class has a custom implementation using android.database.sqlite.SQLiteDatabase because WebViewDatabase doesn’t offer the same functionalities as iOS URLCredentialStorage.

HttpAuthCredentialDatabase methods

WebStorageManager class

This class implements a singleton object (shared instance) which manages the web storage used by WebView instances.

On Android, it is implemented using WebStorage. On iOS, it is implemented using WKWebsiteDataStore.default()

NOTE for iOS: available from iOS 9.0+.

WebStorageManager methods

WebStorageManager Android-specific methods

Android-specific methods can be called using the WebStorageManager.instance().android attribute.

AndroidWebStorageManager class is used to manage the JavaScript storage APIs provided by the WebView. It manages the Application Cache API, the Web SQL Database API and the HTML5 Web Storage API.

WebStorageManager iOS-specific methods

iOS-specific methods can be called using the WebStorageManager.instance().ios attribute.

IOSWebStorageManager class represents various types of data that a website might make use of. This includes cookies, disk and memory caches, and persistent data such as WebSQL, IndexedDB databases, and local storage.

Download Flutter InAppWebView Plugin Source Code on GitHub

Exit mobile version