Bitmap.getWidth() on a null object reference at webview.getDefaultVideoPoster
分析
遇到这样一个 bug:
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:657)
at org.chromium.android_webview.DefaultVideoPosterRequestHandler$$Lambda$0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
分析:
从 log 看出和 getDefaultVideoPoster 方法有关,查看
WebChromeClient.getDefaultVideoPoster:
/**
* When not playing, video elements are represented by a 'poster' image. The
* image to use can be specified by the poster attribute of the video tag in
* HTML. If the attribute is absent, then a default poster will be used. This
* method allows the ChromeClient to provide that default image.
*
* @return Bitmap The image to use as a default poster, or null if no such image is
* available.
*/
public Bitmap getDefaultVideoPoster() {
return null;
}
按注释所述,当 WebView 显示视频时,如果 <video> tag 中没有 poster 属性,该方法就会调用,显示一个默认占位图。该方法默认返回 null,如果没有重写,调用时获取到的就是 null,再直接调用 bitmap.getWidth(),就会产生空指针。
解决方案:
重写 WebChromeClient:
// 视频未播放时的默认图
public Bitmap getDefaultVideoPoster() {
if (mClient.getDefaultVideoPoster() == null) {
return BitmapFactory.decodeResource(ODApplication.getODApp().getResources(), R.drawable.ic_shortcut);
} else {
return mClient.getDefaultVideoPoster();
}
}
参考链接
https://bugs.chromium.org/p/chromium/issues/detail?id=521753#c8
https://blog.****.net/SCHOLAR_II/article/details/81330403
验证:
使用(小米mix2,8.0)、(华为mate20,9.0)、(vivo X7 plus,5.1.1) 验证,效果相同。
查看有 poster 属性的 html 显示
<html>
<body>
<video src="https://qiniu-video9.vmoviercdn.com/5c91f3027033b.mp4" controls="controls"
poster="http://img.zcool.cn/community/[email protected]_1l_2o_100sh.jpg">
</video>
</body>
</html>
这样一个 html,在 chrome 上可以看到 poster:
在手机 WebView 上也能看到:
当不设 poster,即
<html>
<body>
<video src="https://qiniu-video9.vmoviercdn.com/5c91f3027033b.mp4" controls="controls">
</video>
</body>
</html>
这样一个 html,在 chrome 上可以看到显示视频的第一帧:
在手机 WebView 上看到的一个播放按钮:
两种情况下 getDefaultVideoPoster 都没有调到。所以,无法验证问题是否解决。????