您的位置:首页 > 移动开发 > Android开发

android 浏览器插件开发

2014-01-21 20:08 411 查看
2011-08-24 10:21 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
plaincopy

To compile and install a plugin on a device/emulator simply...

1. run "make SampleBrowserPlugin" (compiles libsampleplugin.so and builds the apk)

2. the previous command produces an apk file so record its location

3. run "adb install [apk_file]" to install it on a device/emulator

4. the browser will auto recognize the plugin is available

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

[html] view
plaincopy

<html>

<head>

<title>test</title>

</head>

<body>

<object type="application/x-testbrowserplugin" id="sample">

<param name="DrawingModel" value="Surface" />

<param name="PluginType" value="Background" />

</object>

<object type="application/x-testbrowserplugin" id="ball">

<param name="DrawingModel" value="Bitmap" />

<param name="PluginType" value="Animation" />

</object>

</body>

</html>

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

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

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

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

[html] view
plaincopy

<uses-permission android:name="android.webkit.permission.PLUGIN"/>

<uses-sdk android:minSdkVersion="3" />

<application android:icon="@drawable/sample_browser_plugin"

android:label="@string/sample_browser_plugin">

<service android:name=".SamplePlugin">

<intent-filter>

<action android:name="android.webkit.PLUGIN" />

</intent-filter>

<meta-data android:name="type" android:value="native" />

</service>

</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
plaincopy

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.example.helloplugin"

android:versionCode="1"

android:versionName="1.0">

<uses-permission android:name="android.webkit.permission.PLUGIN"/>

<uses-sdk android:minSdkVersion="3" />

<application android:icon="@drawable/hello_browser_plugin"

android:label="@string/hello_browser_plugin">

<service android:name=".HelloPlugin">

<intent-filter>

<action android:name="android.webkit.PLUGIN" />

</intent-filter>

<meta-data android:name="type" android:value="native" />

</service>

</application>

</manifest>

HelloPlugin.java代码

[html] view
plaincopy

package com.example.helloplugin;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

public class HelloPlugin extends Service {

@Override

public IBinder onBind(Intent intent) {

// TODO Auto-generated method stub

return null;

}

}

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

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

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

[cpp] view
plaincopy

virtual bool supportsDrawingModel(ANPDrawingModel);

virtual int16 handleEvent(const ANPEvent* evt);

我简单实现的HelloPlugin.cpp代码如下

[cpp] view
plaincopy

#include "HelloPlugin.h"

extern ANPLogInterfaceV0 gLogI;

extern ANPCanvasInterfaceV0 gCanvasI;

///////////////////////////////////////////////////////////////////////////////

HelloPlugin::HelloPlugin(NPP inst) : SubPlugin(inst) {

//

gLogI.log(kDebug_ANPLogType, "HelloPlugin created...");

//register for touch events

ANPEventFlags flags = kTouch_ANPEventFlag;

NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);

if (err != NPERR_NO_ERROR) {

gLogI.log(kError_ANPLogType, "Error selecting input events.");

}

}

HelloPlugin::~HelloPlugin(){

//

}

bool HelloPlugin::supportsDrawingModel(ANPDrawingModel model) {

return (model == kBitmap_ANPDrawingModel);

}

void HelloPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {

// create a canvas

ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);

// clip the canvas

ANPRectF clipR;

clipR.left = clip.left;

clipR.top = clip.top;

clipR.right = clip.right;

clipR.bottom = clip.bottom;

gCanvasI.clipRect(canvas, &clipR);

// paint the canvas (using the path API)

gCanvasI.drawColor(canvas, 0xFF0000FF);

// delete the canvas

gCanvasI.deleteCanvas(canvas);

}

int16 HelloPlugin::handleEvent(const ANPEvent* evt) {

NPP instance = this->inst();

switch (evt->eventType) {

case kDraw_ANPEventType:

switch (evt->data.draw.model) {

case kBitmap_ANPDrawingModel:

gLogI.log(kDebug_ANPLogType, "We should draw plugin !!!!!!!!");

drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip);

return 1;

default:

break; // unknown drawing model

}

case kTouch_ANPEventType:

if (kDown_ANPTouchAction == evt->data.touch.action) {

gLogI.log(kDebug_ANPLogType, "touch event occurs!!!!!!!!");

}

return 1;

default:

break;

}

return 0; // unknown or unhandled event

}

是不是很简单?

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

npruntime在ANDROID下的库文件叫什么,链接的时候出错呀?

请参考 http://blog.csdn.net/awebkit/article/details/6713943
把插件代码放在源码合适的位置。在编自己的插件之前,请先尝试编译BrowserPlugin
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: