1 / 32

第十一章 Android 浏览器扩展

第十一章 Android 浏览器扩展. 本章主要内容. NPAPI 简介. Netscape Plugin Application Programming Interface 是一个被许多浏览器遵循和采用的跨平台的插件框架。 NPAPI 的接口分为两组:浏览器侧的 NPN 接口和插件侧的 NPP 接口。 浏览器插件的核心,就是一个实现了 NPP 接口,并使用浏览器提供的 NPN APIs 进行对外操作的动态库。. NPAPI 简介.

astra
Télécharger la présentation

第十一章 Android 浏览器扩展

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十一章 Android浏览器扩展

  2. 本章主要内容

  3. NPAPI简介 • Netscape Plugin Application Programming Interface是一个被许多浏览器遵循和采用的跨平台的插件框架。 • NPAPI的接口分为两组:浏览器侧的 NPN 接口和插件侧的 NPP 接口。 • 浏览器插件的核心,就是一个实现了 NPP 接口,并使用浏览器提供的 NPN APIs 进行对外操作的动态库。

  4. NPAPI简介 • Android 浏览器插件特有的结构:插件的 Java 层。这样,浏览器插件就可以作为一个Android应用,通过常规途径安装到Android设备中。(Android的所有应用都必须通过Java 部分实现安装)

  5. Android中的浏览器插件开发分析 BrowserPlugin • Android的源码目录下提供了Plugin的范例: development/samples/BrowserPlugin; • 通过这个版本的例子编译生成的是完整的apk安装包,可以在模拟器或者真机上安装测试。

  6. Android中的浏览器插件开发分析 BrowserPlugin结构 • jni目录是插件的主体,Native C/C++写的Shared Library,负责NPAPI中NPP侧的实现。下有5种子插件目录(animation,audio,background,form,paint), Android.mk文件(Make文件) ,hello-jni.cpp文件 (注册java本地接口,hello-world函数,测试用),jni-bridge.cpp文件(注册java本地接口,注册的函数在SamplePluginStub.java中调用) ,main.cpp文件(实现NPP接口) ,main.h文件(定义 NPP接口变量) ,PluginObject.cpp文件(插件的基类),PluginObject.h文件 。

  7. Android中的浏览器插件开发分析 jni目录静态结构

  8. Android中的浏览器插件开发分析 jni目录静态结构

  9. Android中的浏览器插件开发分析 BrowserPlugin结构 • res目录,和一般的android工程一样,存放资源的目录。 • src目录下有实现了一个android的service类(其他大部分插件是实现activity类),并为插件提供绘制接口;有SamplePluginStub.java、SamplePlugin.java: 实现服务接口、Cube.java、CubeRenderer.java文件。 • AndroidManifest.xml,同样是每个android的工程都会有文件,包含了apk的注册信息,就在这里实现plugin的注册。 • Android.mk,编译配置文件。

  10. Android中的浏览器插件开发分析 NPP APIs • NPErrorNPP_New(NPMIMETypepluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); • 新建一个实例,浏览器每创建一个plugin的实例就会调用一次这个函数。通过NPN_SetValue告知浏览器plugin对象的一些特性,其中包括了plugin对象能处理的事件(触控事件和按键事件),以及plugin的渲染模式(bitmap模式或surface模式)。

  11. Android中的浏览器插件开发分析 NPP APIs • NPErrorNPP_Destroy(NPP instance, NPSavedData** save); • 当浏览器需要销毁一个plugin实例的时候调用,要在这里完成对应实例的资源释放。 • NPErrorNPP_SetWindow(NPP instance, NPWindow* window); • 浏览器通过该函数告知plugin对象其窗口参数,主要就是的plugin对象所占画面的大小。

  12. Android中的浏览器插件开发分析 NPP APIs • NPErrorNPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBoolseekable, uint16* stype); • 如果需要向plugin传输一些流数据,浏览器会通过此函数告知plugin即将要传输的流,在参数NPStream* stream中包含了流的url,以后需要对根据此url对NPP_Write传入的数据进行区分。

  13. Android中的浏览器插件开发分析 NPP APIs • NPErrorNPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); • 如果数据流传输结束或意外终止了,浏览器会调用此函数告知plugin注销这一数据流,可以通过NPReason reason判断数据流是否为正常结束。 • int32 NPP_WriteReady(NPP instance, NPStream* stream); • 浏览器在给plugin对象传输流数据前,会先调用这一函数询问plugin能接收的数据长度。

  14. Android中的浏览器插件开发分析 NPP APIs • int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len,void* buffer); • 流数据的传输,根据 NPStream* stream里的url可以判断是哪个数据流,int32_t offset为void* buffer这段数据在数据流中的偏移量,int32_t len为void* buffer的长度,返回值是plugin对象实际接收的数据大小。 • void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); • 如果浏览器要传输的是本地文件流,则会选择调用这个参数通知plugin流的信息。

  15. Android中的浏览器插件开发分析 NPP APIs • void NPP_Print(NPP instance, NPPrint* platformPrint); • 根据NPAPI的定义,浏览器会通过这个函数通知plugin进行输出操作。 • int16 NPP_HandleEvent(NPP instance, void* event); • 事件处理函数,在这里plugin要完成各种事件的处理,包括绘制、按键、鼠标、触控等等,事件的参数都包装在void* event里,可以参照external/webkit/WebKit/android/plugins/android_npapi.h中ANPEvent结构体的定义。

  16. Android中的浏览器插件开发分析 NPP APIs • void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData); • 如果plugin调用了NPN_GetURLNotify或者NPN_PostURLNotify,在浏览器侧的操作完成了以后,就会调用这个函数返回一些信息。

  17. Android中的浏览器插件开发分析 NPP APIs • NPErrorNPP_GetValue(NPP instance, NPPVariable variable, void *value); • 浏览器通过此函数获取plugin对象的一些参数,需要根据NPPVariable variable进行不同的处理,NPPVariable的定义可以参照external/webkit/Webcore/bridge/npapi.h和external/webkit/WebKit/android/plugins/android_npapi.h。 • NPErrorNPP_SetValue(NPP instance, NPNVariable variable, void *value);

  18. Android中的浏览器插件开发分析 NPP APIs • NPErrorNPP_SetValue(NPP instance, NPNVariable variable, void *value); • 浏览器通过此函数设置plugin对象的一些参数,和NPP_GetValue一样,需要根据NPPVariable variable进行不同的处理,NPPVariable的定义可以参照external/webkit/Webcore/bridge/npapi.h和external/webkit/WebKit/android/plugins/android_npapi.h。

  19. Android中的浏览器插件开发分析 • ANPInterface • 为了弥补NPAPI在Android上的不足,Google在Android的浏览器上实现了ANPInterface这么一个东西。就是一系列的操作接口(函数),提供了一些NPAPI没有的东西。插件可以在初始化的时候获取这些ANPXXXInterface,并在运行过程中使用。 • 其实ANPInterface提供的接口,大多来自webkit的一些底层库(external/webkit/WebKit/android/plugins) • BrowserPlugin中的ANPInterface列表如下:

  20. Android中的浏览器插件开发分析 • ANPInterface • ANPAudioTrackInterfaceV0 gSoundI; • ANPBitmapInterfaceV0 gBitmapI; • ANPCanvasInterfaceV0 gCanvasI; • ANPLogInterfaceV0 gLogI; • ANPPaintInterfaceV0 gPaintI; • ANPPathInterfaceV0 gPathI; • ANPSurfaceInterfaceV0 gSurfaceI; • ANPSystemInterfaceV0 gSystemI; • ANPTypefaceInterfaceV0 gTypefaceI; • ANPWindowInterfaceV0 gWindowI;

  21. Android中的浏览器插件开发分析 NP_Initialize • Plugin初始化函数,浏览器会通过参数传进一个浏览器侧的NPAPI函数列表(NPN函数列表),plugin需要在这里实现全局参数的初始化,并返回plugin侧的NPAPI函数列表(NPP函数列表)。Android的Plugin可以通过NPN_GetValue获取浏览器参数以及Android提供的各种操作接口(ANP Inerface),Android提供的操作接口可以查看源代码的这一部分:external/webkit/WebKit/android/plugins。Android的NP_Initialize还提供了上层的java运行环境,可用于实现与java侧的交互。

  22. Android中的浏览器插件开发分析 NP_Shutdown • 关闭Plugin,浏览器在销毁了所有plugin实例以后就会调用这个函数,可以在这里释放一些全局的资源。

  23. Android中的浏览器插件开发分析 • 编译BrowserPlugin • 修改jni/main.cpp文件之后编译(主要是增加LOGCAT调试信息),以方便后面分析插件加载流程。 • 进入源码根目录下 • 运行make SampleBrowserPlugin

  24. Android中的浏览器插件开发分析 • 安装BrowserPlugin • 运行 “adb install [apk_file]” ,把编译好的插件apk安装到设备或模拟器中 • 安装成功后,你可以通过“Settings -> Applications -> Manage applications”管理插件 • 用包含以下内容的HTML页面测试浏览器插件 <object type="application/x-testbrowserplugin" height=50 width=250> <param name="DrawingModel" value="Surface" /> <param name="PluginType" value="Background" /> </object>

  25. Android中的浏览器插件开发分析 • 运行测试 • 用浏览器打开测试网页,将会打印类似以下log: • D/plugin ( 366): *** NP_Initialize *** • D/plugin ( 366): *** 0x420f18 START NPP_New *** • D/plugin ( 366): ------ 0x420f18 DrawingModel is 1 • D/plugin ( 366): Application data dir is /data/data/com.android.browser/app_plugins • E/plugin ( 366): ------ 0x420f18 Testing Log Error • W/plugin ( 366): ------ 0x420f18 Testing Log Warning • D/plugin ( 366): ------ 0x420f18 Testing Log Debug • D/plugin ( 366): pixel format [0] unknown has no packing • D/plugin ( 366): pixel format [1] 8888 has packing ARGB [24 8] [0 8] [8 8] [16 8] • D/plugin ( 366): pixel format [2] 565 has packing ARGB [0 0] [11 5] [5 6] [0 5] • D/plugin ( 366): ------ 0x420f18 Testing DOM Access • D/plugin ( 366): ------ 0x420f18 Testing JavaScript Access • E/plugin ( 366): ------ 0x420f18 Invalid Variant type for JS Return: 4,3 • D/plugin ( 366): ------ 0x420f18 PluginType is 3 • D/plugin ( 366): *** 0x420f18 END NPP_New *** • D/plugin ( 366): *** 0x312a10 START NPP_New *** • D/plugin ( 366): ------ 0x312a10 DrawingModel is 1 • D/plugin ( 366): Application data dir is /data/data/com.android.browser/app_plugins • D/plugin ( 366): ------ 0x312a10 PluginType is 6 • D/plugin ( 366): *** 0x312a10 END NPP_New *** • D/plugin ( 366): *** 0x420f18 NPP_SetWindow ***

  26. Android中的浏览器插件开发分析 • 运行测试 • D/dalvikvm( 366): Trying to load lib /data/data/com.android.sampleplugin/lib/libsampleplugin.so 0x43c2e448 • D/dalvikvm( 366): Added shared lib /data/data/com.android.sampleplugin/lib/libsampleplugin.so 0x43c2e448 • D/plugin ( 366): *** 0x312a10 NPP_SetWindow *** • D/plugin ( 366): -------- repeat timer 5 • D/plugin ( 366): -------- latency test: [1937207155] interval 421 expected 50, total 421 expected -1923890058, drift 1923890479 avg 0 • D/plugin ( 366): -------- oneshot timer • D/plugin ( 366): -------- repeat timer 4 • D/plugin ( 366): -------- latency test: [1937207156] interval 473 expected 50, total 894 expected -1923890008, drift 1923890902 avg 0 • E/plugin ( 366): ----0x312a10 Invalid Surface Dimensions (300,150):(120,60) • D/plugin ( 366): -------- repeat timer 3 • D/plugin ( 366): -------- latency test: [1937207157] interval 73 expected 50, total 967 expected -1923889958, drift 1923890925 avg 0 • D/plugin ( 366): -------- repeat timer 2 • D/plugin ( 366): -------- latency test: [1937207158] interval 130 expected 50, total 1097 expected -1923889908, drift 1923891005 avg 0 • D/plugin ( 366): *** 0x420f18 NPP_HandleEvent *** • D/plugin ( 366): ------ 0x420f18 the plugin received an onLoad event • D/plugin ( 366): *** 0x312a10 NPP_HandleEvent *** • D/plugin ( 366): -------- repeat timer 1

  27. Android中的浏览器插件开发分析 • 运行测试 • D/plugin ( 366): -------- latency test: [1937207159] interval 90 expected 50, total 1187 expected -1923889858, drift 1923891045 avg 0 • D/dalvikvm( 54): GC freed 8773 objects / 568952 bytes in 169ms • D/plugin ( 366): *** 0x312a10 NPP_HandleEvent *** • D/plugin ( 366): *** 0x312a10 NPP_HandleEvent *** • D/plugin ( 366): *** 0x312a10 NPP_HandleEvent *** • D/plugin ( 366): *** 0x420f18 NPP_HandleEvent *** • D/plugin ( 366): *** 0x420f18 NPP_HandleEvent *** • D/PowerManagerService( 54): setPowerState: mPowerState=3 newState=7 noChangeLights=false • D/PowerManagerService( 54): oldKeyboardBright=false newKeyboardBright=false • D/PowerManagerService( 54): oldScreenBright=true newScreenBright=true • D/PowerManagerService( 54): oldButtonBright=false newButtonBright=true • D/PowerManagerService( 54): oldScreenOn=true newScreenOn=true • D/PowerManagerService( 54): oldBatteryLow=false newBatteryLow=false • W/KeyCharacterMap( 366): No keyboard for id 0 • W/KeyCharacterMap( 366): Using default keymap: /system/usr/keychars/qwerty.kcm.bin • D/plugin ( 366): *** 0x420f18 NPP_SetWindow *** • D/plugin ( 366): *** 0x420f18 NPP_Destroy *** • D/plugin ( 366): *** 0x312a10 NPP_SetWindow *** • D/plugin ( 366): *** 0x312a10 NPP_Destroy *** • D/plugin ( 366): *** NP_Shutdown ***

  28. Android中的浏览器插件开发分析 插件工作流程 • 浏览器解析页面时,遇到插件的MIME类型,就去检查插件注册表,如果有,就加载插件; • 在插件加载之后,插件先会进行API映射,即把各种调配资源的API映射到NPNetscapeFuncs的结构体指针上,然后作为输入参数调用NP_Initialize() NP_Initialize()只被调用一次,; • 初始化API返回成功后(一个NPPetscapeFuncs结构体指针),插件入口API将被调用,它允许浏览器不必常规地来调用插件端的APIs,这样入口API返回成功后,浏览器的NPPetscapeFuncs结构体将被插件端有效的APIs指针填充(根据适当的内部流程),并将立即按需被调用;

  29. Android中的浏览器插件开发分析 插件工作流程 • 调用NPP_New(),实例化插件,如上面的实例0x312a10和0x420f18;每个实例都会被分配给一个数据块,每个实例根据插件的定义填充参数; • 调用NPP_SetWindow() ,显示插件; • 如果在插件上点击鼠标之类的,就会调用NPP_HandleEvent(); • 关闭此页面,先会调用NPP_SetWindow(),然后调用NPP_Destroy(),释放实例的资源; • 全部实例被 Destroy后,调用NP_ShutDown(),释放全局资源。

  30. Android中的浏览器插件开发分析 插件工作流程

  31. 本章小结 本章为Android浏览器扩展,主要介绍开发浏览器扩展插件的方法,先对浏览器插件进行了介绍,然后介绍了BrowserPlugin,最后完成了一个浏览器插件的编译和运行。

  32. The end

More Related