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
转载请注明出处: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
相关文章推荐
- android 浏览器插件开发 - 插件库
- Android浏览器插件开发(二)
- android 浏览器插件开发 - 流程(1)
- Android浏览器插件开发
- android 浏览器插件开发 - 插件库
- Android浏览器插件开发
- android 浏览器插件开发 - HelloPlugin
- Android浏览器插件开发
- android 浏览器插件开发 - 流程(2)
- Android浏览器插件开发
- Android浏览器插件开发(一)
- Android浏览器插件开发
- android 浏览器插件开发 - Log
- Android浏览器插件开发(三)——ANPInterface的介绍
- 【转】Android浏览器插件开发
- android 浏览器插件开发 - 流程(1)
- Android浏览器插件开发
- Android浏览器插件开发
- android 浏览器插件开发 - HelloPlugin
- android 浏览器插件开发 - Log