3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「Flutter アプリに WebView を追加する」Code Labをwebview_flutter4.0.0以降でやってみた

Posted at

「Flutter アプリに WebView を追加する」はwebview_flutter4.0.0以降に対応していない

詳しく調べた訳ではないのでおそらくです。
Flutter アプリに WebView を追加する

実際のコード


import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:webview_flutter/webview_flutter.dart';

const request = '''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
  if (req.status == 200) {
    let response = JSON.parse(req.responseText);
    SnackBar.postMessage("IP Address: " + response.ip);
  } else {
    SnackBar.postMessage("Error: " + req.status);
  }
}
req.send();''';
const addCookie = '''var date = new Date();
  date.setTime(date.getTime()+(30*24*60*60*1000));
  document.cookie = "FirstName=John; expires=" + date.toGMTString();''';
const removeCookie =
    '''document.cookie = "FirstName=; expires=Thu, 01 Jan 1970 00:00:00 UTC";''';
const String kExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body>

<h1>Local demo page</h1>
<p>
 This is an example page used to demonstrate how to load a local file or HTML
 string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
 webview</a> plugin.
</p>

</body>
</html>
''';

class WebView extends StatelessWidget {
  WebView({super.key});

  static final url = Uri(
    scheme: 'https',
    host: 'flutter.dev',
  );

  final loadPercentage = ValueNotifier(0);

  @override
  Widget build(BuildContext context) {
    var controller = WebViewController();

    void createJavascriptChannels(JavaScriptMessage message) {
      ScaffoldMessenger.of(context)
          .showSnackBar(SnackBar(content: Text(message.message)));
    }

    controller
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel('SnackBar',
          onMessageReceived: createJavascriptChannels)
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) => {},
        onProgress: (progress) => loadPercentage.value = progress,
        onPageFinished: (url) => loadPercentage.value = 100,
        onNavigationRequest: (request) {
          final host = Uri.parse(request.url).host;
          if (host.contains('youtube.com')) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(
                  'Blocking navigation to $host',
                ),
              ),
            );
            return NavigationDecision.prevent;
          }
          return NavigationDecision.navigate;
        },
      ))
      ..loadRequest(url);

    var webViewWidget = WebViewWidget(
      controller: controller,
    );

    var valueListenableBuilder = ValueListenableBuilder(
        valueListenable: loadPercentage,
        builder: (context, count, child) {
          return LinearProgressIndicator(
            value: count / 100,
          );
        });

    var stack = Stack(
      children: [webViewWidget, valueListenableBuilder],
    );

    var appBar = AppBar(
      title: const Text('Flutter WebView'),
      actions: [
        NavigationConrtoller(controller: controller),
        Menu(controller: controller)
      ],
    );

    var scaffold = Scaffold(
      appBar: appBar,
      body: stack,
    );

    return scaffold;
  }
}

class NavigationConrtoller extends StatelessWidget {
  final WebViewController controller;
  const NavigationConrtoller({Key? key, required this.controller})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    late final Row row;
    var left = IconButton(
      icon: const Icon(Icons.arrow_back_ios),
      onPressed: () {
        controller.canGoBack().then((value) => {
              if (value)
                {controller.goBack()}
              else
                {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('No back history item')),
                  )
                }
            });
      },
    );
    var center = IconButton(
      icon: const Icon(Icons.arrow_forward_ios),
      onPressed: () async {
        if (await controller.canGoForward()) {
          await controller.goForward();
        } else {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('No forward history item')),
          );
          return;
        }
      },
    );
    var right = IconButton(
      icon: const Icon(Icons.replay),
      onPressed: () {
        controller.reload();
      },
    );
    row = Row(
      children: <Widget>[
        left,
        center,
        right,
      ],
    );
    return row;
  }
}

enum _MenuOptions {
  navigationDelegate,
  userAgent,
  javascriptChannel,
  listCookies,
  clearCookies,
  addCookie,
  setCookie,
  removeCookie,
  loadFlutterAsset,
  loadLocalFile,
  loadHtmlString,
}

class Menu extends StatelessWidget {
  static final url = Uri(
    scheme: 'https',
    host: 'youtube.com',
  );
  final WebViewController controller;
  final cookieManager = WebViewCookieManager();
  Menu({Key? key, required this.controller}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    var menu = PopupMenuButton(itemBuilder: (context) {
      return <PopupMenuEntry>[
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.navigationDelegate,
          child: Text('Navigate to YouTube'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.userAgent,
          child: Text('Show user-agent'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.javascriptChannel,
          child: Text('Lookup IP Address'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.clearCookies,
          child: Text('Clear cookies'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.listCookies,
          child: Text('List cookies'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.addCookie,
          child: Text('Add cookie'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.setCookie,
          child: Text('Set cookie'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.removeCookie,
          child: Text('Remove cookie'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.loadFlutterAsset,
          child: Text('Load Flutter Asset'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.loadHtmlString,
          child: Text('Load HTML string'),
        ),
        const PopupMenuItem<_MenuOptions>(
          value: _MenuOptions.loadLocalFile,
          child: Text('Load local file'),
        ),
      ];
    }, onSelected: (value) {
      switch (value) {
        case _MenuOptions.navigationDelegate:
          controller.loadRequest(url);
          break;
        case _MenuOptions.userAgent:
          controller.getUserAgent().then((value) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('User-Agent: $value'),
              ),
            );
          });
          break;
        case _MenuOptions.javascriptChannel:
          controller.runJavaScript(request).then((value) => {});
          break;
        case _MenuOptions.clearCookies:
          cookieManager.clearCookies();
          break;
        case _MenuOptions.listCookies:
          controller.runJavaScriptReturningResult('document.cookie').then(
            (value) {
              final String cookies = value as String;
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(
                  content: Text(
                      cookies.isNotEmpty ? cookies : 'There are no cookies.'),
                ),
              );
            },
          );
          break;
        case _MenuOptions.addCookie:
          controller.runJavaScript(addCookie).then((value) => {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(
                    content: Text('Custom cookie added.'),
                  ),
                ),
              });
          break;
        case _MenuOptions.setCookie:
          cookieManager
              .setCookie(
                const WebViewCookie(
                    name: 'foo', value: 'bar', domain: 'flutter.dev'),
              )
              .then((value) => {
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(
                        content: Text('Custom cookie is set.'),
                      ),
                    ),
                  });
          break;
        case _MenuOptions.removeCookie:
          controller.runJavaScript(removeCookie).then((value) => {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(
                    content: Text('Custom cookie removed.'),
                  ),
                ),
              });
          break;
        case _MenuOptions.loadFlutterAsset:
          _onLoadFlutterAssetExample(controller, context);
          break;
        case _MenuOptions.loadLocalFile:
          _onLoadLocalFileExample(controller, context);
          break;
        case _MenuOptions.loadHtmlString:
          _onLoadHtmlStringExample(controller, context);
          break;
      }
    });
    return menu;
  }

  Future<void> _onLoadFlutterAssetExample(
      WebViewController controller, BuildContext context) async {
    await controller.loadFlutterAsset('assets/www/index.html');
  }

  Future<void> _onLoadLocalFileExample(
      WebViewController controller, BuildContext context) async {
    final String pathToIndex = await _prepareLocalFile();

    await controller.loadFile(pathToIndex);
  }

  static Future<String> _prepareLocalFile() async {
    final String tmpDir = (await getTemporaryDirectory()).path;
    final File indexFile = File('$tmpDir/www/index.html');

    await Directory('$tmpDir/www').create(recursive: true);
    await indexFile.writeAsString(kExamplePage);

    return indexFile.path;
  }

  Future<void> _onLoadHtmlStringExample(
      WebViewController controller, BuildContext context) async {
    await controller.loadHtmlString(kExamplePage);
  }
}


3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?