LoginSignup
3
1

More than 3 years have passed since last update.

AndroidのWebViewでハマったポイントまとめ

Last updated at Posted at 2020-07-21

当記事について

WebViewは厄介な存在だと思います。
無数にあるWebページがちゃんと表示されるかが怪しいと感じる今日この頃。
あとはWebViewに限った話ではないですが、OSバージョンや端末によって起きたり起きなかったりするバグ。
当記事では、WebViewの実装で個人的にハマったポイントを随時更新していきます。

Android 6.0にて、動画コンテンツのあるURLを表示しようとするとクラッシュする

事象

Android 6.0にて、動画コンテンツのあるURLを表示しようとすると、以下のようにクラッシュします。

07-21 22:35:26.674 4770-4770/com.example.samplewebviewapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.samplewebviewapp, PID: 4770
    java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
        at com.android.webview.chromium.WebViewContentsClientAdapter.getDefaultVideoPoster(WebViewContentsClientAdapter.java:1208)
        at org.chromium.android_webview.DefaultVideoPosterRequestHandler$1.run(DefaultVideoPosterRequestHandler.java:39)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
07-21 22:35:26.779 4770-4811/com.example.samplewebviewapp E/eglCodecCommon: glUtilsParamSize: unknow param 0x000085b5

原因

HTML内部にvideoタグがあり、その中にposter属性という属性が存在します。
どうやらユーザー環境で利用できる動画が無い場合に表示させる画像を指定するようです。
<video>-HTML5タグリファレンス

この属性が指定されていない場合、WebChromeClient#getDefaultVideoPosterメソッドが呼ばれるのですが、その戻り値がnullであるために起きていました。

解決策

AndroidManifest.xmlWRITE_EXTERNAL_STORAGEを宣言する方法では解決できませんでした。
WebChromeClient#getDefaultVideoPosterメソッドをオーバーライドし、getDefaultVideoPosterメソッドがnullを返すようであれば、代わりの画像を返すように修正することでクラッシュしなくなりました。
ちなみに、BitmapFactory.decodeResourceメソッドの第2引数に指定するリソースIDですが、pngやjpegなどの画像ファイルを指定する必要があります。XMLで定義したリソースではnullとなってしまうので注意。

webView.webChromeClient = object : WebChromeClient() {
    override fun getDefaultVideoPoster(): Bitmap? {
        return if (super.getDefaultVideoPoster() == null) {
            BitmapFactory.decodeResource(applicationContext.resources, android.R.drawable.ic_media_play)
        } else {
            super.getDefaultVideoPoster()
        }
    }
}

結果としては以下の通り表示されますが、指定したリソースが画面に表示されてしまい、ブラウザで本来表示されている内容とは異なってきてしまいます。
ですので、1×1ピクセルの黒画像を用意するなどして、目立たないように表示すると良いかもしれません。

1.png

参考URL

WebViewを長時間表示させるとメモリリークが発生する

事象

WebViewを長時間表示させるとメモリリークが発生します。
起動時間としては端末によりけりですが、だいたい8時間〜12時間弱で発生するようです。

原因

いまいちよくわかりませんが、WebViewのインスタンスを生成しただけでも発生するので、おそらくWebView側のインスタンス生成処理に問題があるようです。

解決策

今のところありません。。インスタンスを破棄しても発生するようです。。
試してはいませんが、代替可能ならChrome Custom Tabsを使用することで解決できるかもしれません。

参考URL

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