在使用cordova开发混合应用的途中,一般采用的插件开发方式来实现原生代码和JS代码之间的通讯。并且一般情况下一个模块就要开发这样一个插件,换句话说就是用某一个插件来负责某个模块的原生与JS代码之间的交互。接下来,我就来简单介绍一下这么一个插件的使用方法。
1、首先,要设计一下cordova插件的文件目录结构。
在mac中显示如下:
解释一下,这些文件代表的意思,或许这样会好理解一点:
-
Readme.md是说明文件,可有可无,但是为了方便其他人阅读,建议带上,并可以在里面说明你的用意。
-
plugin.xml文件:这个文件是对这个插件的总体的配置
- 指定了运行的平台(ios或者andorid)
- 插件的id,插件的标识
- config-file标签中属性target的值指定了将插件中原生代码封装到的目录。在子标签feature中将原生类用一个Key来代替,方便使用。
- header-file标签,source-file标签,属性src分别为插件的Objective-C头文件以及实现文件所在的路径(目录结构见上图)
-
js-module标签,src属性为插件js文件所在路径,属性name为插件在js module中的名字(在clobbers标签以及在前端angular代码调用插件的函数,需要使用到)。
-
clobbers标签target属性的值,plugins.xxx,表示在前端的angularjs代码中能够直接使用window.plugins.mposplugin来获取插件对象(目前是使用cordova.require("com.technologystudios.mpos.mposplugin")方式获取插件对象)。
其实,理解这些是有点难度的,就算你现在不理解我在说什么也不要紧。只要你使用一下就知道了。
2、写插件的原生代码
废话不多说,看注释就明白了
.h
#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>
//继承CDVPlugin类
@interface CDVEarphonePlugin : CDVPlugin {
}
//返回前段js时生成的id,cordova自动维护
@property (nonatomic, copy) NSString* callbackId;
//接口方法, command.arguments[0]获取前端传递的参数
- (void)earPhoneExecute:(CDVInvokedUrlCommand*)command;
@end
.m
#import "CDVEarphonePlugin.h"
@implementation CDVEarphonePlugin
@synthesize callbackId = callbackId;
- (void)earPhoneExecute:(CDVInvokedUrlCommand*)command {
NSDictionary * argums = command.arguments[0];
//要传递的参数
NSDictionary * ret = @{@"success":@"1",@"message":@"参数不为空!",@"code":@(200),@"data":@{}};
CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary:ret];
//根据callbackId回调的id返回原生代码
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}
@end
3、编写插件的jS代码,按照这个格式写就行了
//加载cordova对象以及exec方法
var exec = require('cordova/exec'),
cordova = require('cordova');
//定义插件对象
var EARPHONEPlugin = function () {
};
//定义接口,面向前端angularjs代码的接口,接口参数三个
EARPHONEPlugin.prototype.earPhoneExecute = function (successCallback, errorCallback,options) {
if (errorCallback == null) {
errorCallback = function () {
}
}
if (typeof errorCallback != "function") {
console.log("EARPHONEPlugin.earPhoneExecute: failure: failure parameter not a function");
return
}
if (typeof successCallback != "function") {
console.log("EARPHONEPlugin.earPhoneExecute: success callback parameter must be a function");
return
}
//调用原生代码,
cordova.exec(successCallback, errorCallback, 'EarphonePlugin', 'earPhoneExecute', [options]);
};
// 把新的插件对象对象,赋值给module.exports属性。
var earphoneplugin = new EARPHONEPlugin();
module.exports = earphoneplugin;
4、通过终端(CLI)安装这个插件到开发环境
-
通过CLI(终端)cd 指令进入项目路径
-
输入指令cordova plugin add /Users/Tony/Desktop/plugin/com.technologystudios.logout
(/Users/Tony/Desktop/plugin/com.technologystudios.logout为插件存放的目录) -
安装成功后,CLI显示Installing "com.technologystudios.logout" for ios
项目最外层的plugins目录和/platforms/ios/www/plugins显示新添加的插件,其中平台里面的plugins是copy最外层的plugins的内容
5,打开Plugins文件夹,对Plugin的原生代码文件进行编码
好了,到这里,插件已经成功的引入到项目中了,接下来就是要解释如何去使用这个插件进行开发了,也是就是说如何调用这些服务进行混合开发
6、要在js中调用原生代码,所以我们用js定义一个service。用来调用这个插件的原生代码
// 我的测试
.service('One', function() {
return function(options){
// 获取 options 的内容
var params = options.params,
successCallback = options.successCallback,
errorCallback = options.errorCallback;
console.log('One params:');
console.log(params);
// 获取 plguin
var mopos = false;
if (typeof cordova !== 'undefined') {
mopos = cordova.require("com.technologystudios.earphone.earphoneplugin");
};
if (!mopos) {
if(angular.isFunction(options.errorCallback)) {
options.errorCallback({
code: 'no plguin',
message: '功能异常'
});
};
return false;
};
// 尝试调用原生代码
try
{
mopos.earPhoneExecute(successCallback, errorCallback, params);
}
catch (error){
if(angular.isFunction(options.errorCallback)) {
options.errorCallback({
code: 'no plguin',
message: '功能异常'
});
};
}
}
})
7、Service注入ExternalServiceFacade服务(可以理解为类)
在某个模块负责的服务类中定义对外的借口
例:
ShoukuangService注入ExternalServiceFacade,定义向外暴露的接口
this.callMPos = function(params,paygateLoginParams){
return ExternalServiceFacade.execute('Mpos', {
params: params,
type: 'SwipeCard',
PAYGATE_LOGIN_PARAMS: paygateLoginParams
});
};
ExternalServiceFacade.execute('Mpos',{})函数
参数1,插件的nativeCode,插件在ExternalServiceFacade的标识
参数2,传递到原生代码的参数
ExternalServiceFacade.execute('Mpos',{})函数返回promise对象(目前只需明白:调用插件成功,异步返回.then()方法;调用插件失败,异步返回.catch()方法)
额外知识点
1.module
https://github.com/xufei/blog/issues/17
http://www.angularjs.cn/A00x
2.service
http://www.cnblogs.com/lvdabao/p/3464015.html
http://hellobug.github.io/blog/angularjs-providers/
3.代码混淆
4.module.exports
http://www.jb51.net/article/33269.htm
5.promise对象
http://my.oschina.net/ilivebox/blog/293771
https://cordova.apache.org/docs/en/5.1.1/plugin_ref/spec.html