android 浏览器插件开发

 3791人阅读 评论(10) 收藏 举报

转载请注明出处:http://blog.csdn.net/awebkit

    [注]:android平台不支持除flash之外的插件。为了安全考虑,在真实设备中,ro.secure为true,对于插件的管理,在PluginManager.java中会对签名进行验证,只有falsh的签名才能通过。

      如果自己开发,需要保证ro.secure为false。adb shell getprop ro.secure


    android平台上的浏览器插件开发遵循NPAPI规则,关于NPAPI,请查看https://developer.mozilla.org/En/Plugins


    但是,android平台有自己的特色,比如以java语言生成service来实现插件功能。有如下问题需要解决:

          1. android浏览器插件开发流程如何?这个问题包含的小问题很多,我们慢慢展开。

          2. android对浏览器插件有了那些改变?


    本章,我们讨论第一个问题,即浏览器插件开发流程。


    首先,我们可以从android自带的插件示例开始看起。

    插件代码在android源码下面的 development/samples/BrowserPlugin 。

    编译方法也比较简单,请看README

[plain]  view plain copy
  1. To compile and install a plugin on a device/emulator simply...  
  2.   
  3. 1. run "make SampleBrowserPlugin" (compiles libsampleplugin.so and builds the apk)  
  4. 2. the previous command produces an apk file so record its location  
  5. 3. run "adb install [apk_file]" to install it on a device/emulator  
  6. 4. the browser will auto recognize the plugin is available  

      示例HTML同样在README里面说明了。我扩充了一下,示例HTML如下

[html]  view plain copy
  1. <html>  
  2. <head>  
  3. <title>test</title>  
  4. </head>  
  5.   
  6. <body>  
  7. <object type="application/x-testbrowserplugin" id="sample">  
  8.     <param name="DrawingModel" value="Surface" />  
  9.     <param name="PluginType" value="Background" />  
  10. </object>  
  11.       
  12. <object type="application/x-testbrowserplugin" id="ball">  
  13.     <param name="DrawingModel" value="Bitmap" />  
  14.     <param name="PluginType" value="Animation" />  
  15. </object>  
  16.       
  17. </body>  
  18. </html>  


      解压这个apk,发现里面的主要部分是一个so库(lib/armeabi/libsampleplugin.so)


    经过简单的测试,我们对插件的用法有了大致了解。那么,编写插件的流程是如何的呢?我们可以根据BrowserPlugin 这个示例代码来分析。

    基本思想就是注册一个service,我们生成的apk包里面包含插件解析的动态库


    首先,注册service。模板如下。其中,uses-permission,intent-filter,meta-data都必须按照如下写,不能有改动。具体原因可以看PluginManager.java

[html]  view plain copy
  1. <uses-permission android:name="android.webkit.permission.PLUGIN"/>  
  2.   
  3. <uses-sdk android:minSdkVersion="3" />  
  4.   
  5. <application android:icon="@drawable/sample_browser_plugin"  
  6.              android:label="@string/sample_browser_plugin">  
  7.     <service android:name=".SamplePlugin">  
  8.         <intent-filter>  
  9.             <action android:name="android.webkit.PLUGIN" />  
  10.         </intent-filter>  
  11.         <meta-data android:name="type" android:value="native" />  
  12.     </service>  
  13. </application>  

    其次,生成service。生成service的代码很简单,可以完全照抄SamplePlugin.java。


    最后,生成动态库。这里需要注意的是,动态库的生成需要用到android里面关于插件部分的接口头文件。

        1. 考虑到并非每个人都会下载android源码,我们可以考虑把需要的头文件打包。这样,生成动态库的时候,需要include这些头文件,并且连接android sdk库,需要自己写makefile。好处就是脱离android源码。

        2. 下载android源码,编写和BrowserPlugin差不多的代码。好处就是比较简单。


    最最后,打包apk。


    可以看到,插件制作的主要部分在动态库的生成部分,下一节我们主要讨论动态库应该如何编写。

    上一讲我们说了浏览器插件开发的流程。这里有几个问题说明:

        1. 可不可以不使用android apk的方式,直接把插件库放到系统插件库位置下面?

              在android早期版本中,确实存在一个浏览器插件库位置。但是,我使用的2.3版本,已经没有这个插件库位置了。也就是说,插件只能通过apk的方式,不同的插件库只能放在不同的apk下面

         2. 如果有多个对应插件的service,会如何?

               我们查一下PluginManager.java,就会发现,这些service会放在一个list里面,所有的lib路径都会加到插件库的查找路径下面。

          3. 如何调试webkit中关于插件部分?

                修改代码external/webkit/WebKit/android/plugins/PluginDebugAndroid.h,修改 PLUGIN_DEBUG_GLOBAL 的指。logcat会打印插件部分的debug信息。channel为webkit_plugin


         好,下一讲我们给出一个简单的插件代码。HelloPlugin


         这一讲我们一起来编写一个简单的浏览器插件 - HelloPlugin

         

         java部分:AndroidManifest.xml

[html]  view plain copy
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  2.       package="com.example.helloplugin"  
  3.       android:versionCode="1"  
  4.       android:versionName="1.0">  
  5.   
  6.     <uses-permission android:name="android.webkit.permission.PLUGIN"/>  
  7.   
  8.     <uses-sdk android:minSdkVersion="3" />  
  9.   
  10.     <application android:icon="@drawable/hello_browser_plugin"  
  11.                  android:label="@string/hello_browser_plugin">  
  12.         <service android:name=".HelloPlugin">  
  13.             <intent-filter>  
  14.                 <action android:name="android.webkit.PLUGIN" />  
  15.             </intent-filter>  
  16.             <meta-data android:name="type" android:value="native" />  
  17.         </service>  
  18.     </application>  
  19.   
  20. </manifest>  
    HelloPlugin.java代码
[html]  view plain copy
  1. package com.example.helloplugin;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6.   
  7. public class HelloPlugin extends Service {  
  8.   
  9.     @Override  
  10.     public IBinder onBind(Intent intent) {  
  11.         // TODO Auto-generated method stub  
  12.         return null;  
  13.     }     
  14. }  

   c代码部分。保留main.cpp, main.h, PluginObject.h, PluginObject.cpp,稍微作一些修改。

   修改Android.mk,仿照原来的例子。

   增加hello/HelloPlugin.h hello/HelloPlugin.cpp。这个函数要实现的API有两个

[cpp]  view plain copy
  1. virtual bool supportsDrawingModel(ANPDrawingModel);                           
  2. virtual int16 handleEvent(const ANPEvent* evt);       
    我简单实现的HelloPlugin.cpp代码如下
 

[cpp]  view plain copy
  1. #include "HelloPlugin.h"  
  2.   
  3. extern ANPLogInterfaceV0       gLogI;  
  4. extern ANPCanvasInterfaceV0    gCanvasI;  
  5. ///  
  6.   
  7. HelloPlugin::HelloPlugin(NPP inst) : SubPlugin(inst) {  
  8.     //  
  9.   
  10.     gLogI.log(kDebug_ANPLogType, "HelloPlugin created...");  
  11.     //register for touch events  
  12.     ANPEventFlags flags = kTouch_ANPEventFlag;  
  13.     NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);  
  14.     if (err != NPERR_NO_ERROR) {  
  15.         gLogI.log(kError_ANPLogType, "Error selecting input events.");  
  16.     }  
  17. }  
  18.   
  19. HelloPlugin::~HelloPlugin(){  
  20.     //  
  21. }  
  22.   
  23. bool HelloPlugin::supportsDrawingModel(ANPDrawingModel model) {  
  24.     return (model == kBitmap_ANPDrawingModel);  
  25. }  
  26.   
  27. void HelloPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {  
  28.   
  29.     // create a canvas  
  30.     ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);  
  31.   
  32.     // clip the canvas  
  33.     ANPRectF clipR;  
  34.     clipR.left = clip.left;  
  35.     clipR.top = clip.top;  
  36.   
  37.     clipR.right = clip.right;  
  38.     clipR.bottom = clip.bottom;  
  39.     gCanvasI.clipRect(canvas, &clipR);  
  40.   
  41.     // paint the canvas (using the path API)  
  42.     gCanvasI.drawColor(canvas, 0xFF0000FF);  
  43.   
  44.     // delete the canvas  
  45.     gCanvasI.deleteCanvas(canvas);  
  46. }  
  47.   
  48. int16 HelloPlugin::handleEvent(const ANPEvent* evt) {  
  49.     NPP instance = this->inst();  
  50.   
  51.     switch (evt->eventType) {  
  52.         case kDraw_ANPEventType:  
  53.             switch (evt->data.draw.model) {  
  54.                 case kBitmap_ANPDrawingModel:  
  55.                     gLogI.log(kDebug_ANPLogType, "We should draw plugin !!!!!!!!");  
  56.                     drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip);  
  57.                     return 1;  
  58.                 default:  
  59.                     break;   // unknown drawing model  
  60.             }  
  61.         case kTouch_ANPEventType:  
  62.             if (kDown_ANPTouchAction == evt->data.touch.action) {  
  63.                 gLogI.log(kDebug_ANPLogType, "touch event occurs!!!!!!!!");  
  64.             }  
  65.              return 1;  
  66.         default:  
  67.             break;  
  68.     }  
  69.     return 0;   // unknown or unhandled event  
  70. }  

      是不是很简单?

    

      插件的实现还是比较简单的,我们只要深入理解了NPAPI,然后在合适的时机实现需要的功能即可。


      npruntime在ANDROID下的库文件叫什么,链接的时候出错呀?
      请参考 http://blog.csdn.net/awebkit/article/details/6713943
      把插件代码放在源码合适的位置。在编自己的插件之前,请先尝试编译BrowserPlugin


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值