Welcome to another Webview tutorial,
In this tutorial we will see what are the other API’s available in the webview_flutter plugin. Read the part-1 of this tutorial to get an introduction on webview in flutter.

Webview Flutter
Watch Video Tutorial
We will be implementing the below functionalities in our webview.
- Show User Agent
- List Cookies
- Clear Cookies
- Add To Cache
- List Cache
- Clear Cache
- Navigation Delegate
First we will write the functions that implements all the above functionalities
Show User Agent
void _onShowUserAgent( WebViewController controller, BuildContext context) async { // Send a message with the user agent string to the Toaster JavaScript channel we registered // with the WebView. controller.evaluateJavascript( 'Toaster.postMessage("User Agent: " + navigator.userAgent);' ); } |
List Cookies
void _onListCookies( WebViewController controller, BuildContext context) async { final String cookies = await controller.evaluateJavascript( 'document.cookie' ); Scaffold.of(context).showSnackBar(SnackBar( content: Column( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: <Widget>[ const Text( 'Cookies:' ), _getCookieList(cookies), ], ), )); } |
Clear Cookies
void _onClearCookies(BuildContext context) async { final bool hadCookies = await cookieManager.clearCookies(); String message = 'There were cookies. Now, they are gone!' ; if (!hadCookies) { message = 'There are no cookies.' ; } Scaffold.of(context).showSnackBar(SnackBar( content: Text(message), )); } |
Add To Cache
void _onAddToCache(WebViewController controller, BuildContext context) async { await controller.evaluateJavascript( 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";' ); Scaffold.of(context).showSnackBar( const SnackBar( content: Text( 'Added a test entry to cache.' ), )); } |
List Cache
void _onListCache(WebViewController controller, BuildContext context) async { await controller.evaluateJavascript( 'caches.keys()' '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' '.then((caches) => Toaster.postMessage(caches))' ); } |
Clear Cache
void _onClearCache(WebViewController controller, BuildContext context) async { await controller.clearCache(); Scaffold.of(context).showSnackBar( const SnackBar( content: Text( "Cache cleared." ), )); } |
Navigation Delegate
Here we will listen for each webview navigation and we can block or modify the url based on the request.
void _onNavigationDelegateExample( WebViewController controller, BuildContext context) async { final String contentBase64 = base64Encode( const Utf8Encoder().convert(kNavigationExamplePage)); controller.loadUrl( 'data:text/html;base64,$contentBase64' ); } |
Get Cookies List
Widget _getCookieList(String cookies) { if (cookies == null || cookies == '""' ) { return Container(); } final List<String> cookieList = cookies.split( ';' ); final Iterable<Text> cookieWidgets = cookieList.map((String cookie) => Text(cookie)); return Column( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: cookieWidgets.toList(), ); } } |
Navigation Delegate implementation
@override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text( 'Webview Demo' ), actions: <Widget>[ NavigationControls(_controller.future), ], ), body: Builder( builder: (BuildContext context) { return WebView( initialUrl: 'https://flutter.dev' , javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller.complete(webViewController); }, javascriptChannels: <JavascriptChannel>[ snackbarJavascriptChannel(context), ].toSet(), navigationDelegate: (NavigationRequest request) { return NavigationDecision.navigate; }, ); }, ), ... |
Complete Code
import 'package:flutter/material.dart' ; import 'package:webview_flutter/webview_flutter.dart' ; import 'dart:async' ; import 'dart:convert' ; const String examplepage = '' ' <!DOCTYPE html><html> <head><title>Navigation Delegate Example</title></head> <body> <p> The navigation delegate is set to block navigation to the youtube website. </p> <ul> <ul><a href= "https://www.youtube.com/" >https://www.youtube.com/</a></ul> <ul><a href= "https://www.google.com/" >https://www.google.com/</a></ul> </ul> </body> </html> '' '; class WebviewDemo extends StatefulWidget { final String title; WebviewDemo({Key key, this .title}) : super (key: key); @override State<StatefulWidget> createState() { return _WebviewDemoState(); } } JavascriptChannel snackbarJavascriptChannel(BuildContext context) { return JavascriptChannel( name: 'SnackbarJSChannel' , onMessageReceived: (JavascriptMessage message) { Scaffold.of(context).showSnackBar(SnackBar( content: Text(message.message), )); }, ); } class _WebviewDemoState extends State<WebviewDemo> { // final Completer<WebViewController> _controller = Completer<WebViewController>(); @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text( 'Webview Demo' ), actions: <Widget>[ NavigationControls(_controller.future), SampleMenu(_controller.future) ], ), body: Builder( builder: (BuildContext context) { return WebView( initialUrl: 'http://flutter.dev' , javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller.complete(webViewController); }, javascriptChannels: <JavascriptChannel>[ snackbarJavascriptChannel(context), ].toSet(), navigationDelegate: (NavigationRequest request) { if (request.url.startsWith( "https://www.youtube.com" )) { print( "Blocking navigation" ); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, ); }, ), ); } } enum MenuOptions { showUserAgent, listCookies, clearCookies, addToCache, listCache, clearCache, navigationDelegate } class SampleMenu extends StatelessWidget { SampleMenu( this .controller); final Future<WebViewController> controller; final CookieManager cookieManager = CookieManager(); @override Widget build(BuildContext context) { return FutureBuilder<WebViewController>( future: controller, builder: (BuildContext context, AsyncSnapshot<WebViewController> controller) { return PopupMenuButton<MenuOptions>( itemBuilder: (BuildContext context) => <PopupMenuItem<MenuOptions>>[ PopupMenuItem( value: MenuOptions.showUserAgent, child: const Text( 'Show User Agent' ), enabled: controller.hasData, ), PopupMenuItem( value: MenuOptions.listCookies, child: const Text( 'List Cookies' ), ), PopupMenuItem( value: MenuOptions.clearCookies, child: const Text( 'Clear Cookies' ), ), PopupMenuItem( value: MenuOptions.addToCache, child: const Text( 'Add to Cache' ), ), PopupMenuItem( value: MenuOptions.listCache, child: const Text( 'List Cache' ), ), PopupMenuItem( value: MenuOptions.clearCache, child: const Text( 'Clear Cache' ), ), PopupMenuItem( value: MenuOptions.navigationDelegate, child: const Text( 'Navigation Delegate Demo' ), ) ], onSelected: (MenuOptions value) { switch (value) { case MenuOptions.showUserAgent: showUserAgent(controller.data, context); break ; case MenuOptions.listCookies: listCookies(controller.data, context); break ; case MenuOptions.clearCookies: clearCookies(controller.data, context); break ; case MenuOptions.addToCache: addToCache(controller.data, context); break ; case MenuOptions.listCache: listCache(controller.data, context); break ; case MenuOptions.clearCache: clearCache(controller.data, context); break ; case MenuOptions.navigationDelegate: navigationDelegateDemo(controller.data, context); break ; default : } }, ); }, ); } navigationDelegateDemo( WebViewController controller, BuildContext context) async { final String contentbase64 = base64Encode( const Utf8Encoder().convert(examplepage)); controller.loadUrl( 'data:text/html;base64,$contentbase64' ); } addToCache(WebViewController controller, BuildContext context) async { await controller.evaluateJavascript( 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";' ); Scaffold.of(context).showSnackBar( const SnackBar( content: Text( 'Added a test entry to cache' ), ), ); } void listCache(WebViewController controller, BuildContext context) async { await controller.evaluateJavascript( 'caches.keys().then((cacheKeys) => JSON.stringify({"cacheKeys": cacheKeys, "localStorage": localStorage })).then((caches) => SnackbarJSChannel.postMessage(caches))' ); } void clearCache(WebViewController controller, BuildContext context) async { await controller.clearCache(); Scaffold.of(context).showSnackBar( const SnackBar( content: Text( 'Cache Cleared' ), ), ); } listCookies(WebViewController controller, BuildContext context) async { final String cookies = await controller.evaluateJavascript( 'document.cookie' ); Scaffold.of(context).showSnackBar( SnackBar( content: Column( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: <Widget>[ const Text( 'Cookies:' ), getCookies(cookies)], ), ), ); } Widget getCookies(String cookies) { if ( null == cookies || cookies.isEmpty) { return Container(); } final List<String> cookieList = cookies.split( ';' ); final Iterable<Text> cookieWidgets = cookieList.map( (String cookie) => Text(cookie), ); return Column( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: cookieWidgets.toList(), ); } void clearCookies(WebViewController controller, BuildContext context) async { final bool hadCookies = await cookieManager.clearCookies(); String message = 'There are no cookies' ; Scaffold.of(context).showSnackBar( SnackBar( content: Text(message), ), ); } showUserAgent(WebViewController controller, BuildContext context) { controller.evaluateJavascript( 'SnackbarJSChannel.postMessage("User Agent: " + navigator.userAgent);' ); } } class NavigationControls extends StatelessWidget { const NavigationControls( this ._webViewControllerFuture); final Future<WebViewController> _webViewControllerFuture; @override Widget build(BuildContext context) { return FutureBuilder( future: _webViewControllerFuture, builder: (BuildContext context, AsyncSnapshot<WebViewController> snapshot) { final bool webViewReady = snapshot.connectionState == ConnectionState.done; final WebViewController controller = snapshot.data; return Row( children: <Widget>[ IconButton( icon: const Icon(Icons.arrow_back_ios), onPressed: !webViewReady ? null : () async { if (await controller.canGoBack()) { controller.goBack(); } else { Scaffold.of(context).showSnackBar( const SnackBar( content: Text( "No Back history Item" ), ), ); } }, ), IconButton( icon: const Icon(Icons.arrow_forward_ios), onPressed: !webViewReady ? null : () async { if (await controller.canGoForward()) { controller.goForward(); } else { Scaffold.of(context).showSnackBar( const SnackBar( content: Text( "No Forward history Item" ), ), ); } }, ), IconButton( icon: const Icon(Icons.refresh), onPressed: !webViewReady ? null : () async { controller.reload(); }, ) ], ); }, ); } } |