cordova 插件编写 以及 简单模板


现在写插件我觉得使用 plugman 更加方便,请移步:http://blog.csdn.net/b2259909/article/details/52471178









一、 前言

cordova是什么? 和 phonegap 差不多的东东,用到了自然回去查,你就懂了。

        cordova 官方已经有很多现成的插件,但有时你需要的插件没有,你只能自己实现了。 但是cordova 官方的文档说明看着挺累,照着例子做,好多概念不理清的话,总是会让你感觉,这次成功是偶然的。



二、 准备工作


     1. 先下载cordova最新版本

     2.  使用cordova的命令创建工程,添加 android 和 iOS 平台

    

三、 开始制作插件

      目录结构: 


       


说明: 插件开发是从 js 层 往本地底层走,本地底层先执行一句打印就好。方便验证是否跑到本地底层的代码了


1.   先制作  plugin.xml  这里面的内容很重要,需要非常小心。本地代码放置在 src 下,js文件放在www下

       先看例子:后面再理理概念的东西。

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
    		xmlns:android="http://schemas.android.com/apk/res/android"
    		id="com.cordova.plugins.barcodescanner"
    		version="3.1.0">

    <name>BarcodeScanner</name>
    <description>You can use the BarcodeScanner plugin to scan different types of barcodes (using the device's camera)within your application.</description>
    <license>MIT</license>
    
    <engines>
        <engine name="cordova" version=">=3.5.0" />
    </engines>    

    <js-module src="www/barcodescanner.js" name="BarcodeScanner">
        <clobbers target="cordova.plugins.barcodeScanner" />
    </js-module>

    <!-- ios -->
    <platform name="ios">
        <!-- Cordova >= 2.8 -->
        <config-file target="config.xml" parent="/*">
            <feature name="BarcodeScanner">
                <param name="ios-package" value="HXBarcodeScanner" />
            </feature>
        </config-file>
        
        <resource-file src="src/ios/HXBarcodeScannerViewController.xib" />
        
        <header-file src="src/ios/HXBarcodeScannerViewController.h" />
        
        <source-file src="src/ios/HXBarcodeScannerViewController.m"/>
        <source-file src="src/ios/HXBarcodeScanner.m"/>
        
        <framework src="AVFoundation.framework" />
    </platform>

    <!-- android -->
    <platform name="android">
    	
    	<span style="white-space:pre">	</span><!--  -->
    	<span style="white-space:pre">	</span><source-file src="src/android/HXBarcodeScanner.java" target-dir="src/com/hxsmart/XZbar" />
    	
		<source-file src="src/android/armeabi/libiconv.so" target-dir="libs/armeabi" />
		<source-file src="src/android/armeabi/libZBarDecoder.so" target-dir="libs/armeabi" />
		<source-file src="src/android/armeabi-v7a/libiconv.so" target-dir="libs/armeabi-v7a" />
		<source-file src="src/android/armeabi-v7a/libZBarDecoder.so" target-dir="libs/armeabi-v7a" />
		<source-file src="src/android/XZbar.jar" target-dir="libs" />
			
		<source-file src="src/android/beep.ogg" target-dir="res/raw" />	
    	<span style="white-space:pre">	</span><source-file src="src/android/qr_code_bg.9.png" target-dir="res/drawable" />	
    	<span style="white-space:pre">	</span><source-file src="src/android/scan_line.png" target-dir="res/drawable" />	
    	<span style="white-space:pre">	</span><source-file src="src/android/shadow.png" target-dir="res/drawable" />
    	
    	
    	
		<config-file target="res/xml/config.xml"parent="/*">
			<feature name="BarcodeScanner">
				<param name="android-package" value="com.hxsmart.XZbar.HXBarcodeScanner" />
			</feature>
		</config-file>
			
		<!--  -->
		<config-file target="AndroidManifest.xml" parent="/manifest">
			<supports-screens  
    			android:anyDensity="true"  
    			android:largeScreens="true"  
    			android:normalScreens="true"  
    			android:smallScreens="true"  
    			android:xlargeScreens="true" />  
  
			<uses-permission android:name="android.permission.CAMERA" />  
			<uses-permission android:name="android.permission.FLASHLIGHT" />  
  
			<uses-feature android:name="android.hardware.camera" />  
			<uses-feature android:name="android.hardware.camera.autofocus" />  
  
			<uses-permission android:name="android.permission.VIBRATE" />  
			<uses-permission android:name="android.permission.WAKE_LOCK" />  
		</config-file>	
			
		<!-- activity -->
		<config-file target="AndroidManifest.xml" parent="/manifest/application">
				
				<activity android:name="com.ZbarZxing.XZbar.ZbarActivity" > 
				<intent-filter>
            <span style="white-space:pre">				</span><action android:name="com.hxsmart.XZbar.SCAN" />
                <span style="white-space:pre">			</span><category android:name="android.intent.category.DEFAULT" />
            <span style="white-space:pre">			</span></intent-filter> 
        <span style="white-space:pre">			</span></activity>
				
<span style="white-space:pre">		</span></config-file>
	
     
    </platform>
</plugin>


解释一下 :

1.  前面几个字段比较普通,除了插件都有一个唯一id,其他你爱咋写咋写。


2. 下面这句

<js-module src="www/barcodescanner.js" name="BarcodeScanner">
      <clobbers target="cordova.plugins.barcodeScanner" />
</js-module>

这里很重要, 它指明了 插件的原始  js 文件放在哪里,clobbers target有用。等会用到,这会我们把它叫做 clobbers


3.  添加平台代码:


1.) ios的先讲,以下的 

feature name="BarcodeScanner"  表示服务名为BarcodeScanner 。 记住这个服务名,有用
value="HXBarcodeScanner"       对应的.m文件中插件的类名

 

<config-file target="config.xml" parent="/*">
           <feature name="BarcodeScanner">
                <param name="ios-package" value="HXBarcodeScanner" />
           </feature>
</config-file>

后面就是一些原始文件,标记在哪里获取,以便cordova放到工程。

注意:

<framework src="AVFoundation.framework" />  可以在后面添加 custom=“true”来加载第三方的framework。</span></span>


2)android 的,和iOS大同小异,主要是 添加文件需要指明文件放置的目的地target-dir 而且不区分文件类型。

<config-file target="res/xml/config.xml"parent="/*">
<span style="white-space:pre">	</span><feature name="BarcodeScanner">
	<span style="white-space:pre">	</span><param name="android-package" value="com.hxsmart.XZbar.HXBarcodeScanner" />
<span style="white-space:pre">	</span></feature>
</config-file>

服务名一般和 ios 保持一致。

value 值 为  你写的类在包中的位置,也就是  包名.类名


其他的字段一看就知道了,无非就是你写android底层需要在  

AndroidManifest.xml 中添加的字段。 依照规则写就好了。


3)  写  barcodescanner.js  文件。注意红色部分


var exec = require("cordova/exec");


        /**
         * Constructor.
         *
         * @returns {BarcodeScanner}
         */
        function BarcodeScanner() {};


        /**
         * Read code from scanner.
         *
         * @param {Function} successCallback 
         * @param {Function} errorCallback
         */
        BarcodeScanner.prototype.scan = function (successCallback, errorCallback) {
            if (errorCallback == null) {
                errorCallback = function () {
                };
            }


            if (typeof errorCallback != "function") {
                console.log("BarcodeScanner.scan failure: failure parameter not a function");
                return;
            }


            if (typeof successCallback != "function") {
                console.log("BarcodeScanner.scan failure: success callback parameter must be a function");
                return;
            }


            exec(successCallback, errorCallback, 'BarcodeScanner', 'scan', ["AVMetadataObjectTypeQRCode,AVMetadataObjectTypeUPCECode,AVMetadataObjectTypeAztecCode,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeCode39Code,AVMetadataObjectTypeCode39Mod43Code,AVMetadataObjectTypeCode93Code,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypePDF417Code"]);
        };


var barcodeScanner = new BarcodeScanner();
module.exports = barcodeScanner;


按照模板写,第一句红色的必须有,绿色部分的函数名字,你自己起,最后面两句也是必须的,名字也是你自己起,new 的那个对象是你前面绿色部分写的。

注意后面 红色部分,分别表示 服务名 ,动作名

服务名: 按照 plugin.xml 写的,应该写为  BarcodeScanner

动作名: 在android中,由 intent.getAction 得到这个动作名,你依据这个执行不同的底层代码

               在iOS中,是指类中,实现了 CDplugin 接口的方法。


这样js 文件写好后,别人怎么调用?

还记得那个 clobbers 吗?  我不懂里面具体什么规则,反正你要调的话是类似这样:


  (clobbers-target). scan   这个scan 是 上面js文件中写的 BarcodeScanner的其中一个方法



这样可以这样写:


function test18() {
   

cordova.plugins.barcodeScanner.scan(onSuccess, onFailure);
}


function onSuccess(result) {
alert("Result:"+ result);
}
function onFailure(err) {
alert("Failure:"+ err);
}


4)本地代码怎么写?


   1. android 

      写一个类继承  CordovaPlugin , 类名要与 plugin.xml 的一致

public class HXBarcodeScanner extends CordovaPlugin
{
    public CallbackContext callbackContext;
    
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        this.callbackContext = callbackContext;
        
        if (action.equals("scan")) {
        	
        	//do something
            }
        	return true;
        }
		return false;
    } 
    
}

  2. iOS

   写一个类继承   CDVPlugin,动作方法要带有 CDVInvokedUrlCommand的参数即可

//------------------------------------------------------------------------------
// plugin class
//------------------------------------------------------------------------------
@interface HXBarcodeScanner : CDVPlugin

@property (nonatomic, retain) NSString* callback;

- (void)scan:(CDVInvokedUrlCommand*)command;

@end

@implementation HXBarcodeScanner

//--------------------------------------------------------------------------
- (void)scan:(CDVInvokedUrlCommand*)command
{
    _callback = [[NSString alloc] initWithString:command.callbackId];
    
    NSString *scannerCodeTypesString = nil;
    if ( [command.arguments count] >= 1 )
    {
        scannerCodeTypesString = [command.arguments objectAtIndex:0];
    }
    NSLog(@"scannerCodeTypesString = %@", scannerCodeTypesString);
    
}

command.argumentsobjectAtIndex:0

可以得到一个 dict  然后就是用key 去取值了。android的则是用 

JSONObject json = new JSONObject(args.getString(0));   args 是 exec 中的 CordovaArgs参数


至于是什么 key,自己在js层定义并用json格式传进来就行,本文不涉及。

cordova.plugins.barcodeScanner<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">.scan(onSuccess, onFailure,param);后面增加一个param参数</span>

传给它 {"key":"value","key1":"value1"}  在里面传给  exec(successCallback, errorCallback, ' BarcodeScanner', ' scan', [params]);



3.  返回结果:


最好也是返回一个 json数据,这些函数都是异步的

比如 

android : 

callbackContext.error("{\"ErrorMsg\": \"设备未连接,请检查蓝牙是否打开并且与设备配对成功\"}"); 


iOS:


CDVPluginResult* pluginResult = [CDVPluginResultresultWithStatus:CDVCommandStatus_ERRORmessageAsString:[NSStringstringWithFormat:@"{\"ErrorMsg\":\"参数错误\"}"]];

[self.commandDelegate sendPluginResult:pluginResultcallbackId:_callbackId];



最后,直接使用  cordova plugin add 你的插件所在路径 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值