Blog

Blog

PHODAL

Cordova插件 / 混合应用插件开发: hello,world解析

周末学了一下怎么样开始Cordova的插件,也顺便分享一下这一天的经验。

Cordova插件创建

在解释之前,我们先来创建一个插件。这里我们用用到一个名为plugman的工具,然后执行如下的命令:

plugman create --name cordovaCoap --plugin_id coap-cordova-plugin --plugin_version 0.0.1

然后就会生成如下的文件内容,即下面的两个文件:

.
├── plugin.xml
├── src
└── www
    └── cordovaCoap.js

plugin.xml

先让我们来看看plugin.xml文件里有什么:

<?xml version='1.0' encoding='utf-8'?>
<plugin id="coap-cordova-plugin" version="0.0.1" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
    <name>cordovaCoap</name>
    <js-module name="cordovaCoap" src="www/cordovaCoap.js">
        <clobbers target="cordovaCoap" />
    </js-module>
</plugin>

它定义了几个内容:

  • plugin -- 命名空间、ID、版本
  • name -- 名称
  • js-module -- js文件地址,会被默认加载到首页面(index.html)。clobbers元素定义的内容将会被插入到window对象中,即变成window.cordovaCoap。

使用创建的命令少了一些内容,我们在hello,world中详细展开。

src目录中定义了不同平台的代码,我们就会在稍后的内容中看到。

让我们来看看www目录下的cordovaCoap.js吧:

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

exports.coolMethod = function(arg0, success, error) {
    exec(success, error, "cordovaCoap", "coolMethod", [arg0]);
};

我们给上面的cordovaCoap创建了一个名为coolMethod的方法,然后cordova将调用对应平台的Native方法。

插件创建的内容,还是比较简单,让我们来看看一个完整的hello,world示例代码吧。

Cordova插件hello,world

在网上寻找到一个已经创建好的Hello,world包含了iOS、Android和Windows Phone下的代码,地址:https://github.com/don/cordova-plugin-hello

目录如下所示:

├── README.md
├── plugin.xml
├── src
│   ├── android
│   │   └── Hello.java
│   ├── ios
│   │   ├── HWPHello.h
│   │   └── HWPHello.m
│   └── wp7
│       └── Hello.cs
└── www
    └── hello.js

让我们再从``plugin.xml文件看起:

<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
        id="com.example.hello"
        version="0.7.0">

  <name>Hello</name>

  <engines>
    <engine name="cordova" version=">=3.4.0"/>
  </engines>

  <asset src="www/hello.js" target="js/hello.js"/>

  <js-module src="www/hello.js" name="hello">
    <clobbers target="hello" />
  </js-module>

  <platform name="android">

    <config-file target="res/xml/config.xml" parent="/*">
      <feature name="Hello">
        <param name="android-package" value="com.example.plugin.Hello"/>
      </feature>
    </config-file>

    <source-file src="src/android/Hello.java" target-dir="src/com/example/plugin/"/>
  </platform>

  <platform name="ios">

    <config-file target="config.xml" parent="/widget">
      <feature name="Hello">
        <param name="ios-package" value="HWPHello" />
      </feature>
    </config-file>

    <header-file src="src/ios/HWPHello.h" target-dir="HelloPlugin"/>
    <source-file src="src/ios/HWPHello.m" target-dir="HelloPlugin"/>
  </platform>

  <platform name="wp7">
    <source-file src="src/wp7/Hello.cs"/>
  </platform>

</plugin>

在这个xml里多定义了下面的一些内容:

  • engines定义了基于Cordova插件的Codova版本,也可以定义不同平台的版本,如<engine name="cordova-android" version=">=1.8.0" />
  • platform定义了iOS、android、wp7三个不同平台的代码
  • 在不同的平台里,又有不同的定义。如Android定义了包名和路径、iOS定义了头文件和源文件也有包名。

在我们的www目录的hello.js的内容也是一样的:

/*global cordova, module*/

module.exports = {
    greet: function (name, successCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "Hello", "greet", [name]);
    }
};

区别比较大的就是三个不同平台的Native代码。

Cordova iOS、Android、WP原生代码

在开始看代码之前,我们先看看应该怎么去调用这些代码:

var success = function(message) {
    alert(message);
}

var failure = function() {
    alert("Error calling Hello Plugin");
}

hello.greet("World", success, failure);

我们创建了一个成功和失败的回调,并且直接调用了hello对象的greet方法,将"World"这个值传了进去。并且,这个hello是绑定在window对象中。

现在我们来看看Android平台下的Java代码吧:

package com.example.plugin;

import org.apache.cordova.*;
import org.json.JSONArray;
import org.json.JSONException;

public class Hello extends CordovaPlugin {

    @Override
    public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {

        if (action.equals("greet")) {

            String name = data.getString(0);
            String message = "Hello, " + name;
            callbackContext.success(message);

            return true;

        } else {

            return false;

        }
    }
}

我们创建了一个Hello类,它继承了CordovaPlugin,然后Override了execute方法。接着从data中取出了第一个值,即"World",并且callbackContext.success返回了处理完后的结果——Hello,World。

同理,对于Windows Phone平台来说也是如此:

using WP7CordovaClassLib.Cordova;
using WP7CordovaClassLib.Cordova.Commands;
using WP7CordovaClassLib.Cordova.JSON;

namespace Cordova.Extension.Commands
{
    public class Hello : BaseCommand
    {
        public void greet(string args)
        {
            string name = JsonHelper.Deserialize<string>(args);
            string message = "Hello, " + name;
            PluginResult result = new PluginResult(PluginResult.Status.OK, message);
            DispatchCommandResult(result);
        }
    }
}

对于iOS来说就稍微麻烦一些了,我们需要源文件和头文件,如下是头文件:

#import <Cordova/CDV.h>

@interface HWPHello : CDVPlugin

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

@end

下面是源文件:

#import "HWPHello.h"

@implementation HWPHello

- (void)greet:(CDVInvokedUrlCommand*)command
{

    NSString* callbackId = [command callbackId];
    NSString* name = [[command arguments] objectAtIndex:0];
    NSString* msg = [NSString stringWithFormat: @"Hello, %@", name];

    CDVPluginResult* result = [CDVPluginResult
                               resultWithStatus:CDVCommandStatus_OK
                               messageAsString:msg];

    [self success:result callbackId:callbackId];
}

@end

方法总的来说都是一样的。

Cordova插件要素

从上面的代码中我们可以发现,对于一个插件来说,我们需要下面的一些内容:

  • plugin.xml 清单文件,定义了插件的结构以及相关的设置。
  • JavaScript接口,用于插件与混合应用的接口。
  • 原生代码,提供原生功能和接口。

相关参考资料:

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签