Android KitKat一项重要的更新就是WebView采用Chromium/Blink渲染引擎,本文简要的叙述了新版WebView的主要特性、需要进一步改进的地方以及WebView的代码结构等。
WebView前世今生
WebView是Android平台上一个非常重要的系统组件,用于将一个显示Web页面的窗口部件view嵌入到应用程序,并提供了一组API接口允许开发者定制页面加载和绘制的行为,比如响应页面加载状态的变化和弹出JavaScript对话框的请求等等。自Android 1.0发布以来,WebView被广泛地使用在应用程序中,最典型的当属Stock浏览器了,它就是基于WebView开发的一个浏览器程序。关于详尽的文档描述,请参看WebView的官方文档。
早期的WebView (在Android 4.4以前)是基于WebKit实现的,可以简单理解为直接在WebKit代码库中增加一个分支,解决Android平台特定的页面渲染方式以及通过JNI接口将WebKit的功能桥接为Java层的API接口。在图形方面,WebView和Android平台一样,采用的是Skia图形库,但没有启用硬件加速,渲染性能非常不好,这也是许多使用者经常抱怨的诟病之一。
随着Android 4.4 (KitKat) 平台的发布,基于Chromium开源项目的WebView成为KitKat平台的一大亮点。新版WebView采用了与Chrome浏览器相同的Blink渲染引擎,v8 JavaScript引擎,网络库以及内存分配器,在HTML5特性支持方面不仅与Chrome保持了更高的一致性,而且还弥补了旧版WebView在渲染性能方面的不足。Android平台上所有使用WebView的应用程序都将无缝透明地受益于新版WebView的特性支持和性能提升。
目前,Android KitKat上的WebView是基于Chromium 30.0.0.0,而Chromium开源项目一直以6周一次的迭代周期在快速演进,Google官方并没有给出一个明确的计划什么时候以什么方式升级WebView组件,也许是通过GMS,但尽管如此,就目前的情形来看,新版WebView只能在Android 4.4系统上使用。这就意味着目前市面大量Android 4.3或以前的设备都不能使用新版的WebView,享用不到新版WebView引入的好处。为什么其他非4.4的设备上不能使用呢?原因主要是Chromium WebView必须与AOSP (Android Open Source Project) 源代码一起才能编译,不能单独从Chromium的代码库中编译一个可以独立安装的软件包。
主要特性
支持更多的HTML5特性,例如Web Socket, Web Worker, FileSystem API, Page Visibility API, CSSfilter等等。html5test.com跑分结果为448分,与Chrome浏览器非常接近了。
添加了对远程调试功能的支持。任何使用WebView的应用程序默认都开启了远程调试功能,通过USB线连接到开发主机上,在主机的Chrome浏览器中输入chrome://inspect就可以直接在开发主机上直接调试WebView加载的页面。开发者也可以调用 setWebContentsDebuggingEnabled开启或关闭这个功能。这对广大HTML5应用开发者绝对是一个福音。
更智能的内存管理策略。旧版WebView需要应用程序在系统内存不足的情况下,显式地调用freeMemory方法来释放WebView占用的内存资源,。而新版的 WebView中,freeMemory这个方法已经被标记为“deprecated”,也就是应用程序不需要自己去释放内存,WebView的内部实现已经考虑了对系统低内存运行时的响应,一旦发现系统处于低内存的运行状态,WebView会主动调整内存分配策略,尽可能释放一些已占用的内存资源。
支持软件渲染和硬件加速模式。Android应用程序可以在manifest文件中指定hardwareAccelerated的值表明是否启动硬件加速,为了兼容早期使用WebView的应用程序,新版WebView同时支持软件渲染和硬件渲染两种模式。
不足之处
尚有一些重量级的HTML5特性没有支持,比如WebGL,WebRTC,其中原因是WebGL对图形显卡的要求很高,而目前市面上每个厂商的硬件能力不尽相同,所有激进地开启WebGL的支持可能会导致平台的一致性问题,即同一个HTML5应用在不同的设备上行不一致,有的能跑,有的挂掉。
尚有一些轻量级但实用的HTML5 API还不支持。典型的有两个,一个是全屏Fullscreen API,另外一个是Network Information API.
Canvas 2D没有开启硬件加速模式。Canvas2D的性能和Chrome浏览器还是有一定差距,从代码注释来看,是因为skia库中硬件加速的Canvas 2D后端Ganesh可能会导致WebView崩溃。
硬件加速渲染模式下所有对GPU的操作都发生在主线程中。UI主线程实在是太忙,如果能和Chrome一样,专门为GPU操作创建一个线程,性能还可得到进一步提升。
更新:最新的Chromium WebView,已经添加了WebGL,WebRTC以及加速Canvas 2D的支持了。
代码结构
确切地说,在AOSP中WebView是由三部分代码组成:
Chromium代码:包含在external/chromium_org目录中,其中android_webview/目录包含了WebView的内部实现代码和对应的Java类包;
Java桥接代码:包含在framework/webview/java目录中,提供了基于Chromium的WebViewProvider实现类WebViewChromium,这个类将被Android系统动态加载后作为android.webkit.WebView的内部实现;
Android平台支持代码:这部分代码量少但至关重要。在硬件加速模式下,WebView必须能够直接访问Android系统的显存以及对HardwareCanvas执行GL操作,而访问显存和对HardwareCanvas的操作没有相应的SDK或NDK的支持,只能直接调用AOSP代码。这也是前面提到的WebView必须和AOSP一起编译的原因。
从AOSP中编译WebView
如果编译一个完整版的WebView,需要先要下载整个AOSP的代码,运行source build/envsetup.sh和lunch <target>命令后,进入framework/webview目录执行mm –j8编译WebView模块,最后在out目前将会得到libchromiumwebview.so和libwebkit_plat_support.so两个动态链接库,将这两个so文件拷贝到目标设备的/system/lib目录下,重启设备后就可以使用你自己编译的WebView了。
从Chromium中编译WebView
实际上,也从直接从Chromium代码库中编译WebView,但这个WebView并不是一个完整的WebView。前面说到,WebView还包括了Android平台支撑代码,而Chromium代码库并没有包含这部分代码,所以编译出来的WebView只有纯软件的渲染模式。因此,它对帮助验证一个WebView功能性方面的问题还有有用的,对于优化渲染性能只能从AOSP编译了。
根据chromium.org官方文档,下载chromium代码库,配置好环境后运行:
$ . build/android/envsetup.sh
$ android_gyp
$ ninja –C out/Release android_webview_apk
编译成功后,在out/Release/apks目录中会有一个名为AndroidWebView.apk的文件生成,它是一个Shell程序,提供了一个简单的UI,方便开发者验证WebView的核心功能,但AndroieWebView.apk并没有直接使用android.webkit.WebView,而是基于WebView的核心类AwContents实现的,查看manifest文件你会发现它将android:hardwareAccelerated设置为false了,也就是说应用程序没有开启硬件加速,相应地WebView也只是工作在软件渲染模式下。如果强制把android:hardwareAccelerated设置为true,这个Shell程序则不能正常显示网页了,这是意料之中的,硬件加速渲染模式必须要与AOSP一起编译才会有。
参考资源
[1] WebView SDK,http://developer.android.com/reference/android/webkit/WebView.html
[2] Web程序的迁移,http://developer.android.com/guide/webapps/migrating.html
[3] WebView for Android, https://developers.google.com/chrome/mobile/docs/webview
[4] 远程调试 for Android, https://developers.google.com/chrome-developer-tools/docs/remote-debugging
[5] Android上编译Chromium, https://code.google.com/p/chromium/wiki/AndroidBuildInstructions