Android浏览器插件小结(二)

上一节简单介绍了WebKit加载插件的过程,这一节开始介绍插件的具体开发方法


在Android平台开发插件,下面这4个函数是必须实现的

NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env);
NPError NP_GetValue(NPP instance, NPPVariable variable, void *value);
const char* NP_GetMIMEDescription(void);
void NP_Shutdown(void);
注:这个在不同的平台下面有区别,我发现在mac os上面需要实现

NPError NP_Initialize(NPNetscapeFuncs *browserFuncs);
NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
void NP_Shutdown(void);
这3个函数,比较一下参数就知道,Android下面的
NP_Initialize
包括了mac os中的
NP_Initialize

NP_GetEntryPoints

的功能,额外的java_env是将java虚拟机环境传下来,作为jni层的context,这个是Android必须要的,你懂的生气

但mac os为啥不需要实现

NP_GetMIMEDescription

呢?嗯,这个俺没去深究,有谁有兴趣的可以去研究一下


下面看看

const char* NP_GetMIMEDescription(void);

比如返回:"application/x-yourname:tst:MIME type is application/x-yourname"

可以参考


NP_Initialize

比较重要,通过browserFuncs将浏览器的接口传给插件,通过pluginFuncs得到插件的接口,java_env上面提过了


问题:为啥用这种方式将接口传给插件呢?

一般来说,公布模块的接口,我们会直接声明函数的,要使用它,包含头文件,库文件就可以直接调用了,但这里有个问题,我们开发的是插件,是给浏览器用的,而不是直接调用浏览器。从语法上说明可能更清楚一些,在Android上面这些插件都是app,并包含动态库.so文件,按照一般的调用方式,将提示找不到这些接口的实现,是的,用函数指针将解决这个问题,在插件中访问浏览器的接口都是通过函数指针实现的,感觉有点类似C++中的虚函数,万能的指针,C的灵魂啊


问题:那为啥插件的接口传给浏览器也要用这种方式呢?

对啊,既然调用是从浏览器到插件的,那插件直接提供头文件,浏览器直接调用不就好了,为啥又要用函数指针?这个我也没整明白,貌似用直接调用的方式也是可行的,比如我们在讨论的这4个函数就是从浏览器直接调用插件的,不知道大家有没有别的答案


下面分析一下参数browserFuncs,在npfunctions.h中定义的:

typedef struct _NPNetscapeFuncs {
    uint16 size;
    uint16 version;
    
    NPN_GetURLProcPtr geturl;
    NPN_PostURLProcPtr posturl;
    NPN_RequestReadProcPtr requestread;
    NPN_NewStreamProcPtr newstream;
    NPN_WriteProcPtr write;
    NPN_DestroyStreamProcPtr destroystream;
    NPN_StatusProcPtr status;
    NPN_UserAgentProcPtr uagent;
    NPN_MemAllocProcPtr memalloc;
    NPN_MemFreeProcPtr memfree;
    NPN_MemFlushProcPtr memflush;
    NPN_ReloadPluginsProcPtr reloadplugins;
    NPN_GetJavaEnvProcPtr getJavaEnv;
    NPN_GetJavaPeerProcPtr getJavaPeer;
    NPN_GetURLNotifyProcPtr geturlnotify;
    NPN_PostURLNotifyProcPtr posturlnotify;
    NPN_GetValueProcPtr getvalue;
    NPN_SetValueProcPtr setvalue;
    NPN_InvalidateRectProcPtr invalidaterect;
    NPN_InvalidateRegionProcPtr invalidateregion;
    NPN_ForceRedrawProcPtr forceredraw;
    
    NPN_GetStringIdentifierProcPtr getstringidentifier;
    NPN_GetStringIdentifiersProcPtr getstringidentifiers;
    NPN_GetIntIdentifierProcPtr getintidentifier;
    NPN_IdentifierIsStringProcPtr identifierisstring;
    NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
    NPN_IntFromIdentifierProcPtr intfromidentifier;
    NPN_CreateObjectProcPtr createobject;
    NPN_RetainObjectProcPtr retainobject;
    NPN_ReleaseObjectProcPtr releaseobject;
    NPN_InvokeProcPtr invoke;
    NPN_InvokeDefaultProcPtr invokeDefault;
    NPN_EvaluateProcPtr evaluate;
    NPN_GetPropertyProcPtr getproperty;
    NPN_SetPropertyProcPtr setproperty;
    NPN_RemovePropertyProcPtr removeproperty;
    NPN_HasPropertyProcPtr hasproperty;
    NPN_HasMethodProcPtr hasmethod;
    NPN_ReleaseVariantValueProcPtr releasevariantvalue;
    NPN_SetExceptionProcPtr setexception;
    NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
    NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
    NPN_EnumerateProcPtr enumerate;
    NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
    NPN_ConstructProcPtr construct;
    NPN_GetValueForURLProcPtr getvalueforurl;
    NPN_SetValueForURLProcPtr setvalueforurl;
    NPN_GetAuthenticationInfoProcPtr getauthenticationinfo;
    NPN_ScheduleTimerProcPtr scheduletimer;
    NPN_UnscheduleTimerProcPtr unscheduletimer;
    NPN_PopUpContextMenuProcPtr popupcontextmenu;
    NPN_ConvertPointProcPtr convertpoint;
} NPNetscapeFuncs;
有超过50个函数。。。。。我没找到详细的说明文档,那就以后碰到了再研究吧,有个概念,里面提供了浏览器端的各种接口,提供给插件使用


下面是pluginFuncs的:

typedef struct _NPPluginFuncs {
    uint16 size;
    uint16 version;
    NPP_NewProcPtr newp;
    NPP_DestroyProcPtr destroy;
    NPP_SetWindowProcPtr setwindow;
    NPP_NewStreamProcPtr newstream;
    NPP_DestroyStreamProcPtr destroystream;
    NPP_StreamAsFileProcPtr asfile;
    NPP_WriteReadyProcPtr writeready;
    NPP_WriteProcPtr write;
    NPP_PrintProcPtr print;
    NPP_HandleEventProcPtr event;
    NPP_URLNotifyProcPtr urlnotify;
    JRIGlobalRef javaClass;
    NPP_GetValueProcPtr getvalue;
    NPP_SetValueProcPtr setvalue;
} NPPluginFuncs;
这个只有13个函数,比较好看哈,我也没找到详细的说明文档。。。。但看名字大概可以猜出作用,这些都是插件提供给浏览器的回调,浏览器会在需要的时候调用它们,比如创建插件的时候调用NPP_NewProcPtr,销毁的时候调用NPP_DestroyProcPtr等


在这里,Android为我们提供了一套接口,扩展了浏览器端的接口,定义在Android_npapi.h中:

#define kLogInterfaceV0_ANPGetValue         ((NPNVariable)1000)
#define kAudioTrackInterfaceV0_ANPGetValue  ((NPNVariable)1001)
#define kCanvasInterfaceV0_ANPGetValue      ((NPNVariable)1002)
#define kMatrixInterfaceV0_ANPGetValue      ((NPNVariable)1003)
#define kPaintInterfaceV0_ANPGetValue       ((NPNVariable)1004)
#define kPathInterfaceV0_ANPGetValue        ((NPNVariable)1005)
#define kTypefaceInterfaceV0_ANPGetValue    ((NPNVariable)1006)
#define kWindowInterfaceV0_ANPGetValue      ((NPNVariable)1007)
#define kBitmapInterfaceV0_ANPGetValue      ((NPNVariable)1008)
#define kSurfaceInterfaceV0_ANPGetValue     ((NPNVariable)1009)
#define kSystemInterfaceV0_ANPGetValue      ((NPNVariable)1010)
#define kEventInterfaceV0_ANPGetValue       ((NPNVariable)1011)
#define kSupportedDrawingModel_ANPGetValue  ((NPNVariable)2000)
#define kJavaContext_ANPGetValue            ((NPNVariable)2001)

上面列出的是ANPGetValue使用到的类型参数,分别可以得到相关的接口,比如Log,播放音频,绘图,控制视图,得到当前Context等等,这些接口的实现都是由WebKit引擎做的,其中有个ANPEventInterfaceV0,post事件会在NPP_HandleEventProcPtr中得到,相当于引擎提供的一个消息分发中心,这里负责分发各种系统消息,包括鼠标,键盘,触摸,绘制等,用户也可以自定义消息,具体请参考android_npapi.h,这里的消息将发送给具体的插件,后面将介绍具体的插件是怎么生成的


注意一下上面接口的NPX前缀,NPN表示浏览器端的接口(Netscape-Plugin-Netscape?),而NPP表示插件端的接口(Netscape-Plugin-Plugin?),那最开始的NP接口呢?嗯,不清楚,可能只是为了和这两种区别开来


OK,到了这里,浏览器通过MIME找到了插件,通过函数指针,告诉了插件,我浏览器提供的接口,也得到了插件提供的接口,顺便也把java环境Context传给了插件








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值