パルカワ2

PerlとRubyとイチャラブ

FlutterでWebViewをがんばる その2

github.com

FlutterでWebViewを扱うために webview_flutter を使って、flutter_inappwebviewを使ってきたが、結局native_webviewというライブラリを自分で作り始めた。

webview_flutterもflutter_inappwebviewもどちらとも良い面があるので採用してきたのだけど、不満もあった。

webview_flutterの不満は、必要な機能が足りていないこと。足りないのであれば自分でforkしてプルリクすればいいのだけど、結構放置されているプルリクが多くリリースまでに間に合いそうにないなと感じた。また機能が少ない分実装はシンプルなのだけど、Objective-CJavaで実装されていて、自分でforkしてそれを継続的にメンテナンスしていくのは大変だなという印象だった。

flutter_inappwebviewの不満は、現状メンテンスが行われていないこと。また色んな機能があるため僕自身が使っていない部分が多く、自分でforkしてメンテナンスしていくのは大変そうで嫌だった。またCIでテストが実行されていないからか、結構バグってるなという印象だった(数ヶ月前はイシューを書けば反応があったので良かったんだけど、今は反応がなくなってしまった…) あとflutter_inappwebviewをforkして出されたプルリクをマージしてるリポジトリもあるのだけど、テストがなかったり動かなくなるようなプルリクもマージしていてちょっとやだなあという印象だったので使わなかった。

native_webviewの利点

僕が気づいているwebivew_flutterやinappwebviewにあるバグはなるべく直して、テストがありCIでもテストを動かしている。

Fix HTTPCookie.secure by xtyxtyx · Pull Request #311 · pichillilorenzo/flutter_inappwebview · GitHub

これはそのまま対応してある

NPE when window.prompt · Issue #261 · pichillilorenzo/flutter_inappwebview · GitHub

これはwindow.promptだけ起きることではないようで、使ってないページでも再現することがあった。つまり、時々ページを開くとアプリがクラッシュすることがある。

これの原因はAndroid WebViewを作るときにActivity contextを使っているから起きている。Presentation contextを使うと起きなくなるがPresentation contextを使うと以下の問題が起きる。

webview_flutter crash with HTML dropdown · Issue #34248 · flutter/flutter · GitHub

inappwebviewと違い、webview_flutterはAndroid WebViewをつくるときにPresentation contextを使っているのだが、Presentation contextを使っているとDropdownをタップするとアプリがクラッシュする。 inappwebviewのようにActivity contextを渡していると起きないのだが、すでに書いたようにページを開くと時々アプリがクラッシュすることがある。

これをどうにかするには、flutter/engine側の修正(Fix AlertDialogs built by platform views by amirh · Pull Request #17511 · flutter/engine · GitHub) がリリースされるのを待つか自分でContextをラップするしかない。native_webviewはContextをラップしたので現在のFlutter stableでも再現しない。

TypeError: Promise._immediateFn is not a function. · Issue #288 · pichillilorenzo/flutter_inappwebview · GitHub

これは、inappwebviewが自動でJavaScriptを実行しているゆえの問題でnative_webviewはJSを自動で読み込むことをほぼしないのでこういうことは起きない。またテストもCIで動かしているので起きたとしても多分わかる。

iOSの実機で一瞬画面が暗くなる

背景色が指定されていないのが原因

Androidの実機で一瞬画面が暗くなることがある

コメントによるとPlatformViewで使っているVirtualDisplayのバグっぽい。どうしようもないので、native_webviewではライブラリ側で対処するようにした。

google_maps_flutter I am getting black screen before loading maps · Issue #39797 · flutter/flutter · GitHub

Android V2 embedding対応

inappwebviewはAndroid V2 embeddingを使うとクラッシュする。native_webviewはAndroid V2 embedding対応している

Causes the app to crash on Android Emulator · Issue #327 · pichillilorenzo/flutter_inappwebview · GitHub

逆にいうとnative_webviewはV1にあえて対応してないので、V1を使ってるアプリはV2に移行しましょう。

native_webview のだめなところ

これはあえてそうしているのだけど、新しめのバージョンでしか動かない。

例えばAndroid 7以上でしか動かない。ぼくが作ってるアプリの要件がAndroid 7以上で、それ未満に対応する意味がないからというのとAndroidはOSのバージョンによってChromeに同梱されたWebViewが使われたり、Android WebView Systemが使われたりと実行環境が変わるので、なるべくそういう違いを少なくしたかった。(Android 10でまた変わったのだけど……)

また自分に必要な機能しかいれていないので、inappwebviewと比べるとまだまだ機能は少ない。JSに依存しないで実現できるものは、対応していく予定

まとめ

webview_flutter, flutter_inappwebviewと使ってきたが、結局自分で作り始めた。webview_flutterやinappwebviewのイシューを見ていると大変だな………という感じなのですが、まあがんばります。