官方
插件开发指南
Plugin.xml
因本人比较熟悉iOS , 所以创建的plugin 以iOS 为主, android 简单的涉及.
我们知道cordova plugin 是原生与html沟通的桥梁, cordova 可以说是一个webView,加载一个大的html 页面.相关的版面以html 网页的形式出现,而cordova plugin ,就好像你要打开手机的相机功能,单靠html是完成不了这个功能的.所以就需要cordova plugin的存在, 它异常的重要.
目标
这样添加plugin
希望我们最后这样使用就可以添加到cordova-plugin: (因未在registry.cordova.io中注册.暂指定备用URL)
cordova plugin add https://github.com/apache/cordova-plugin-console.git
- 也可以在https://github.com/apache/cordova-plugin-console.git => 后面加 #
在#字符后面附加备用git-ref,例如 标记或分支:
cordova plugin add https://github.com/apache/cordova-plugin-console.git#r0.2.0
- 如果插件(及其plugin.xml文件)位于git repo中的子目录中,则可以使用:字符指定它。请注意,#仍然需要该 角色:
cordova plugin add https://github.com/someone/aplugin.git#:/my/sub/dir
- 还可以将git-ref和子目录结合使用:
cordova plugin add https://github.com/someone/aplugin.git#r0.0.1:/my/sub/dir
- 或者,指定包含该plugin.xml文件的插件目录的本地路径:
cordova plugin add ../my_plugin_dir
删除plugin
cordova plugin rm pluginName(可以打开本地plugin list 看, 也可以执行 cordova plugin list 看)
開始創建我們的Plugin
-
插件文件夹必须具有plugin.xml清单文件,所以我們可以简单地创建一个plugin.xml文件, 然后我们开始对里面的参数做一一讲解
用工具打开plugin.xml.
<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns: Required , 插件名称空间,http://apache.org/cordova/ns/plugins/1.0。 如果文档包含来自其他命名空间的XML,例如在Android的情况下要添加到AndroidManifest.xml文件的标记,那么这些命名空间也应该包含在元素中。-->
<!-- id, Required ,通常是this-is-a-plugin的形式,就像cordova-plugin-device(作为示例) -->
<!-- version,Required, 插件的版本号 -->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-netspay" version="0.1.0">
<!-- name,用于指定插件的名称。(尚未)处理本地化。-->
<name>netspay</name>
<!--description用于指定插件的描述.(尚未)处理本地化。-->
<description>Cordova Plugin netspay</description>
<!--author包含插件作者的名称。-->
<author>peijue chen</author>
<!--关键字元素的内容,可以用逗号分隔的-->
<keywords>cordova, plugin, enets, netspay</keywords>
<!--此元素用于指定插件的许可证。-->
<license>MIT</license>
<!---如果有pod , 请添加此,
如果不添加这个,请先安装: cordova plugin add cordova-plugin-cocoapod-support --save
--->
<dependency id="cordova-plugin-cocoapod-support"/>
<!-- 指定的cordova 版本, 如果安裝時比它小, cordova 會終止.如果不指定,cordova 会不管三七二十一安装.-->
<!-- name : cordova/cordova-ios/cordova-android....-->
<!-- <engines>
<engine name="cordova" version=">=4.0.0" />
<engine name="cordova-android" version=">=4.0.0" />
<engine name="cordova-ios" version=">=1.7.1" />
</engines> -->
<!-- Custom frameworks example:-->
<!--
<engines>
<engine name="my_custom_framework" version="1.0.0" platform="android" scriptSrc="path_to_my_custom_framework_version"/>
<engine name="another_framework" version=">0.2.0" platform="ios|android" scriptSrc="path_to_another_framework_version"/>
<engine name="even_more_framework" version=">=2.2.0" platform="*" scriptSrc="path_to_even_more_framework_version"/>
</engines>
-->
<!-- js-module
src:插件目录中相对于plugin.xml文件;
name 提供模块名称的最后一部分.可以是你喜欢的任何东西,如果你想在你的JavaScript代码中使用cordova.require导入插件, 这里可以这样输入: var netspay = require('./netspay')
<js-module>的模块名称是插件的id,后跟name的值。 -->
<!-- clobbers: 用于指定插入module.exports的window对象下的命名空间。 您可以拥有任意数量的<clobbers>。 -->
<!-- e.g: window.cordova.plugins.netspay 这里可以这样使用-->
<js-module src="www/netspay.js" name="netspay">
<clobbers target="cordova.plugins.netspay" />
</js-module>
<!-- 加入多个, 也可以在某个平台单独指定
<js-module src="www/PositionError.js" name="PositionError">
<clobbers target="PositionError" />
</js-module>
-->
<!--<dependency>标签允许您指定当前插件所依赖的其他插件。 插件由其唯一的 npm id或github url 引用。-->
<!--
<dependency id="cordova-plugin-someplugin" url="https://github.com/myuser/someplugin" commit="428931ada3891801" subdir="some/path/here" />
<dependency id="cordova-plugin-someplugin" version="1.0.1">
-->
<!--如果不指定platform,就当作只是JavaScript,可以安装到任何平台-->
<!--Required ,Allowed values: ios, android, windows, browser, osx -->
<!-- android -->
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="NetsPay">
<param name="android-package" value="cordova-plugin-netspay.NetsPay" />
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="normal" />
<uses-permission android:name="com.nets.netspay.QR_TRANSACTION" />
</config-file>
<source-file src="src/android/NetsPay.java" target-dir="src/cordova-plugin-netspay/NetsPay" />
<framework src="src/android/netspay.gradle" custom="true" type="gradleReference"/>
<resource-file src="src/android/enetslib_UAT_1.2.1.aar" target="libs/enetslib_UAT_1.2.1.aar"/>
<!--
<resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" />
// 添加配置
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<activity android:name="com.foo.Foo" android:label="@string/app_name">
<intent-filter>
</intent-filter>
</activity>
</config-file>
-->
<!---
On Android (as of cordova-android@4.0.0), framework tags are used to include Maven dependencies, or to include bundled library projects.
-->
<!-- Depend on latest version of GCM from play services
<framework src="com.google.android.gms:play-services-gcm:+" />
-->
<!-- Depend on v21 of appcompat-v7 support library
<framework src="com.android.support:appcompat-v7:21+" />
-->
<!-- Depend on library project included in plugin
<framework src="relative/path/FeedbackLib" custom="true" />
-->
<!--
Framework can also be used to have custom .gradle files sub-included into the main project's build.gradle file:
<framework src="relative/path/rules.gradle" custom="true" type="gradleReference" />
On Windows, using custom='true' and type='projectReference' will add a reference to the project which will be added to the compile+link steps of the cordova project. This essentially is the only way currently that a 'custom' framework can target multiple architectures as they are explicitly built as a dependency by the referencing cordova application.
<framework src="path/to/project/LibProj.csproj" custom="true" type="projectReference"/>
Examples of using these Windows specific attributes:
<framework src="src/windows/example.dll" arch="x64" />
<framework src="src/windows/example.dll" versions=">=8.0" />
<framework src="src/windows/example.vcxproj" type="projectReference" target="win" />
<framework src="src/windows/example.vcxproj" type="projectReference" target="all" versions="8.1" arch="x86" />
<framework src="src/windows/example.dll" target-dir="bin/x64" arch="x64" custom="true"/>
-->
<!--
Another example of using Windows-specific attributes to add a reference to WinMD components, written in C# and C++, whose API will be available at runtime:
-->
<!-- C# component that consists of one .winmd file
<framework src="lib\windows\component.winmd" versions="<10.0" />
-->
<!-- C++ component with separated metadata and implementation
<framework src="lib\windows\x86\cppcomponent.winmd"
implementation="lib\windows\x86\cppcomponent.dll"
target-dir="component\x86" arch="x86" versions=">=10.0" />
-->
</platform>
<!-- ios -->
<platform name="ios">
<!--
这个配置相当重要, feature 中的name 你可以写 上面的id ,
param 的name 写: ios-package , 但value : 一定要写你本地的.m /.swift 文件的 class 名字, cordova 要用它来call 方法.
-->
<config-file target="config.xml" parent="/*">
<feature name="NetsPay">
<param name="ios-package" value="NetsPay" />
</feature>
</config-file>
<!-- 配置info 文件 -->
<!---往info.plist 中添加东西, 可以设置默认值, 在外面添加plugin 时也可以根据GEOLOCATION_USAGE_DESCRIPTION来添加, 请往下看-->
<preference name="GEOLOCATION_USAGE_DESCRIPTION" default="Enable access for location helps us to show you nearest stores." />
<config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
<string>$GEOLOCATION_USAGE_DESCRIPTION</string>
</config-file>
<!-- add url schemes -->
<config-file target="*-Info.plist" parent="CFBundleURLTypes">
<array>
<dict>
<key>CFBundleURLName</key>
<string>bundle.id</string>
<key>CFBundleURLSchemes</key>
<array>
<string>netspaySchemes</string>
</array>
</dict>
</array>
</config-file>
<!-- 头文件, 只复制文件进cordova项目, 不参与编译 -->
<header-file src="src/ios/NetsPay.h" />
<!--安装到项目中的可执行源代码。-->
<source-file src="src/ios/NetsPay.m" />
<!--<source-file src="src/ios/Netspay.swift" />-->
<!--compiler-flags: 如果设置,则为特定源文件指定指定的编译器标志。-->
<!--
<source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
-->
<!-- 系統庫 -->
<!-- alipay depen -->
<!-- <framework src="libc++.tbd" />
<framework src="libz.tbd" />
<framework src="SystemConfiguration.framework" />
<framework src="CoreTelephony.framework" />
<framework src="QuartzCore.framework" />
<framework src="CoreText.framework" />
<framework src="CoreGraphics.framework" />
<framework src="UIKit.framework" />
<framework src="Foundation.framework" />
<framework src="CFNetwork.framework" />
<framework src="CoreMotion.framework" /> -->
<!-- pod framework 但仅限静态库, 必须: cordova-ios@4.3.0 and cordova-cli 6.4.0
如果使用该属性, 请设置好 cordova-ios 版本.
-->
<!---或者这种情况-->
<pods-config ios-min-version="8.0" use-frameworks="true"/>
<pod id="GoogleConversionTracking" version="3.4.0"/>
<pod id="FirebaseAppIndexing" version="1.0.3"/>
<!-- <framework src="OrderPlaceSdk" type="podspec" spec="~> 0.1.3" /> -->
<!--包含本地需要说明的文件或头文件-->
<!-- <header-file src="src/ios/WechtSDK1.8.2/WechatAuthSDK.h" />
<header-file src="src/ios/WechtSDK1.8.2/WXApi.h" />
<header-file src="src/ios/WechtSDK1.8.2/WXApiObject.h" />
<header-file src="src/ios/WechtSDK1.8.2/README.txt" />
// 如果设置为true,则还将指定的文件作为框架添加到项目中。
<source-file src="src/ios/WechtSDK1.8.2/libWeChatSDK.a" framework="true" />
// 这类似于<source-file>元素,但专门针对iOS和Android等平台,用于区分源文件,头文件和资源。
// 写入xcode 中: copy bundle resource 中 一般為 xml bundle 文件
<resource-file src="src/ios/AlipaySDK.bundle" /> -->
<!--
.a 静态库, 请往上看, 需要用 source-file
custom: 指示framework是否包含在插件文件中。也就是本地库, 如果是系统库不需要 custom="true"
embed="true"需要配合custom="true"使用, 就是可以将你的动态库嵌入到应用程序中, 但需要: cordova-ios@4.4.0 and cordova-cli@7.0.0 , 如果使用该属性, 请设置好 cordova-ios 版本.
<framework src="src/ios/OrderPlaceSDK.framework" custom="true" embed="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/Alamofire.framework" custom="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/Caishen.framework" custom="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/CryptoSwift.framework" custom="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/ENETSLib.framework" custom="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/MBProgressHUD.framework" custom="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/Presentr.framework" custom="true" />
<framework src="src/ios/iOS_ENETS_SDK_UAT/SwiftyJSON.framework" custom="true" />
-->
</platform>
</plugin>
到此我们的plugin.xml 就配置好了, 这里需要添加的文件就放到对应的文件夹下面就可以
目前我的结构类似这样
- 其中 LICENSE ,是许可证, 可以用txt 文件写一个,不要后缀,名字是: LICENSE就可以.
- package.json 可以说是配置文件吧.
- README.md , 可以写上这个plugin 怎么用之类的, 如果上传到gitHub , 它会插件的首页显示.
- src: 是放ios/android 原生代码的地方
- www: 放的是js 文件
package.json
// version/ name/description, 与plugin.xml中保持一致
// repository, 是你放到gitHub 上的仓库
// bugs 是gitHub的issues 讨论区
{
"version": "0.1.0",
"name": "cordova-plugin-netspay",
"cordova_name": "cordova-plugin-netspay",
"description": "cordova-plugin-netspay",
"license": "Apache 2.0",
"author": {
"name": "Joson",
"email": "xxxx@xxx.com"
},
"repository": {
"type": "git",
"url": "https://github.com/PeiJueChen/cordova-plugin-netspay.git"
},
"bugs": {
"url": "https://github.com/PeiJueChen/cordova-plugin-netspay.git/issues"
},
"keywords": [
"cordova",
"plugin",
"netspay"
]
}
js 文件怎么写 , js 文件一般放在www 文件夹下, 这是规范
/**
*
* exec(callback, errorCallback, pluginName, actionName, argumentArray)
* callback 插件成功返回时调用,并将本机插件中的任何参数传递给它
* errorCallback在插件遇到错误时调用。我们在上面省略了这一点
* pluginName 是本机端的插件类名称。就是类名 (feature 下param 中的value , 它也要和原生代码中的类名对上.)
* actionName 是我们将在本机方面执行的操作。
* argumentArray 是传递给本机端的参数数组
*/
// prototype 屬於是為class 添加方法/屬於用到的
var exec = require('cordova/exec'),
cordova = require('cordova'),
// utils = require('cordova/utils'),
// 如果需要引用本地js, 已经在Plugin.xml 中
// <js-module src="www/PositionError.js" name="PositionError">
// <clobbers target="PositionError" />
// </js-module>
//PositionError = require('./PositionError');
var NetsPay = (function () {
// var platformId = cordova.platformId; // 'android' 'ios'
function NetsPay() {
// console.log("platformId: " + platformId + code);
}
// 建议加上cordova调用, 因为之后的版本cordova 提示说需要加cordova在前面调用
NetsPay.prototype.requestPay = function (echoValue, successCallback, errorCallback) {
cordova.exec(successCallback, errorCallback, 'NetsPay', 'requestPay', [echoValue]);
};
return NetsPay;
})();
var netsPay = new NetsPay();
// 导出属性, 调试时, window. 就会有提示这个属性.
module.exports = netsPay;
下面看看 NetsPay 文件
- iOS
#import "NetsPay.h"
#import <Cordova/CDVPluginResult.h>
#import <ENETSLib/ENETSLib-Swift.h>
@interface NetsPay ()<PaymentRequestDelegate>
@property (strong, nonatomic) NSString* requestPayCallbackId;
@end
@implementation NetsPay
- (void)requestPay:(CDVInvokedUrlCommand*)command
{
NSString* callbackId = [command callbackId];
self.requestPayCallbackId = callbackId;
// do something
[self pay:command];
// 说几点注意的, 传过来的参数可以根据 [command.arguments objectAtIndex:0]; 索引拿到
// 想调用回调时:
/*
CDVCommandStatus_OK , 这个值cordova 提供多种了,可以选择
NSDictionaray *dict = @{@"key":@"value"};
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:dict];
[self.commandDelegate pluginResult callbackId:command.callbackId];
*/
// 如果call back 是异步调用,要
// [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
}
*Android
package cordova.plugin.netspay;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class NetsPay extends CordovaPlugin {
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("requestPay")) {
String message = args.getString(0);
this. requestPay(message, callbackContext);
return true;
}
return false;
}
private void requestPay(String message, CallbackContext callbackContext) {
if (message != null && message.length() > 0) {
callbackContext.success(message);
} else {
callbackContext.error("Expected one non-empty string argument.");
}
}
}
到此一个cordova plugin 就完成了
添加
- 建议先在本地使用, 因为本地安装时,如果写得有问题, 会安装提示失败及原因. 最后测试没问题再Push 到github .
-
可以把写好plugin 放在与测试工程同一级下, 执行:
cordova plugin add ../cordova-plugin-netspay(插件文件夹名, 要让他能够找到plugin.xml 文件)
如果你已经push 到github 可以执行
cordova plugin add github地址 --variable GEOLOCATION_USAGE_DESCRIPTION ="写上你想在xcode info.plist文件中对应key的value"
添加成功后.
使用
// cordova.plugins.netspay 这个名字是由
/*
<js-module src="www/netspay.js" name="netspay">
<clobbers target="cordova.plugins.netspay" />
</js-module>
clobbers中的target 来的
*/
try {
(<any>window).cordova.plugins.netspay.requestPay({"hmac": "hmacfdsff3424"},
(s) => {
console.log('callback requestPay success', s);
}, err => {
console.log('callback requestPay err', err);
})
} catch (exception) {
console.log(' open requestPay error ', exception);
}
到此, 我们的cordova plugin 就创建结束, 如果想看关于swift怎么创建cordova插件, 请看我的另一篇文章:创建swift 版本的 cordova 插件,它会多几个注意点, 其实就是语法不同导致的.
补允: 如果是app 的使用者, 想添加pod ,可以在config.xml 中做以下配置 , ref
<platform name="ios">
<!-- set platform :ios, defaults to 7.0 -->
<preference name="pods_ios_min_version" value="8.0"/>
<!-- add use_frameworks! to Podfile, this also disabled bridging headers -->
<preference name="pods_use_frameworks" value="true"/>
<!-- use the latest version of a pod -->
<pod name="LatestPod" />
<!-- use a specific version of a pod -->
<pod name="VersionedPod" version="1.0.0" />
<!-- use a custom repo -->
<pod name="GitPod1" git="https://github.com/blakgeek/something" tag="v1.0.1" />
<pod name="GitPod2" git="https://github.com/blakgeek/something" branch="wood" />
<pod name="GitPod3" git="https://github.com/blakgeek/something" commit="1b33368" />
<!-- target specific configurations, this can be combined with all other options -->
<pod name="GitPod2" configuration="debug" />
<pod name="GitPod2" configurations="release,debug" />
<!-- add a pod dependency using a custom podspec -->
<pod name="GitPod2" podspec="https://example.com/JSONKit.podspec" />
<!-- add a pod dependency using the spec parameter like a Cordova framework -->
<pod name="GitPod2" spec="~> 2.0.0"/>
<pod name="GitPod2" spec=":configurations => ['Debug', 'Beta']"/>
<!-- if pod uses a bundle that isn't compatible with Cocoapods 1.x -->
<pod name="BadBundle" fix-bundle-path="Bad/Path.bundle"/>
</platform>