PhoneGap 08 Android 插件介绍

来源:互联网 发布:上海软件开发工资 编辑:程序博客网 时间:2024/05/01 01:47

本节描述了在Android平台上面使用本地代码怎么实现插件。在读这一部分前,需要先阅读插件体系及其提供的javascript通用接口,这一部分同样以echo作为例子。对于其他的例子,可以查看CordovaPlugin.java.

Android插件是基于Cordova-Android,它包含通过钩子与其连接的Android WebView。插件是通过在config.xml里面的一个类来表示的。一个插件至少包含一个继承自CordovaPlugin并重写了它的execute()方法的类。最好的处理办法是插件也处理pause和resume事件,这些事件在插件之间传输比较多。需要长时间运行的请求、后台运行的服务,比如媒体播放、监听程序或者内部状态需要实现onReset()接口,它是在webview执行到新页面或者load javascript文件并刷新的时候执行。

插件映射

插件的javascript接口像下面这样使用 cordova.exec方法

exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);

它封装一个从WebView到Android本地调用的请求,调用service类的action方法,通过args传递需要的参数。

不管你是使用java文件或者jar文件作为插件,插件必须在config.xml文件中标明。

<feature name="<service_name>">        <param name="android-package" value="<full_name_including_namespace>" />    </feature>

service_name对应javascript exec调用的名称,value属性表示类的全名,否则,插件可以编译但是永远不会被调用。

写一个java插件

javascript调用可以触发一个插件请求一个本地代码,以config.xml映射的方式与插件进行通信。但是android插件到底是怎么样的呢?javascript的exec方法传递给插件的execute方法。execute大多是像下面这样的:

    @Override    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {        if ("beep".equals(action)) {            this.beep(args.getLong(0));            callbackContext.success();            return true;        }        return false;  // Returning false results in a "MethodNotFound" error.    }

javascript的exec函数的action参数对应于私有类的方法。

当检测到异常并返回错误的时候,尽快安全地处理从java中返回给javascript的错误就是相当重要的。

线程

插件的javascript代码不能运行在webview接口的主线程中。而是跟execute() 方法一样运行在WebCore线程中,如果这一过程需要跟UI交互,你需要像下面这样:

    @Override    public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {        if ("beep".equals(action)) {            final long duration = args.getLong(0);            cordova.getActivity().runOnUiThread(new Runnable() {                public void run() {                    ...                    callbackContext.success(); // Thread-safe.                }            });            return true;        }        return false;    }

如果你既不需要在主线程中运行,也不想阻塞WebCore线程,你可以像下面这样做:

    @Override    public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {        if ("beep".equals(action)) {            final long duration = args.getLong(0);            cordova.getThreadPool().execute(new Runnable() {                public void run() {                    ...                    callbackContext.success(); // Thread-safe.                }            });            return true;        }        return false;    }

Echo 插件例子

为了配合在应用程序插件里面描述的javascript echo feature 接口,使用plugin.xml向本地平台的config.xml里面注入一个 feature:

    <platform name="android">        <config-file target="config.xml" parent="/*">            <feature name="Echo">                <param name="android-package" value="org.apache.cordova.plugin.Echo"/>            </feature>        </config-file>    </platform>
然后增加下面的代码到src/org/apache/cordova/plugin/Echo.java文件里面:
    package org.apache.cordova.plugin;    import org.apache.cordova.CordovaPlugin;    import org.apache.cordova.CallbackContext;    import org.json.JSONArray;    import org.json.JSONException;    import org.json.JSONObject;    /**     * This class echoes a string called from JavaScript.     */    public class Echo extends CordovaPlugin {        @Override        public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {            if (action.equals("echo")) {                String message = args.getString(0);                this.echo(message, callbackContext);                return true;            }            return false;        }        private void echo(String message, CallbackContext callbackContext) {            if (message != null && message.length() > 0) {                callbackContext.success(message);            } else {                callbackContext.error("Expected one non-empty string argument.");            }        }    }

必须导入的包首先是CordovaPlugin,它的execute方法重写了从exec哪里接收的信息的处理方式。execute方法首先需要测试action的值,必须要能够找到想对应的方法才行,在这个例子中仅有一个echo方法,所以可以进行直接的判断,不然一般情况都需要分支结构来进行判断。如果找不到相应的函数,则会返回false,并且在javascript调用端会引起一个INVALID_ACTION错误。

接下来,通过object的getString()方法得到传递给函数的第一个参数,接着讲该参数传递给私有的echo函数,它检测参数是否为null或者空,如果是,通过callbackContext.error()调用javascript的错误处理函数。如果各种情况都通过之后,通过callbackContext.success()将原始的消息作为参数传递给javascript调用时的successFunction函数。

Android集成

Android的Intent特征允许进行间相互通信。插件必须能够访问到CordovaInterface对象,该对象可以访问到运行程序的Android主Activity。这是一个运行Android Intent必须的上下文。CordovaInterface允许插件去开启一个Activity并且从中获取结构,或者为Intent返回到应用程序的时候设置一个回调的插件。

从Cordova 2.0开始,插件不再能够直接访问到Context了,并且惰性ctx成员变量也被标记为过时。现在所有的ctx方法都存在在Context对象中,可以通过getContext()或者getActivity()得到

调试Android插件

Eclipse可以调试插件,将插件作为java源文件包含在项目中。但是仅仅只有最新的ADT工具才支持。


原文链接:Android Plugins

1 1