flutter_webview_pluginでJS側からFlutterの関数を呼び出す

Table of Contents

Table of Contents

FlutterでWebviewを使いたくて、調査してみました。その時によく目に入ってるライブラリーは flutter_webview_pluginwebview_flutterです。webview_flutterは公式の製品ですが、ドキュメントの情報は flutter_webview_plugin より少ないですし、プレビュー公開の状態ですので、充実できたら、使っても良いと思いますが、今回はドキュメント情報が多い flutter_webview_plugin を利用して、WebVeiwからFlutter側に処理を実行させる方法を試してみました。



Table of contents

  • flutter_webview_pluginの導入
  • WebviewScaffold
  • webviewのイベント
  • webviewの表示を制御する
  • javascript側でFlutterの関数を呼び出す
  • 参考
  • 所感

flutter_webview_pluginの導入

ライブラリーの紹介はこちら

導入する際に、IOSでも正常に機能するため、ios/Runner/Info.plistにkeyを追加する。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>


WebviewScaffold

使う時には、WebviewScaffoldを作成して、urlappBarの属性を設定すれば指定しているURLのウェブページが表示されます。

基本例

class WebViewSample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new WebviewScaffold(
      url: "https://www.google.com/",
      appBar: new AppBar(
        title: const Text('WebView Sample'),
      ),
      javascriptChannels: jsChannels,
      withJavascript: true,
      withLocalStorage: true,
      hidden: true,
      initialChild: Container(
        color: Colors.redAccent,
        child: const Center(
          child: Text('Waiting.....'),
        ),
      ),
    );
  }
}

他の細かい弄りたい場合、用意している属性を設定すれば色々調整ができます。

withJavascript

Javascriptを使いたいなら、trueに設定します。


withLocalStorage

ローカルストレージを使いたい場合、trueに設定します。


hidden

trueに設定すると、ページはローディングになっている時に、円型のプログレスバーが表示されます。


initialChild

設定するとページはローディングになっている時に自前の画面を表示するもできます。


withZoom

Zoomの機能の設定


また、他にも色々ありますので、こちらを参考していただければと思います。



webviewのイベント

イベントの監視はできます。

  • onUrlChanged
  • onScrollYChanged
  • onScrollXChanged
  • onDestroy
  • onStateChanged
  • onError

使用例

final flutterWebviewPlugin = new FlutterWebviewPlugin();

flutterWebviewPlugin.onUrlChanged.listen((String url) {
  ...
});
flutterWebviewPlugin.onScrollYChanged.listen((double offsetY) { // latest offset value in vertical scroll
  // compare vertical scroll changes here with old value
});

flutterWebviewPlugin.onScrollXChanged.listen((double offsetX) { // latest offset value in horizontal scroll
  // compare horizontal scroll changes here with old value
});

FlutterWebviewPluginのインスタンスを作成して、インスタンスで各種イベントの監視ができます。

注意: flutterWebviewPlugin.dispose() でwebviewの廃棄を忘れないように



webviewの表示を制御する

FlutterWebviewPluginのインスタンスでwebviewの表示を制御できます。

flutterWebviewPlugin.hide();
flutterWebviewPlugin.show();
flutterWebviewPlugin.close();
flutterWebviewPlugin.launch(url, hidden: true);


javascript側でFlutterの関数を呼び出す

javascriptとFlutterのコミュニケーションは必要になる場合、javascriptChannels属性を設定します。 また、withJavascripttrueに設定します。

今回の例は、javascriptから文字列をFlutterに渡して、print関数でFlutter側のコンソールに文字列を出力してみます。 そのため、javascriptChannelsでjavascript側で使えるチャンネルを設定し、チャンネル経由でFlutterの処理を実行します。 javascriptChannelsに配列を設定しますので、複数チャンネルの設定ができます。 今回は一つのチェンネル(名前はPrint)を設定します。中の処理も単にもらったmessageの文字列を出力するだけです。

final jsChannels = [
  JavascriptChannel(
    name: 'Print',
    onMessageReceived: (JavascriptMessage message) {
      print(message.message);
    }
  )
].toSet();

class WebViewSample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new WebviewScaffold(
      url: "https://www.mysite.com/",
      appBar: new AppBar(
        title: const Text('WebView Sample'),
      ),
      javascriptChannels: jsChannels,
      withJavascript: true,
      withLocalStorage: true,
      initialChild: Container(
        color: Colors.redAccent,
        child: const Center(
          child: Text('Waiting.....'),
        ),
      ),
    );
  }
}

Webページのjavascript

if (typeof Print !== 'undefined') {
    Print.postMessage('Hello world being called from Javascript code')
    console.log('running inside a Flutter webview')
} else {
    console.log('not running inside a Flutter webview')
}

Printが定義しているなら、postMessageで文字列をFlutter側に送る。 上記のコードはページのロード完了したら実行します。

Flutterアプリでwebviewを起動したら、コンソールには下記のような文字列が表示されます。

result



参考



所感

flutter_webview_pluginを使ってみた感想はかなり便利で、使い方も簡単ですし、途中に何か不具合とか今のところは発生していません。品質はすごく良いと感じました。ただ、作成したwebviewのUIは一番上に表示されますので、FlutterのDialogやToastなどの表示が隠されるみたいです。その時には、hideshowを使って一時的にwebviewの表示・非表示にしてもいいかもしれません。webview_flutterではそのように問題はないみたいですし、公式のライブラリーでもあるし、色々便利の機能が出てくるではないかと期待していますので、flutter_webview_pluginとwebview_flutterを組み合わせて使う方は良い方法かもしれません。