You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by bc...@apache.org on 2012/03/19 22:21:11 UTC
android commit: [CB-352] Support initializing DroidGap with existing
WebView,
WebViewClient and webViewChrome. [CB-353] Create PluginEntry object to use by
PluginManager.
Updated Branches:
refs/heads/master 04b3e4d84 -> 7e70d7623
[CB-352] Support initializing DroidGap with existing WebView, WebViewClient and webViewChrome.
[CB-353] Create PluginEntry object to use by PluginManager.
Project: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/commit/7e70d762
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/tree/7e70d762
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/diff/7e70d762
Branch: refs/heads/master
Commit: 7e70d762320420dddf04e61ab2543721566d5eaf
Parents: 04b3e4d
Author: Bryce Curtis <cu...@gmail.com>
Authored: Mon Mar 19 16:20:57 2012 -0500
Committer: Bryce Curtis <cu...@gmail.com>
Committed: Mon Mar 19 16:20:57 2012 -0500
----------------------------------------------------------------------
.../org/apache/cordova/CordovaWebViewClient.java | 2 +-
framework/src/org/apache/cordova/DroidGap.java | 54 +-
.../src/org/apache/cordova/api/PluginEntry.java | 119 ++++
.../src/org/apache/cordova/api/PluginManager.java | 518 ++++++++-------
4 files changed, 416 insertions(+), 277 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/7e70d762/framework/src/org/apache/cordova/CordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java
index 042f743..03ed2c1 100755
--- a/framework/src/org/apache/cordova/CordovaWebViewClient.java
+++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java
@@ -64,7 +64,7 @@ public class CordovaWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// First give any plugins the chance to handle the url themselves
- if (this.ctx.pluginManager.onOverrideUrlLoading(url)) {
+ if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) {
}
// If dialing phone (tel:5551212)
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/7e70d762/framework/src/org/apache/cordova/DroidGap.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/DroidGap.java b/framework/src/org/apache/cordova/DroidGap.java
index 3a138ff..4d1ae72 100755
--- a/framework/src/org/apache/cordova/DroidGap.java
+++ b/framework/src/org/apache/cordova/DroidGap.java
@@ -56,6 +56,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
+import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebView;
@@ -345,22 +346,33 @@ public class DroidGap extends Activity implements CordovaInterface {
}
/**
- * Create and initialize web container.
+ * Create and initialize web container with default web view objects.
*/
public void init() {
+ this.init(new WebView(DroidGap.this), new CordovaWebViewClient(this), new CordovaChromeClient(DroidGap.this));
+ }
+
+ /**
+ * Initialize web container with web view objects.
+ *
+ * @param webView
+ * @param webViewClient
+ * @param webChromeClient
+ */
+ public void init(WebView webView, WebViewClient webViewClient, WebChromeClient webChromeClient) {
LOG.d(TAG, "DroidGap.init()");
- // Create web container
- this.appView = new WebView(DroidGap.this);
+ // Set up web container
+ this.appView = webView;
this.appView.setId(100);
-
+
this.appView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT,
1.0F));
- this.appView.setWebChromeClient(new CordovaChromeClient(DroidGap.this));
- this.setWebViewClient(this.appView, new CordovaWebViewClient(this));
+ this.appView.setWebChromeClient(webChromeClient);
+ this.setWebViewClient(this.appView, webViewClient);
this.appView.setInitialScale(0);
this.appView.setVerticalScrollBarEnabled(false);
@@ -393,6 +405,9 @@ public class DroidGap extends Activity implements CordovaInterface {
// Clear cancel flag
this.cancelLoadUrl = false;
+
+ // Create plugin manager
+ this.pluginManager = new PluginManager(this.appView, this);
}
/**
@@ -498,12 +513,7 @@ public class DroidGap extends Activity implements CordovaInterface {
else {
me.callbackServer.reinit(url);
}
- if (me.pluginManager == null) {
- me.pluginManager = new PluginManager(me.appView, me);
- }
- else {
- me.pluginManager.reinit();
- }
+ me.pluginManager.init();
// If loadingDialog property, then show the App loading dialog for first page of app
String loading = null;
@@ -834,8 +844,10 @@ public class DroidGap extends Activity implements CordovaInterface {
this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onPause.fire();}catch(e){console.log('exception firing pause event from native');};");
// Forward to plugins
- this.pluginManager.onPause(this.keepRunning);
-
+ if (this.pluginManager != null) {
+ this.pluginManager.onPause(this.keepRunning);
+ }
+
// If app doesn't want to run in background
if (!this.keepRunning) {
@@ -852,7 +864,9 @@ public class DroidGap extends Activity implements CordovaInterface {
super.onNewIntent(intent);
//Forward to plugins
- this.pluginManager.onNewIntent(intent);
+ if (this.pluginManager != null) {
+ this.pluginManager.onNewIntent(intent);
+ }
}
@Override
@@ -875,8 +889,10 @@ public class DroidGap extends Activity implements CordovaInterface {
this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onResume.fire();}catch(e){console.log('exception firing resume event from native');};");
// Forward to plugins
- this.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
-
+ if (this.pluginManager != null) {
+ this.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
+ }
+
// If app doesn't want to run in background
if (!this.keepRunning || this.activityResultKeepRunning) {
@@ -942,7 +958,9 @@ public class DroidGap extends Activity implements CordovaInterface {
*/
@Deprecated
public void addService(String serviceType, String className) {
- this.pluginManager.addService(serviceType, className);
+ if (this.pluginManager != null) {
+ this.pluginManager.addService(serviceType, className);
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/7e70d762/framework/src/org/apache/cordova/api/PluginEntry.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/PluginEntry.java b/framework/src/org/apache/cordova/api/PluginEntry.java
new file mode 100755
index 0000000..450fa4c
--- /dev/null
+++ b/framework/src/org/apache/cordova/api/PluginEntry.java
@@ -0,0 +1,119 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+package org.apache.cordova.api;
+
+import android.webkit.WebView;
+
+/**
+ * This class represents a service entry object.
+ */
+public class PluginEntry {
+
+ /**
+ * The name of the service that this plugin implements
+ */
+ public String service = "";
+
+ /**
+ * The plugin class name that implements the service.
+ */
+ public String pluginClass = "";
+
+ /**
+ * The plugin object.
+ * Plugin objects are only created when they are called from JavaScript. (see PluginManager.exec)
+ * The exception is if the onload flag is set, then they are created when PluginManager is initialized.
+ */
+ public IPlugin plugin = null;
+
+ /**
+ * Flag that indicates the plugin object should be created when PluginManager is initialized.
+ */
+ public boolean onload = false;
+
+ /**
+ * Constructor
+ *
+ * @param service The name of the service
+ * @param pluginClass The plugin class name
+ * @param onload Create plugin object when HTML page is loaded
+ */
+ public PluginEntry(String service, String pluginClass, boolean onload) {
+ this.service = service;
+ this.pluginClass = pluginClass;
+ this.onload = onload;
+ }
+
+ /**
+ * Create plugin object.
+ * If plugin is already created, then just return it.
+ *
+ * @return The plugin object
+ */
+ @SuppressWarnings("unchecked")
+ public IPlugin createPlugin(WebView webView, CordovaInterface ctx) {
+ if (this.plugin != null) {
+ return this.plugin;
+ }
+ try {
+ Class c = getClassByName(this.pluginClass);
+ if (isCordovaPlugin(c)) {
+ this.plugin = (IPlugin) c.newInstance();
+ this.plugin.setContext(ctx);
+ this.plugin.setView(webView);
+ return plugin;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Error adding plugin " + this.pluginClass + ".");
+ }
+ return null;
+ }
+
+ /**
+ * Get the class.
+ *
+ * @param clazz
+ * @return
+ * @throws ClassNotFoundException
+ */
+ @SuppressWarnings("unchecked")
+ private Class getClassByName(final String clazz) throws ClassNotFoundException {
+ Class c = null;
+ if (clazz != null) {
+ c = Class.forName(clazz);
+ }
+ return c;
+ }
+
+ /**
+ * Get the interfaces that a class implements and see if it implements the
+ * org.apache.cordova.api.Plugin interface.
+ *
+ * @param c The class to check the interfaces of.
+ * @return Boolean indicating if the class implements org.apache.cordova.api.Plugin
+ */
+ @SuppressWarnings("unchecked")
+ private boolean isCordovaPlugin(Class c) {
+ if (c != null) {
+ return org.apache.cordova.api.Plugin.class.isAssignableFrom(c) || org.apache.cordova.api.IPlugin.class.isAssignableFrom(c);
+ }
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-cordova-android/blob/7e70d762/framework/src/org/apache/cordova/api/PluginManager.java
----------------------------------------------------------------------
diff --git a/framework/src/org/apache/cordova/api/PluginManager.java b/framework/src/org/apache/cordova/api/PluginManager.java
index 4367669..b253427 100755
--- a/framework/src/org/apache/cordova/api/PluginManager.java
+++ b/framework/src/org/apache/cordova/api/PluginManager.java
@@ -15,7 +15,7 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-*/
+ */
package org.apache.cordova.api;
import java.io.IOException;
@@ -29,7 +29,6 @@ import org.xmlpull.v1.XmlPullParserException;
import android.content.Intent;
import android.content.res.XmlResourceParser;
-import android.util.Log;
import android.webkit.WebView;
/**
@@ -39,321 +38,324 @@ import android.webkit.WebView;
* from JavaScript.
*/
public class PluginManager {
+ private static String TAG = "PluginManager";
+
+ // List of service entries
+ private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>();
+
+ private final CordovaInterface ctx;
+ private final WebView app;
+
+ // Flag to track first time through
+ private boolean firstRun;
- private HashMap<String, IPlugin> plugins = new HashMap<String,IPlugin>();
- private HashMap<String, String> services = new HashMap<String,String>();
-
- private final CordovaInterface ctx;
- private final WebView app;
-
// Map URL schemes like foo: to plugins that want to handle those schemes
// This would allow how all URLs are handled to be offloaded to a plugin
- protected HashMap<String, String> urlMap = new HashMap<String,String>();
-
- /**
- * Constructor.
- *
- * @param app
- * @param ctx
- */
- public PluginManager(WebView app, CordovaInterface ctx) {
- this.ctx = ctx;
- this.app = app;
- this.loadPlugins();
- }
-
- /**
- * Re-init when loading a new HTML page into webview.
- */
- public void reinit() {
-
- // Stop plugins on current HTML page and discard
- this.onPause(false);
- this.onDestroy();
- this.plugins = new HashMap<String, IPlugin>();
- }
-
- /**
- * Load plugins from res/xml/plugins.xml
- */
- public void loadPlugins() {
- int id = ctx.getResources().getIdentifier("plugins", "xml", ctx.getPackageName());
- if (id == 0) { pluginConfigurationMissing(); }
- XmlResourceParser xml = ctx.getResources().getXml(id);
- int eventType = -1;
- String pluginClass = "", pluginName = "";
- while (eventType != XmlResourceParser.END_DOCUMENT) {
- if (eventType == XmlResourceParser.START_TAG) {
- String strNode = xml.getName();
- if (strNode.equals("plugin")) {
- pluginClass = xml.getAttributeValue(null, "value");
- pluginName = xml.getAttributeValue(null, "name");
- //System.out.println("Plugin: "+name+" => "+value);
- this.addService(pluginName, pluginClass);
-
- // Create plugin at load time if attribute "onload"
- if ("true".equals(xml.getAttributeValue(null, "onload"))) {
- this.getPlugin(pluginName);
- }
- } else if (strNode.equals("url-filter")) {
- this.urlMap.put(xml.getAttributeValue(null, "value"), pluginName);
- }
- }
- try {
- eventType = xml.next();
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- /**
- * Receives a request for execution and fulfills it by finding the appropriate
- * Java class and calling it's execute method.
- *
- * PluginManager.exec can be used either synchronously or async. In either case, a JSON encoded
- * string is returned that will indicate if any errors have occurred when trying to find
- * or execute the class denoted by the clazz argument.
- *
- * @param service String containing the service to run
- * @param action String containt the action that the class is supposed to perform. This is
- * passed to the plugin execute method and it is up to the plugin developer
- * how to deal with it.
- * @param callbackId String containing the id of the callback that is execute in JavaScript if
- * this is an async plugin call.
- * @param args An Array literal string containing any arguments needed in the
- * plugin execute method.
- * @param async Boolean indicating whether the calling JavaScript code is expecting an
- * immediate return value. If true, either Cordova.callbackSuccess(...) or
- * Cordova.callbackError(...) is called once the plugin code has executed.
- *
- * @return JSON encoded string with a response message and status.
- */
- @SuppressWarnings("unchecked")
- public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async) {
- PluginResult cr = null;
- boolean runAsync = async;
- try {
- final JSONArray args = new JSONArray(jsonArgs);
- final IPlugin plugin = this.getPlugin(service);
- final CordovaInterface ctx = this.ctx;
- if (plugin != null) {
- runAsync = async && !plugin.isSynch(action);
- if (runAsync) {
- // Run this on a different thread so that this one can return back to JS
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- // Call execute on the plugin so that it can do it's thing
- PluginResult cr = plugin.execute(action, args, callbackId);
- int status = cr.getStatus();
-
- // If no result to be sent and keeping callback, then no need to sent back to JavaScript
- if ((status == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
- }
-
- // Check the success (OK, NO_RESULT & !KEEP_CALLBACK)
- else if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) {
- ctx.sendJavascript(cr.toSuccessCallbackString(callbackId));
- }
-
- // If error
- else {
- ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
- }
- } catch (Exception e) {
- PluginResult cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
- ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
- }
- }
- });
- thread.start();
- return "";
- } else {
- // Call execute on the plugin so that it can do it's thing
- cr = plugin.execute(action, args, callbackId);
-
- // If no result to be sent and keeping callback, then no need to sent back to JavaScript
- if ((cr.getStatus() == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
- return "";
- }
- }
- }
- } catch (JSONException e) {
- System.out.println("ERROR: "+e.toString());
- cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
- }
- // if async we have already returned at this point unless there was an error...
- if (runAsync) {
- if (cr == null) {
- cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
- }
- ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
- }
- return ( cr != null ? cr.getJSONString() : "{ status: 0, message: 'all good' }" );
- }
-
- /**
- * Get the class.
- *
- * @param clazz
- * @return
- * @throws ClassNotFoundException
- */
- @SuppressWarnings("unchecked")
- private Class getClassByName(final String clazz) throws ClassNotFoundException {
- Class c = null;
- if (clazz != null) {
- c = Class.forName(clazz);
- }
- return c;
- }
-
- /**
- * Get the interfaces that a class implements and see if it implements the
- * org.apache.cordova.api.Plugin interface.
- *
- * @param c The class to check the interfaces of.
- * @return Boolean indicating if the class implements org.apache.cordova.api.Plugin
- */
- @SuppressWarnings("unchecked")
- private boolean isCordovaPlugin(Class c) {
- if (c != null) {
- return org.apache.cordova.api.Plugin.class.isAssignableFrom(c) || org.apache.cordova.api.IPlugin.class.isAssignableFrom(c);
- }
- return false;
- }
+ protected HashMap<String, String> urlMap = new HashMap<String, String>();
/**
- * Add plugin to be loaded and cached. This creates an instance of the plugin.
- * If plugin is already created, then just return it.
+ * Constructor.
*
- * @param className The class to load
- * @param clazz The class object (must be a class object of the className)
- * @param callbackId The callback id to use when calling back into JavaScript
- * @return The plugin
+ * @param app
+ * @param ctx
+ */
+ public PluginManager(WebView app, CordovaInterface ctx) {
+ this.ctx = ctx;
+ this.app = app;
+ this.firstRun = true;
+ }
+
+ /**
+ * Init when loading a new HTML page into webview.
+ */
+ public void init() {
+ LOG.d(TAG, "init()");
+
+ // If first time, then load plugins from plugins.xml file
+ if (firstRun) {
+ this.loadPlugins();
+ firstRun = false;
+ }
+
+ // Stop plugins on current HTML page and discard plugin objects
+ else {
+ this.onPause(false);
+ this.onDestroy();
+ this.clearPluginObjects();
+ }
+
+ // Start up all plugins that have onload specified
+ this.startupPlugins();
+ }
+
+ /**
+ * Load plugins from res/xml/plugins.xml
+ */
+ public void loadPlugins() {
+ int id = ctx.getResources().getIdentifier("plugins", "xml", ctx.getPackageName());
+ if (id == 0) {
+ pluginConfigurationMissing();
+ }
+ XmlResourceParser xml = ctx.getResources().getXml(id);
+ int eventType = -1;
+ String service = "", pluginClass = "";
+ boolean onload = false;
+ PluginEntry entry = null;
+ while (eventType != XmlResourceParser.END_DOCUMENT) {
+ if (eventType == XmlResourceParser.START_TAG) {
+ String strNode = xml.getName();
+ if (strNode.equals("plugin")) {
+ service = xml.getAttributeValue(null, "name");
+ pluginClass = xml.getAttributeValue(null, "value");
+ // System.out.println("Plugin: "+name+" => "+value);
+ onload = "true".equals(xml.getAttributeValue(null, "onload"));
+ entry = new PluginEntry(service, pluginClass, onload);
+ this.addService(entry);
+ } else if (strNode.equals("url-filter")) {
+ this.urlMap.put(xml.getAttributeValue(null, "value"), service);
+ }
+ }
+ try {
+ eventType = xml.next();
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Delete all plugin objects.
*/
- @SuppressWarnings("unchecked")
- private IPlugin addPlugin(String pluginName, String className) {
- try {
- Class c = getClassByName(className);
- if (isCordovaPlugin(c)) {
- IPlugin plugin = (IPlugin)c.newInstance();
- this.plugins.put(className, plugin);
- plugin.setContext(this.ctx);
- plugin.setView(this.app);
- return plugin;
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("Error adding plugin "+className+".");
- }
- return null;
+ public void clearPluginObjects() {
+ for (PluginEntry entry : this.entries.values()) {
+ entry.plugin = null;
+ }
}
-
+
/**
- * Get the loaded plugin.
+ * Create plugins objects that have onload set.
+ */
+ public void startupPlugins() {
+ for (PluginEntry entry : this.entries.values()) {
+ if (entry.onload) {
+ entry.createPlugin(this.app, this.ctx);
+ }
+ }
+ }
+
+ /**
+ * Receives a request for execution and fulfills it by finding the appropriate
+ * Java class and calling it's execute method.
+ *
+ * PluginManager.exec can be used either synchronously or async. In either case, a JSON encoded
+ * string is returned that will indicate if any errors have occurred when trying to find
+ * or execute the class denoted by the clazz argument.
*
- * If the plugin is not already loaded then load it.
+ * @param service String containing the service to run
+ * @param action String containt the action that the class is supposed to perform. This is
+ * passed to the plugin execute method and it is up to the plugin developer
+ * how to deal with it.
+ * @param callbackId String containing the id of the callback that is execute in JavaScript if
+ * this is an async plugin call.
+ * @param args An Array literal string containing any arguments needed in the
+ * plugin execute method.
+ * @param async Boolean indicating whether the calling JavaScript code is expecting an
+ * immediate return value. If true, either Cordova.callbackSuccess(...) or
+ * Cordova.callbackError(...) is called once the plugin code has executed.
*
- * @param className The class of the loaded plugin.
- * @return
+ * @return JSON encoded string with a response message and status.
*/
- private IPlugin getPlugin(String pluginName) {
- String className = this.services.get(pluginName);
- if (this.plugins.containsKey(className)) {
- return this.plugins.get(className);
- } else {
- return this.addPlugin(pluginName, className);
- }
+ @SuppressWarnings("unchecked")
+ public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async) {
+ PluginResult cr = null;
+ boolean runAsync = async;
+ try {
+ final JSONArray args = new JSONArray(jsonArgs);
+ final IPlugin plugin = this.getPlugin(service);
+ final CordovaInterface ctx = this.ctx;
+ if (plugin != null) {
+ runAsync = async && !plugin.isSynch(action);
+ if (runAsync) {
+ // Run this on a different thread so that this one can return back to JS
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ // Call execute on the plugin so that it can do it's thing
+ PluginResult cr = plugin.execute(action, args, callbackId);
+ int status = cr.getStatus();
+
+ // If no result to be sent and keeping callback, then no need to sent back to JavaScript
+ if ((status == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
+ }
+
+ // Check the success (OK, NO_RESULT & !KEEP_CALLBACK)
+ else if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) {
+ ctx.sendJavascript(cr.toSuccessCallbackString(callbackId));
+ }
+
+ // If error
+ else {
+ ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
+ }
+ } catch (Exception e) {
+ PluginResult cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
+ ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
+ }
+ }
+ });
+ thread.start();
+ return "";
+ } else {
+ // Call execute on the plugin so that it can do it's thing
+ cr = plugin.execute(action, args, callbackId);
+
+ // If no result to be sent and keeping callback, then no need to sent back to JavaScript
+ if ((cr.getStatus() == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
+ return "";
+ }
+ }
+ }
+ } catch (JSONException e) {
+ System.out.println("ERROR: " + e.toString());
+ cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ }
+ // if async we have already returned at this point unless there was an error...
+ if (runAsync) {
+ if (cr == null) {
+ cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
+ }
+ ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
+ }
+ return (cr != null ? cr.getJSONString() : "{ status: 0, message: 'all good' }");
}
-
+
/**
- * Add a class that implements a service.
- * This does not create the class instance. It just maps service name to class name.
+ * Get the plugin object that implements the service.
+ * If the plugin object does not already exist, then create it.
+ * If the service doesn't exist, then return null.
*
- * @param serviceType
- * @param className
+ * @param service The name of the service.
+ * @return IPlugin or null
*/
- public void addService(String serviceType, String className) {
- this.services.put(serviceType, className);
+ private IPlugin getPlugin(String service) {
+ PluginEntry entry = entries.get(service);
+ if (entry == null) {
+ return null;
+ }
+ IPlugin plugin = entry.plugin;
+ if (plugin == null) {
+ plugin = entry.createPlugin(this.app, this.ctx);
+ }
+ return plugin;
}
/**
- * Called when the system is about to start resuming a previous activity.
+ * Add a plugin class that implements a service to the service entry table.
+ * This does not create the plugin object instance.
*
- * @param multitasking Flag indicating if multitasking is turned on for app
+ * @param service The service name
+ * @param className The plugin class name
+ */
+ public void addService(String service, String className) {
+ PluginEntry entry = new PluginEntry(service, className, false);
+ this.addService(entry);
+ }
+
+ /**
+ * Add a plugin class that implements a service to the service entry table.
+ * This does not create the plugin object instance.
+ *
+ * @param entry The plugin entry
+ */
+ public void addService(PluginEntry entry) {
+ this.entries.put(entry.service, entry);
+ }
+
+ /**
+ * Called when the system is about to start resuming a previous activity.
+ *
+ * @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onPause(boolean multitasking) {
- for (IPlugin plugin : this.plugins.values()) {
- plugin.onPause(multitasking);
+ for (PluginEntry entry : this.entries.values()) {
+ if (entry.plugin != null) {
+ entry.plugin.onPause(multitasking);
+ }
}
}
-
+
/**
- * Called when the activity will start interacting with the user.
+ * Called when the activity will start interacting with the user.
*
- * @param multitasking Flag indicating if multitasking is turned on for app
+ * @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onResume(boolean multitasking) {
- for (IPlugin plugin : this.plugins.values()) {
- plugin.onResume(multitasking);
+ for (PluginEntry entry : this.entries.values()) {
+ if (entry.plugin != null) {
+ entry.plugin.onResume(multitasking);
+ }
}
}
/**
- * The final call you receive before your activity is destroyed.
+ * The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
- for (IPlugin plugin : this.plugins.values()) {
- plugin.onDestroy();
+ for (PluginEntry entry : this.entries.values()) {
+ if (entry.plugin != null) {
+ entry.plugin.onDestroy();
+ }
}
}
/**
- * Send a message to all plugins.
+ * Send a message to all plugins.
*
- * @param id The message id
- * @param data The message data
+ * @param id The message id
+ * @param data The message data
*/
public void postMessage(String id, Object data) {
- for (IPlugin plugin : this.plugins.values()) {
- plugin.onMessage(id, data);
+ for (PluginEntry entry : this.entries.values()) {
+ if (entry.plugin != null) {
+ entry.plugin.onMessage(id, data);
+ }
}
}
/**
- * Called when the activity receives a new intent.
- */
+ * Called when the activity receives a new intent.
+ */
public void onNewIntent(Intent intent) {
- for (IPlugin plugin : this.plugins.values()) {
- plugin.onNewIntent(intent);
+ for (PluginEntry entry : this.entries.values()) {
+ if (entry.plugin != null) {
+ entry.plugin.onNewIntent(intent);
+ }
}
}
/**
* Called when the URL of the webview changes.
*
- * @param url The URL that is being changed to.
- * @return Return false to allow the URL to load, return true to prevent the URL from loading.
+ * @param url The URL that is being changed to.
+ * @return Return false to allow the URL to load, return true to prevent the URL from loading.
*/
public boolean onOverrideUrlLoading(String url) {
- Iterator<Entry<String, String>> it = this.urlMap.entrySet().iterator();
+ Iterator<Entry<String, String>> it = this.urlMap.entrySet().iterator();
while (it.hasNext()) {
HashMap.Entry<String, String> pairs = it.next();
if (url.startsWith(pairs.getKey())) {
- return this.getPlugin(pairs.getValue()).onOverrideUrlLoading(url);
+ return this.getPlugin(pairs.getValue()).onOverrideUrlLoading(url);
}
}
- return false;
+ return false;
}
- private void pluginConfigurationMissing() {
- System.err.println("=====================================================================================");
- System.err.println("ERROR: plugin.xml is missing. Add res/xml/plugins.xml to your project.");
- System.err.println("https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=blob;f=framework/res/xml/plugins.xml");
- System.err.println("=====================================================================================");
- }
+ private void pluginConfigurationMissing() {
+ System.err.println("=====================================================================================");
+ System.err.println("ERROR: plugin.xml is missing. Add res/xml/plugins.xml to your project.");
+ System.err.println("https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=blob;f=framework/res/xml/plugins.xml");
+ System.err.println("=====================================================================================");
+ }
}