170 result) { bool ret = false; char* js_script = new char[evaScript->UTF8Length+1]; memcpy(js_script, evaScript->UTF8Characters, evaScript->UTF8Length); 175 js_script[evaScript->UTF8Length] = 0; if(strstr(js_script, "document.readyState")) { const char* s_complete = "complete"; 180 result->type = NPVariantType_String; result->value.stringValue.UTF8Characters = strdup(s_complete); result->value.stringValue.UTF8Length = strlen(s_complete); ret = true; } 185 delete[] js_script; return ret; } 由于本研究的目标是实现一个轻量级的插件加载器,因此,加载器NPN 函数的实现原 则就是,在保证可用性的前提下,尽可能地简单。 190 3.2 ANPInterface 的实现 NPN_GetValue 是一个多用途的函数,除了获取浏览器的环境参数以及html 文档对象以 外,Android 的NPN_GetValue 还必须提供一些Android 系统特有的数据结构,那就是 ANPInterface。 ANPInterface 是浏览器提供给插件的一些Android 平台特有的APIs 主要有以下几个: 195 表2 ANPInterface 说明 Tab. 2 Introduction of ANPInterface ANPInterface NPN_GetValue 传入的NPNVariable 说明 LogInterface kLogInterfaceV0_ANPGetValue 日志接口 AudioTrackInterface kAudioTrackInterfaceV0_ANPGetValue 音频接口 CanvasInterface kCanvasInterfaceV0_ANPGetValue Canvas 绘制接口 MatrixInterface kMatrixInterfaceV0_ANPGetValue 矩阵接口,绘制辅助 PaintInterface kPaintInterfaceV0_ANPGetValue 画笔接口,绘制辅助 PathInterface kPathInterfaceV0_ANPGetValue 路径接口,绘制辅助 TypefaceInterface kTypefaceInterfaceV0_ANPGetValue 字体接口,绘制辅助 WindowInterface kWindowInterfaceV0_ANPGetValue 窗口控制接口 BitmapInterface kBitmapInterfaceV0_ANPGetValue 提供Bitmap 格式索引 SurfaceInterface kSurfaceInterfaceV0_ANPGetValue Surface 控制接口 SystemInterface kSystemInterfaceV0_ANPGetValue 系统接口,提供程序目录和Java 类的 获取 EventInterface kEventInterfaceV0_ANPGetValue 事件接口,提供消息队列功能 Webkit 的源码中有ANPInterface 相关实现,其中大部分代码都可以直接搬到加载器中 使用,只有WindowInterface、SystemInterface 和EventInterface,这三类接口的原版代码实 200 现依赖于Webkit,因此需要重新实现。 例如,对于SystemInterface 中的getApplicationDataDirectory,可以这样实现: static char* appDir = NULL; static const char* anp_getApplicationDataDirectory() { if(appDir == NULL) 205 appDir = getAppDirFromJava(); return appDir; } 其中getAppDirFromJava()方法需要实现回调Java 获取应用程序目录的功能。由于这部 分涉及JNI 开发的相关知识,不在本文所讨论的范畴,同时由于篇幅所限,故不在此作详细 210 介绍。 3.3 插件加载流程 在保证了NPN 函数和ANPInterface 的实现以后,就可以通过NPP 调用实现插件的加载, 对插件的调用需要按照如下顺序进行: (1) 加载插件动态库,获取动态库的公共静态函数入口NP_xxx; 215 (2) 调用NP_Initialzie,初始化插件。在这一步,加载器会把NPN 函数表提供给插件, 插件也会把NPP 函数表返回给加载器。另外,Android 的NP_Initialzie 还需要传入 JNI 的结构体JNIEnv,供插件使用。 (3) 调用NPP_New,实例化插件。这一步需要传入一些插件控制参数,这些参数通常 是由插件定义的。 220 (4) 调用NPP_SetWindow,告知插件实例的显示范围。 (5) 如果插件是使用Surface 模式进行渲染的(例如Flash Player),调用NPP_GetValue (NPPVariable == kJavaSurface_ANPGetValue)得到插件的SurfaceView 实例,回传 到Java 侧,添加到显示画面中。如果是插件是使用Bitmap 模式进行渲染的,在每 当插件调用NPN_InvalidateRect 之后,都需要通过NPP_HandleEvent 发送Draw 事 225 件,通知插件重绘。 (6) 通过NPP_HandleEvent 向插件发送kOnLoad_ANPLifecycleAction 事件。 (7) 如果有附带数据(例如Flash Player 中的SWF 文件),依次调用NPP_NewStream、 NPP_Write、NPP_DestroyStream,把数据以数据流的方式传给插件。 在上述过程中,插件会调用一些NPN 或者ANPInterface 提供的接口,以完成自身的初 230 始化,如果加载器提供的这些接口都能向插件提供正确的返回值,那完成上述步骤以后,插 件能运行起来。 在插件运行过程中,如果要传入按键、鼠标、触控、绘制等事件,可以生成相应类型的 ANPEvent 实例,并调用NPP_HandleEvent 方法,把ANPEvent 传给插件,实现插件的控制。 当要销毁插件的时候,依次调用下列方法: 235 (1) 调用NPP_HandleEvent 向插件发送kPause_ANPLifecycleAction 事件。 (2) 调用NPP_SetWindow 把插件显示范围置零。 (3) 调用NPP_Destory 销毁插件实例。 (4) 如果所有插件实例已经销毁,调用NPP_Shutdown 关闭插件。 在保证NPN 和ANPInterface 实现的准确性,并实现了上述调用控制之后,就可以建立 240 一进行个不依赖于系统浏览器的轻量级插件加载器,实现简单的插件加载。 4 结论 本文基于Android 浏览器插件的基本工作原理,提出了一种不依赖浏览器,直接对插件 进行加载的轻量级解决方案。种方法可以实现对诸如Flash Player 一类的插件的加载,并把 插件的显示内容嵌入到程序中。在移动平台浏览器插件领域的相关研究匮乏的现在,本文的 245 研究具有一定的实用意义。 本文所提出的方法,以实现基本功能为前提,对接口作了尽可能的简化,如果对NPN 函数进行更为完善的实现,将可以支持更丰富的插件功能,例如网络访问、对外调用等等。 因此这种方案具有很强的可扩展性。 5 致谢 250 衷心感谢陈建亚教授和王振凯副教授,在课题研究的过程中所给予的指导。陈建亚老师 丰富的理论知识和严谨的治学态度,让我受益匪浅;王振凯老师在前沿技术上的敏锐触觉, 以及丰富的开发实践经验,让我敬佩不已,王老师在课题研究上的指导也让我受益良多。此 外,还要感谢实验室的李增辉前辈和宁栗前辈,他们对我在浏览器插件上的研究,给予了很 大的帮助。感谢实验室所提供的开发环境和设备,让本课题研究得以顺利进行。 255 [参考文献] (References) [1] 韩超,梁泉. Android 系统原理及开发要点详解[M]. 北京:电子工业出版社,2010. [2] 陈璟,陈平华,李文亮. Android 内核分析[J]. 现代计算机(专业版). 2009,319(11): 112-115. [3] 杨丰盛. ANDROID 应用开发揭秘[M]. 北京:机械工业出版社,2010. 260 [4] 杨文志. Google Android 程序设计指南[M]. 北京: 电子工业出版社,2009. [5] 公磊,周聪. 基于Android 的移动终端应用程序开发与研究[J]. 2008,(8):85-89. [6] 汪诗林,吴泉源. WWW 浏览器插件开发技术[J]. 计算机应用研究,2000,(4): 55-57. 原创学术论文网Tag:代发论文 论文发表 代写毕业论文 代写经济论文 代写毕业设计 计算机论文 |