写在前边
cordova框架可以让h5页面调用硬件,比如手机拍照等.这部分其实是需要原声代码支持的,cordova框架做的是h5页面和原生代码的中间件.硬件调用的功能有原生代码实现,不同平台(安卓/ios/window等)需要不同平台单独编写.这些原生代码叫做插件(plugin).h5代码负责显示内容,交互需要调用js代码,js再调用插件,插件执行可以调用手机硬件的方法,然后将返回值传递给js的回调方法,完成整个交互过程.这些插件可以自己编写,需要继承Cordova框架提供的类,在iOS平台,这些插件需要继承CDVPlugins类.这些插件也可以在网上下载,Cordova官网和Github都有非常丰富的插件可以供用户下载使用.
cordova版本:6.5.0
目录
1. 自己编写插件流程
2. js与插件间传递参数,以及插件回调js方法
3. 下载第三方插件
一、自己编写插件流程
示例代码下载地址
github传送门
1.新建一个空白项目,打开后删除掉没用的目录,以免混淆视听:
(config.xml 和www文件夹都是使用Staging目录下的,根目录下的没用,删掉后项目变得更清晰)
2.用以下代码完全替换www文件夹下的index.html文件的代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="format-detection" content="telephone=no" />
<title>首页</title>
<style>
.ui-margin {
width: 300px;
height: 64px;
}
.ui-block-a {
font-size: 16px;
margin: 4px;
padding: 4px;
width: 180px;
height: 32px;
}
</style>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script>
var JSObject = new Object();
JSObject.IsMobile = function () {
return navigator.platform.indexOf('Win32') == -1;
};
JSObject.SupportCovdova = function () {
return typeof (cordova) != "undefined";
};
JSObject.testCordovaPlugin = function() {
console.log("testJS");
//alert("IsMobile:"+this.IsMobile());
//alert("SupportCovdova:"+this.SupportCovdova());
if (!this.IsMobile() || !this.SupportCovdova()) {
alert("不支持Cordova");
return;
}
cordova.exec(null, null, "TestPluginName", "testPluginFunction", null);
};
</script>
</head>
<body>
<div class="ui-margin"></div>
<div>
<input class="ui-block-a" type="button" value="调用插件" onclick="JSObject.testCordovaPlugin()" />
</div>
</body>
</html>
3.编写插件,目录和代码如下
//TestPlugin.h
#import <Cordova/CDVPlugin.h>
@interface TestPlugin : CDVPlugin
-(void)testPluginFunction:(CDVInvokedUrlCommand *)command;
@end
//TestPlugin.m
#import "TestPlugin.h"
@implementation TestPlugin
-(void)testPluginFunction:(CDVInvokedUrlCommand *)command{
UIAlertController *ac = [UIAlertController alertControllerWithTitle:@"提示" message:@"testPluginFunction" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *aa = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[ac addAction:aa];
[self.viewController presentViewController:ac animated:YES completion:nil];
}
@end
4.配置 config.xml文件
<feature name="TestPluginName">
<param name="ios-package" value="TestPlugin" />
</feature>
5.最终效果
点击网页上的按钮,js调用插件执行原生OC代码的弹框。调用成功。
6.稍微总结一下
1. js代码调用插件时,可以使用以下代码判断当前是否支持cordova
function SupportCovdova() {
return typeof (cordova) != "undefined";
};
如果不支持cordova,记得引入cordova.js
<script type="text/javascript" src="cordova.js"></script>
2. 说明一下js代码调用插件的关系,如图:
二、 js与插件间传递参数,以及插件回调js方法
JS通过cordova.exec()方法调用插件时,可以传入插件方法需要的参数,和插件将来回调的js参数。
//执行cordova插件,五个参数分别是:
//成功回调方法,失败回调方法,插件名(配置文件中配置的插件名),插件方法,传入插件的参数(数组类型,可传入多个参数)
cordova.exec(this.testSuccess, this.testFail, "TestPluginName", "testPluginFunctionWithArgumentsAndCallBack", [{"name" : "小明"}, {"age" : "9"}, {"frends" : ["小白", "小溪"]}]);
插件方法
-(void)testPluginFunctionWithArgumentsAndCallBack:(CDVInvokedUrlCommand *)command{}
的参数CDVInvokedUrlCommand *command
有四个成员变量:
//***CDVInvokedUrlCommand的四个成员变量, NSString *callbackId = command.callbackId; NSString *className = command.className; NSString *methodName = command.methodName; NSArray *arguments = command.arguments;
其中command.arguments就是js调用插件时传过来那个参数(数组类型),command.callbackId用来在插件中回调js回调方法时使用:
NSArray *array = @[@"返回参数1", @"返回参数2"];
//CDVPluginResult 的status属性是只读属性,初始化方法“resultWithStatus: messageAsArray:”的第一个参数传入CDVCommandStatus_OK时,调用js的成功回调方法,传入其他的值都执行js的失败回调方法
//回调js的成功回调方法
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:array];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
示例代码:
//JS代码
var JSObject = new Object();
JSObject.IsMobile = function () {
return navigator.platform.indexOf('Win32') == -1;
};
JSObject.SupportCovdova = function () {
return typeof (cordova) != "undefined";
};
JSObject.testCordovaPluginWithArgumentsAndCallBack = function() {
console.log("testJS");
if (!this.IsMobile() || !this.SupportCovdova()) {
alert("不支持Cordova");
return;
}
//执行cordova插件,五个参数分别是:
//成功回调方法,失败回调方法,插件名(配置文件中配置的插件名),插件方法,传入插件的参数(数组类型,可传入多个参数)
cordova.exec(this.testSuccess, this.testFail, "TestPluginName", "testPluginFunctionWithArgumentsAndCallBack", [{"name" : "小明"}, {"age" : "9"}, {"frends" : ["小白", "小溪"]}]);
};
JSObject.testSuccess = function(result) {
alert("JS成功回调方法:testSuccess\n\n"+result);
}
JSObject.testFail = function(result) {
alert("JS失败回调方法:testFail\n\n"+result);
}
//OC插件代码
#import "TestPlugin.h"
@interface TestPlugin()
@property(nonatomic,strong) NSString *callbackId;
@end
@implementation TestPlugin
-(void)testPluginFunctionWithArgumentsAndCallBack:(CDVInvokedUrlCommand *)command{
//***CDVInvokedUrlCommand的四个成员变量,
NSString *callbackId = command.callbackId;
NSString *className = command.className;
NSString *methodName = command.methodName;
NSArray *arguments = command.arguments;
NSLog(@"callbackId:%@",callbackId);
NSLog(@"className:%@",className);
NSLog(@"methodName:%@",methodName);
NSLog(@"arguments:%@",arguments);
//***打印传入的参数
NSString *argumentsStr = @"";
for (NSDictionary *dict in command.arguments) {
for (NSString *key in dict.allKeys) {
NSObject *object = [dict objectForKey:key];
if ([object isKindOfClass:[NSString class]]) {
argumentsStr = [NSString stringWithFormat:@"%@%@=%@\n",argumentsStr,key,object];
} else if([object isKindOfClass:[NSArray class]]){
argumentsStr = [NSString stringWithFormat:@"%@%@:\n",argumentsStr,key];
for (NSObject *subObject in (NSArray *)object) {
if ([subObject isKindOfClass:[NSString class]]) {
argumentsStr = [NSString stringWithFormat:@"%@%@\n",argumentsStr,subObject];
}
}
}
}
}
self.callbackId = command.callbackId;
[self alertMessage:argumentsStr andTitle:@"OC弹框"];
}
//弹出提示信息
-(void)alertMessage:(NSString *)message andTitle:(NSString *)title{
UIAlertController *ac = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *aaYES = [UIAlertAction actionWithTitle:@"成功" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//***回调JS方法
NSArray *array = @[@"返回参数1", @"返回参数2"];
//CDVPluginResult 的status属性是只读属性,初始化方法“resultWithStatus: messageAsArray:”的第一个参数传入CDVCommandStatus_OK时,调用js的成功回调方法,传入其他的值都执行js的失败回调方法
//回调js的成功回调方法
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:array];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}];
UIAlertAction *aaNO = [UIAlertAction actionWithTitle:@"失败" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
//***回调JS方法
NSArray *array = @[@"返回参数1", @"返回参数2"];
//CDVPluginResult 的status属性是只读属性,初始化方法“resultWithStatus: messageAsArray:”的第一个参数传入CDVCommandStatus_OK时,调用js的成功回调方法,传入其他的值都执行js的失败回调方法
//回调js的失败回调方法
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsArray:array];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}];
[ac addAction:aaYES];
[ac addAction:aaNO];
[self.viewController presentViewController:ac animated:YES completion:nil];
}
@end
效果如图: