You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2012/07/19 00:36:24 UTC
docs commit: [CB-1069] plugin documentation for android
Updated Branches:
refs/heads/master 80e650655 -> 8f89b497c
[CB-1069] plugin documentation for android
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-docs/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-docs/commit/8f89b497
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-docs/tree/8f89b497
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-docs/diff/8f89b497
Branch: refs/heads/master
Commit: 8f89b497c1d38215288e65dd6e6853556cdf2d11
Parents: 80e6506
Author: Fil Maj <ma...@gmail.com>
Authored: Wed Jul 18 15:38:57 2012 -0700
Committer: Fil Maj <ma...@gmail.com>
Committed: Wed Jul 18 15:39:11 2012 -0700
----------------------------------------------------------------------
.../edge/guide/plugin-development/android/index.md | 165 +++++++++------
1 files changed, 103 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-docs/blob/8f89b497/docs/en/edge/guide/plugin-development/android/index.md
----------------------------------------------------------------------
diff --git a/docs/en/edge/guide/plugin-development/android/index.md b/docs/en/edge/guide/plugin-development/android/index.md
index 5734e86..2fc8761 100644
--- a/docs/en/edge/guide/plugin-development/android/index.md
+++ b/docs/en/edge/guide/plugin-development/android/index.md
@@ -17,29 +17,43 @@ license: Licensed to the Apache Software Foundation (ASF) under one
under the License.
---
-Developing a Plugin on Android
-==============================
+# Developing a Plugin on Android
-Writing a plugin requires an understanding of the architecture of Cordova-Android. Cordova consists
-of a WebView with hooks attached to it. These plugins are represented as sub-classes in the config.xml
+Writing a plugin requires an understanding of the architecture of Cordova-Android. Cordova-Android consists
+of an Android WebView with hooks attached to it. These plugins are represented as class mappings in the config.xml
file.
A plugin will consist of at least a single Java class that extends the `Plugin` class. A plugin **must**
have a method called `execute` that must return a `PluginResult` object. In addition to this, there is a best practice that
the plugin should handle pause and resume events, and should handle message passing between plugins.
-Writing the Java portion:
---------------------------------
-Assuming that you know how the JavaScript portion of plugins work, you must use the `exec` method as follows:
+## Plugin Class Mapping
+
+The JavaScript portion of a plugin always uses the `cordova.exec` method as follows:
exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
This will marshall a request from the WebView to the Android native
side, more or less boiling down to calling the `action` method on the
-`service` class, with the arguments passed in the `args` Array. Then you must handle what
-comes into the plugin in the execute command. Most execute commands look like the following:
+`service` class, with the arguments passed in the `args` Array.
+
+Whether you distribute your plugin as Java file or as a JAR of its own, the plugin must be added to the `config.xml` file in your Cordova-Android application's `res/xml/` folder.
+
+ <plugin name="<service_name>" value="<full_name_including_namespace>"/>
+
+The service name should match what you use in the JavaScript `exec` call, and the value will be the full name of the Java class including the namespace. Without this added, the plugin may compile but
+will not be reachable by Cordova.
+
+## Writing an Android Java Plugin
+
+We have JavaScript to fire off a plugin request to the native side. We
+have the Android Java plugin mapped properly via the `config.xml` file.
+So what does the final Android Java Plugin class look like?
+
+What gets dispatched to the plugin via JavaScript's `exec` function gets
+passed into the Plugin class's `execute` method. Most `execute`
+implementations look like this:
-{{
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
@@ -48,66 +62,93 @@ comes into the plugin in the execute command. Most execute commands look like th
if (action.equals("beep")) {
this.beep(args.getLong(0));
}
- else if (action.equals("vibrate")) {
- this.vibrate(args.getLong(0));
- }
- else if (action.equals("alert")) {
- this.alert(args.getString(0), args.getString(1), args.getString(2), callbackId);
- PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
- r.setKeepCallback(true);
- return r;
- }
- else if (action.equals("confirm")) {
- this.confirm(args.getString(0), args.getString(1), args.getString(2), callbackId);
- PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
- r.setKeepCallback(true);
- return r;
- }
- else if (action.equals("activityStart")) {
- this.activityStart(args.getString(0), args.getString(1));
- }
- else if (action.equals("activityStop")) {
- this.activityStop();
- }
- else if (action.equals("progressStart")) {
- this.progressStart(args.getString(0), args.getString(1));
- }
- else if (action.equals("progressValue")) {
- this.progressValue(args.getInt(0));
- }
- else if (action.equals("progressStop")) {
- this.progressStop();
- }
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
-}}
-
-When catching exceptions and returning errors, it's important that the error we return to JavaScript match the Java exception as much as possible, otherwise the developer won't know what
-is going on with the device.
-Adding your plugin to a project:
----------------------------------
-Whether you distribute your plugin as Java file, or whether it's in a JAR of its own, the plugin must be added with this XML:
-{{
- <plugin name="<service_name>" value="<full_name_including_namespace>"/>
-}}
+Essentially we compare the value of the `action` parameter, and dispatch
+the request off to a (private) method in the class, optionally passing
+some of the parameters to the method.
+
+When catching exceptions and returning errors, it's important that the error we return to JavaScript match the Java exception as much as possible, for clarity.
+
+### Echo Plugin Android Plugin
+
+We would add the following to our config.xml:
+
+ <plugin name="Echo" value="org.apache.cordova.plugin.Echo" />
+
+Then we would add the following file to
+`src/org/apache/cordova/plugin/Echo.java` inside our Cordova-Android
+application:
+
+ package org.apache.cordova.plugin;
+
+ import org.apache.cordova.api.Plugin;
+ import org.apache.cordova.api.PluginResult;
+ import org.json.JSONArray;
+ import org.json.JSONException;
+ import org.json.JSONObject;
+
+ /**
+ * This class echoes a string called from JavaScript.
+ */
+ public class App extends Plugin {
+
+ /**
+ * Executes the request and returns PluginResult.
+ *
+ * @param action The action to execute.
+ * @param args JSONArry of arguments for the plugin.
+ * @param callbackId The callback id used when calling back into JavaScript.
+ * @return A PluginResult object with a status and message.
+ */
+ public PluginResult execute(String action, JSONArray args, String callbackId) {
+ try {
+ if (action.equals("echo")) {
+ String echo = args.getString(0);
+ if (echo != null && echo.length() > 0) {
+ return new PluginResult(PluginResult.Status.OK, echo);
+ } else {
+ return new PluginResult(PluginResult.Status.ERROR);
+ }
+ } else {
+ return new PluginResult(PluginResult.Status.INVALID_ACTION);
+ }
+ } catch (JSONException e) {
+ return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ }
+ }
+ }
-The service name will be what you use in exec to call the plugin, and the value will be the full name of the Java class including the namespace. Withotu this added, the plugin may compile but
-will not be reachable by Cordova.
+Let's take a look at the code. At the top we have all of the necessary
+Cordova `import`s. Our class extends from `Plugin` - very important. The
+one method that the `Plugin` interface demands is the `execute` method.
+The method first compares against `action`: this plugin only supports
+one action, the `echo` action. Any other action will return a
+`PluginResult` with a status of `INVALID_ACTION` - this will translate
+into an error callback invocation on the JavaScript side. Next, we grab
+the echo string using the `getString` method on our `args`, telling it
+we want to get the 0th parameter in the parameter array. We do a bit of
+parameter checking: make sure it is not `null`, and make sure it is not
+a zero-length string. If it is, we return a `PluginResult` with an
+`ERROR` status (which, by now, you should now will invoke the error
+callback). If all of those checks pass, then we return a `PluginResult`
+with an `OK` status, and pass in the `echo` string we received in the
+first place as a parameter. This will finally translate into a success
+callback invocation on the JavaScript side. It will also pass the `echo`
+parameter as a parameter into the JavaScript success callback function.
+
+## Debugging Plugins
-Debugging Plugins
------------------------
Eclipse can be used to debug an Android project, and the plugins can be debugged if the Java source is included in the project. Only the latest version of the Android Dev Tools is known to allow source code attachment to JAR dependencies, this is not fully supported at this time.
-Common Pitfalls:
--------------------------------
-* Plugins have access to a CordovaInterface object. This object has access to the activity that is running the application, which of course, is the context required to launch
-a new intent. The CordovaInterface allows plugins to start an activity for a result, and to set the callback plugin for when the intent comes back to the application. This is important, since the
-intents system is how Android communicates between processes.
-
-* Plugins do not have direct access to the Context as they have in the past. ctx id deprecated, and will be removed six months after 2.0 is released. All the methods that ctx have exist on the context, so both getContext() and getActivity() are capable of returning the proper object required.
+## Common Pitfalls
-* Avoid calling JavaScript using webView.loadUrl(). The reason we have a callback server is to allow JavaScript execution to be thread-safe, and loadUrl explicitly interrupts the UI thread, and can affect the usability of your plugin.
+* Plugins have access to a `CordovaInterface` object. This object has access to the Android `Activity` that is running the application. This is the `Context` required to launch
+a new Android `Intent`. The `CordovaInterface` allows plugins to start an `Activity` for a result, and to set the callback plugin for when the `Intent` comes back to the application. This is important, since the
+`Intent`s system is how Android communicates between processes.
+* Plugins do not have direct access to the `Context` as they have in the past. The legacy `ctx` member is deprecated, and will be removed six months after 2.0 is released. All the methods that `ctx` has exist on the `Context`, so both `getContext()` and `getActivity()` are capable of returning the proper object required.
+* Avoid calling JavaScript using `webView.loadUrl()`. The reason we have a callback server is to allow JavaScript execution to be thread-safe, and `loadUrl` explicitly interrupts the UI thread, and can affect the usability of your plugin.