当記事について
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.xml
にWRITE_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ピクセルの黒画像を用意するなどして、目立たないように表示すると良いかもしれません。
参考URL
- android-Bitmap.getWidth()でのnullポインタによるWebViewのクラッシュ-スタックオーバーフロー
- AndroidでWebViewを使うときはManifestに「WRITE_EXTERNAL_STORAGE」 | GROUP DEV BLOG | TECHNO MOBILE
- Bitmap.getWidth() on a null object reference at webview.getDefaultVideoPoster_Gdeer 的专栏-CSDN博客_getdefaultvideoposter
WebViewを長時間表示させるとメモリリークが発生する
事象
WebViewを長時間表示させるとメモリリークが発生します。
起動時間としては端末によりけりですが、だいたい8時間〜12時間弱で発生するようです。
原因
いまいちよくわかりませんが、WebViewのインスタンスを生成しただけでも発生するので、おそらくWebView側のインスタンス生成処理に問題があるようです。
解決策
今のところありません。。インスタンスを破棄しても発生するようです。。
試してはいませんが、代替可能ならChrome Custom Tabsを使用することで解決できるかもしれません。