android 2.3 webkit
来源:互联网 发布:mac比较好的杀毒软件 编辑:程序博客网 时间:2024/04/29 18:49
1. 前言
大家对WebView应该不陌生, 它是Android里面用来显示网页的控件, 用它显示网页只需要几行代码, 如下:
public class WebViewDemoActivity extendsActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.loadUrl("http://www.google.com");
}
}
这样在WebViewDemoActivity启动时就会显示出google的主页, 我们还可以在里面输入关键字进行搜索。究竟WebView的loadUrl函数里面究竟做了哪些事情呢?我们带着好奇心走进android的Webkit世界。
2. 加载网页过程的UML序列图
这里先给出loadUrl整个过程的uml序列图, 然后再慢慢分析。
3. WebKit介绍
前面提到了Webkit, 那究竟Webkit是什么呢?它和我们所熟悉的WebView是什么关系呢?这里引用网上的解释:“WebKit是一个开源的浏览器网页排版引擎,包含WebCore排版引擎和JSCore引擎。 WebCore和JSCore引擎来自于KDE项目的KHTML和KJS开源项目。Android平台的Web引擎框架采用了WebKit项目中的WebCore和JSCore部分,上层由Java语言封装,并且作为API提供给Android应用开发者,而底层使用WebKit核心库(WebCore和JSCore)进行网页排版。”可见, WebView就属于Android的Webkit提供给应用开发者用的上层API部分。
很多伟大的软件都是可移植的, Webkit也不例外。 目前Webkit支持Qt, Gtk, Android等等。 大家都知道移植是有条件的,比如要将linux系统移植到某个硬件平台, 那么这个硬件平台至少要有个硬件定时器来进行进程调度,要有mmu来支持虚拟内存管理,另外对系统ram和flash的空间也是有一定底线要求的。移植Webkit所要求的条件是什么呢?先分析Webkit加载网页的这样一个过程:
l 从网络上把url地址上的html文件下载到本地
l 词法分析和语法分析
l 绘制
很明显, Webkit需要依赖平台相关的网络接口和图形接口, 如下图所示:
可移植的软件都可以分为两部分:平台相关代码和平台无关代码。 这两部分之间的交互是通过固定接口来完成的,当然Webkit也不例外。对于Android Webkit, 我们把它简单看为两部分:Android和WebCore。 Android到Webcore方向当然是直接调用的关系, 而WebCore有时也需要回调Android部分的代码, 这就需要通过WebCore定义的一套固定的接口来完成。如下图所示, ResourceHandle是WebCore获取网络资源的接口, Android平台对这个接口的实现是调用了Android API中的android.net.*包里面的类实现的。 GraphicContext是WebCore绘制页面的接口, Android平台对这个接口的实现是通过调用Android平台的2D绘图引擎Skia实现的。
4. 加载网页过程分析
有一个很重要的概念需要解释一下, Frame, 翻译成中文是“帧”, 一个html页面构成如下图,即一个html页面包含一个MainFrame, MainFrame中又可以包含0到n个子Frame。一个Frame对应一个Url, 在MainFrame里包含子Frame就意味着把子Frame的内容嵌入到MainFrame的一块空间里面。
在WebKit里面有个结构体WebCore::Frame, 这个数据结构就包含了, 一个网页解析后的全部数据。下面就是从一个Url到生成一个MainFrame的过程。
接下来就是要将Main frame里面的数据显示出来, 这部分代码是每个平台的实现都是不同的,我们以Android为例。 首先需要说明的是, Android Webkit加载网页是通过三个线程协作完成的:
l UI线程:Android图形系统派发事件的线程, WebView的onDraw函数和onTouchEvent函数就是运行在这个线程。UI线程只做一些轻量级的工作, 会将耗时的工作转给Webcore线程进行处理。
l WebCore线程:在andriod.webkit.WebViewCore类中创建, 负责html文件解析等任务。
l 下载线程:在android.webkit.WebViewWorker中创建,负责下载从指定url下载html。
当调用WebView.loadUrl时线程协作图如下, UI线程向WebCore线程发送消息, WebCore线程接到消息会把下载任务交给下载线程, 下载线程下载完毕后通知WebCore线程进行html的解析, WebCore线程解析完html后通知UI线程刷新界面。
回顾一下这个图:
Webcore线程就是通过ResourceHandleAndroid来启动下载线程下载html的, 然后WebCore线程进行html解析, 最后生成能够描述整个html页面的Main frame,再通知UI线程绘制页面。假设UI线程在onDraw函数里需要通过分析 Mainframe来绘图, 那么很可能给人不流畅的感觉。所以WebCore线程在生成Frame结构体之后, 又做了一个工作, 就是解析Main frame并绘制到一块内存上面, 而UI线程在onDraw时只需把这块内存上的内容绘制到屏幕上即可, 这块内存叫PictureSet。Picture是一个图片集合, Main frame是Frame的集合,PictureSet里面的Picture和Main frame里面得Frame都是一一对应的关系。
还记得以前提到的代码层次吗?PictureSet是属于Webkit的Andriod移植层的, 而Frame是属于WebCore层的, 也就是说WebCore生成Frame后任务就完成了, 然后会通过固定的接口通知Android移植层, Android移植层随后分析Frame来生成PictureSet。在PictureSet生成后才会通知UI线程更新界面, WebView.onDraw中便会将PictureSet绘制到画布上。
最后需要补充说明的是, Android的Webkit移植层比其它平台相比多了jni部分, 通过阅读代码你会发现WebView, WebViewCore等类在Java和C++部分都存在,它们是通过Java和c++一起实现的。
5. Android Webkit插件
5.1. 本章的目的
引导读者理解Android Webkit的插件框架, 通过介绍本人研究过程阅读过并认为有价值的文章,并对Android Framework源码中的SampleBrowserPlugin里难懂的地方进行解释, 希望能够清除读者对怎样写Android Webkit插件的疑惑。 SampleBrowserPlugin 是Android Webkit插件的例程, 位于源码中的development/samples/BrowserPlugin目录下, 先看一下里面的README文件吧。
5.2. 推荐先看几篇文章
l https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:虽然firefox是gecko的引擎,但是gecko和webkit的插件同样遵循NPAPI的标准, 这篇看完后就会弄如下几个问题:
(1)什么是Webkit插件, 有什么作用
(2)NPAPI一些函数和结构的作用。
l http://blog.csdn.net/ownerwu/archive/2011/05/18/6429072.aspx:这篇文章会帮助你对Android Webkit插件有个简单的了解。
l http://blog.csdn.net/qyqzj/archive/2010/06/14/5670816.aspx:这篇文章提到了Android Webkit插件的两种模式。
5.3. 架构
插件是用来扩展webkit的, 是webkit的智囊团。 例如有一种新类型的数据嵌在网页里,如下图所示, webkit不知如何处理, 此时webkit就会问他的插件们如何处理"application/x-shockwave-flash”类型的数据。
<embed src="http://player.youku.com/player.php/Type/Folder/Fid/13005645/Ob/1/Pt/0/sid/XMzAxNDEwMTY4/v.swf"
quality="high"
width="480"
height="400"
align="middle"
allowScriptAccess="always"
allowFullScreen="true"
mode="transparent"
type="application/x-shockwave-flash">
</embed>
webkit写在先, 插件产生再后。 Webkit的设计者写基类, 插件编写者写子类来实现基类的虚函数。 同时,webkit也提供api供插件的子类调用。这样解释来看, 架构和Android Framework的思想一致, 插件系统的控制点在webkit (framework)。
上图的NPPluginFuncs是插件必须要实现的接口, 而如果你的插件要扩展浏览器规定的接口, 向通过网页中的javascript脚本调用到插件的函数, 就需要继承NPClass来做扩展。下面代码示范如何在网页中调用插件的扩展接口:
1. <embed type="application/plugin-mimetype">
2. <script>
3. var embed = document.embeds[0];
4. embed.nativeMethod();
5. alert(embed.nativeProperty);
6. embed.nativeProperty.anotherNativeMethod();
7. </script>
5.14. 编译安装SampleBrowserPlugin
l 进入android源码顶层目录运行:make SampleBrowserPlugin
会生成out/target/product/generic/data/app/SampleBrowserPlugin.apk
l 开启模拟器(模拟器创建时需要添加sdcard支持)
l 运行adb install “path to SampleBrowserPlugin.apk”
5.15. 运行例程
l 写个s.html文件内容如下:
<objecttype="application/x-testbrowserplugin" height=50 width=250>
<param name="DrawingModel"value="Surface" />
<param name="PluginType"value="Background" />
</object>
l 运行adb push “path to s.html” /mnt/sdcard
l 在模拟器中启动Browser程序, 在地址栏输入:file:///mnt/sdcard/s.html或file:///sdcard/s.html,结果如下图说明浏览器正确加载运行了插件。
5.16. SampleBrowserPlugin.apk里面包含了什么
l libsampleplugin.so: NPAPI中plugin方的实现, 会安装到/data/data/com.android.sampleplugin/lib目录下。
l 一些配合libsampleplugin.so工作的java class。
l 一个“莫名其妙”的Service。
为什么说它“莫名其妙”?让我们看看SamplePlugin.java的内容:
public class SamplePluginextendsService {
@Override
public IBinder onBind(Intentintent) {
// TODO Auto-generated method stub
return null;
}
}
初看觉得写代码的人是在开玩笑吧, 这样的Service能有什么用呢? 再看这个Service在AndroidManifest.xml里的描述:
<service android:name=".SamplePlugin">
<intent-filter>
<action android:name="android.webkit.PLUGIN" />
</intent-filter>
<meta-data android:name="type" android:value="native"/>
</service>
不过没有这个Service, 现在有点启发了吗?试想一下Webkit是怎样知道这个插件的存在的呢?
Webkit是通过PackageManager查询系统中能够响应android.webkit.PLUGIN的Service来得到插件安装的路径的。
5.17. 对Surface模式和Bitmap模式的理解
l Surface模式:如果plugin要绘制的内容是动态的就需要在单独的surface上绘图。
l Bitmap模式:Webkit为Plugin提供绘图的Bitmap, Plugin在上面绘图后Webkit再把Bitmap 的内容绘制到WebView所在的Surface上面。
5.18. 具体分析
百闻不如一见, 去看SampleBrowserPlugin的代码吧, 结合上面提到的文档, 条理就会很清晰。
- android 2.3 webkit
- Android 2.3 Webkit
- android webKit
- android WebKit
- Webkit Android
- android webkit
- Android WebKit
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- WebKit – WebKit For Android
- 网游服务器的安全和稳定性
- android 按钮按下效果3
- 《设计模式解析》第5章 设计模式简介 复习题
- oracle 缓存表
- 中文验证码,用C#生成随机中文汉字验证码的基本原理
- android 2.3 webkit
- C调用汇编
- 程序员每天该做的事
- PyCharm
- google Snappy
- 验证码相关资料
- curl应用总结(一)
- 暗恋,一种美丽的痛
- 使用 Spring 2.5 基于注解驱动的 Spring MVC