LoginSignup
2
1

More than 1 year has passed since last update.

FlutterのDartからWebViewのJavascript関数を呼ぶのはonPageFinished以降にする

Posted at

Flutter始めたばかりで「FlutterのDartからWebViewへ画像を送るにはData URIを使う」という記事を書きましたが、その後、注意した方がいいことに気づいたので書きます。

以下のサンプルはDartでHtmlを作成してWebViewを表示し、そこにDartから画像を転送するものです。WebView 構築時のonWebViewCreated:パラメータで指定するコールバックの中で処理されます。

    // まずHtmlを作成
    String html = "<html><head><script>"+
                  "function putimg(id,src){document.getElementById(id).src=src;}"+
                  "function test(){alert('test');}</script></head><body>"+
                  "<img id='i00'></body></html>";
    // HtmlをData URIに変換してサーバー経由しないで取得できるようにする
    final fileurl = Uri.dataFromString(
        html, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')
    ).toString();
    // それをWebViewで表示
    webviewcontroller.loadUrl( fileurl );

    // 画像をダウンロードし、Data URIでWebViewに転送
    http.get(Uri.parse('http://example.com/test.jpg')).then((response) { 
        var dataurl = Uri.dataFromBytes(response.bodyBytes, mimeType: 'image/jpeg').toString();
        webviewcontroller.evaluateJavascript("putimg('"+ item['id'] +"','"+ dataurl +"');");
      });
    webviewcontroller.evaluateJavascript("test();");

WebViewで表示されるHtmlには、イメージ表示用のputimg(id,src)関数と、テスト用のtest()関数が定義されています。ところが実際にコーディングして実行してみると、putimg(id,src)は動作してimgタグに画像が表示されますが、test()ルーチンは以下のようなエラーになることがあります。

I/chromium( 7851): [INFO:CONSOLE(1)] "Uncaught ReferenceError: test is not defined", source:  (1)

何度かくり返していると、タイミングによってはputimg()まで同じエラーになったりします。

これはwebviewcontroller.loadUrl( fileurl );の実行が終わらないうちに、evaluateJavascriptがコールされたので、Html内に対象の関数が見つからなかったからです。text()はエラーになるがputimg()がエラーにならないのは、putimg()はhttp.getの終了を待ってからコールされるので、そのころはwebviewcontroller.loadUrl()の実行が完了しているからでしょう。

ではどうすればいいかというと、onWebViewCreated:ではなく、onPageFinished:のタイミングで呼べばいいとマニュアルに書いてありました。

Androidでは描画が終わってない可能性がありますが、Html内に埋め込まれたJavascriptは存在しているので、evaluateJavascriptでコールしても大丈夫ということです。

  onPageFinished: (String url) {
    http.get(Uri.parse('http://example.com/test.jpg')).then((response) { 
        var dataurl = Uri.dataFromBytes(response.bodyBytes, mimeType: 'image/jpeg').toString();
        webviewcontroller.evaluateJavascript("putimg('"+ item['id'] +"','"+ dataurl +"');");
      });
    webviewcontroller.evaluateJavascript("test();");
  },

2
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
2
1