我们先看一下cordova插件的文件夹,都包括哪些目录以及文件。这里我以Device插件为例:
插件目录

因为是官方的插件所以目录和文件比较多,我们在实际开发中可以适当的增删,不过有些是必须要有的。
src
目录里面放对应不同平台的文件,andorid是java,iOS是.h和.m文件
www
文件夹下放我们的javascript文件。
plugin.xml
插件的配置文件。
plugin.xml
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:rim="http://www.blackberry.com/ns/widgets"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-device"
version="1.1.1">
<name>Device</name>
<description>Cordova Device Plugin</description>
<license>Apache 2.0</license>
<keywords>cordova,device</keywords>
<repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git</repo>
<issue>https://issues.apache.org/jira/browse/CB/component/12320648</issue>
<js-module src="www/device.js" name="device">
<clobbers target="device" />
</js-module>
...
主要的几个属性
Attributes(type) | Description |
---|
xmlns | The plugin namespace, http://apache.org/cordova/ns/plugins/ 1.0. If the document contains XML from other namespaces, such as tags to be added to the AndroidManifest.xml file in the case of Android, those namespaces should also be included in the element. |
id | A npm-style identifier for the plugin. |
version | A version number for the plugin. Semver syntax is supported. |
name | specify the name of the plugin |
description | specify the description of the plugin. |
keyWords | contains comma separated keywords to describe the plugin |
keyWords | specify the license of the plugin |
js-module | specifies the path to the common JavaScript interface |
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="Device">
<param name="ios-package" value="CDVDevice"/>
</feature>
</config-file>
<header-file src="src/ios/CDVDevice.h" />
<source-file src="src/ios/CDVDevice.m" />
</platform>
这里是插件的配置信息(iOS为例子)的插件信息插入到平台的 config.xml 文件中,来通知平台添加了插件.
插件的调用过程
要开发自己的cordova插件,了解一下插件的调用过程是非常有必要的。下面是简单介绍一下。
首先我们在js中调用device的方法,获取设备信息。
App.uuid = device.uuid;
App.model = device.model;
App.version = device.version;
App.platform = device.platform;
然后看一下www目录下的device.js
Device.prototype.getInfo = function(successCallback, errorCallback) {
argscheck.checkArgs('fF', 'Device.getInfo', arguments);
exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
};
cordova 插件最后都是通过exec函数完成插件调用的,在exec函数里,首先会判断平台,可能是如果是ios平台,cordova主要会通过iframe的方式与native交互。
cordova.exec往当前的html中插入一个不可见的iframe,从而向UIWebView请求加载一个特殊的URL,这个URL里当然就包含了要调用的native plugin的类名,方法名,参数,回调函数等信息。
function iOSExec() {
var successCallback, failCallback, service, action, actionArgs
var callbackId = null
if (typeof arguments[0] !== 'string') {
successCallback = arguments[0]
failCallback = arguments[1]
service = arguments[2]
action = arguments[3]
actionArgs = arguments[4]
callbackId = 'INVALID'
} else {
throw new Error('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
'cordova.exec(null, null, \'Service\', \'action\', [ arg1, arg2 ]);'
)
}
actionArgs = actionArgs || []
if (successCallback || failCallback) {
callbackId = service + cordova.callbackId++
cordova.callbacks[callbackId] =
{success:successCallback, fail:failCallback}
}
actionArgs = massageArgsJsToNative(actionArgs)
var command = [callbackId, service, action, actionArgs]
commandQueue.push(JSON.stringify(command))
if (!isInContextOfEvalJs && commandQueue.length == 1) {
if (execIframe && execIframe.contentWindow) {
execIframe.contentWindow.location = 'gap://ready'
} else {
execIframe = document.createElement('iframe')
execIframe.style.display = 'none'
execIframe.src = 'gap://ready'
document.body.appendChild(execIframe)
}
...
}
}
native端通过UIWebView的方法,截获js端传来的命令。通过这个方式,js调用native是异步的。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest (NSURLRequest *)request navigationType: (UIWebViewNavigationType)navigationType
最后在看一下ios目录下CDVDevice文件
然后是CDVDevice.h文件,继承自CDVplugin类,调用getDeviceInfo获取设备信息,代码如下
#import <UIKit/UIKit.h>
#import <Cordova/CDVPlugin.h>
@interface CDVDevice : CDVPlugin
{}
+ (NSString*)cordovaVersion;
- (void)getDeviceInfo:(CDVInvokedUrlCommand*)command;
@end
关于CDVInvokedUrlCommand
通过这个类的几个成员变量应该可以发现,使用这个类的实例来接收js端传过来的参数。
@interface CDVInvokedUrlCommand : NSObject {
NSString* _callbackId;
NSString* _className;
NSString* _methodName;
NSArray* _arguments;
}
到这里 js端使用cordova 插件的过程就完成了。
参考资料
http://cordova.apache.org/docs/en/latest/
http://www.cocoachina.com/industry/20140623/8919.html
http://www.jianshu.com/p/36f8fd15664c