Create CordovaPlugin.java and make Plugin.java a compatibility shim.

The intent of this is to encourage plugins to execute synchronously
when appropriate by not defaulting to using a background thread.

This will also encourage plugins that do run asynchronously to run some
of its logic synchronously before dispatching to a background thread.
This is required for tasks that can be abort()ed, such as
FileTransfer. (CB-1532)

This also makes it possible to lazily parse the JSON args, which is
important for large payloads. (CB-1530)
This commit is contained in:
Andrew Grieve 2012-09-24 23:37:34 -04:00
parent ec3c5b2ca2
commit 6e6e0275ad
10 changed files with 368 additions and 222 deletions

View File

@ -22,9 +22,9 @@ import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
import org.json.JSONException;
import org.json.JSONObject;
@ -162,7 +162,7 @@ public class DroidGap extends Activity implements CordovaInterface {
String baseUrl = null;
// Plugin to call when activity result is received
protected Plugin activityResultCallback = null;
protected CordovaPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning;
// Default background color for activity
@ -773,7 +773,7 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param intent The intent to start
* @param requestCode The request code that is passed to callback to identify the activity
*/
public void startActivityForResult(Plugin command, Intent intent, int requestCode) {
public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
this.activityResultCallback = command;
this.activityResultKeepRunning = this.keepRunning;
@ -798,13 +798,13 @@ public class DroidGap extends Activity implements CordovaInterface {
*/
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Plugin callback = this.activityResultCallback;
CordovaPlugin callback = this.activityResultCallback;
if (callback != null) {
callback.onActivityResult(requestCode, resultCode, intent);
}
}
public void setActivityResultCallback(Plugin plugin) {
public void setActivityResultCallback(CordovaPlugin plugin) {
this.activityResultCallback = plugin;
}

View File

@ -18,40 +18,27 @@
*/
package org.apache.cordova;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
public class Echo extends Plugin {
public class Echo extends CordovaPlugin {
/**
* 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 {
String result = args.getString(0);
if ("echo".equals(action) || "echoAsync".equals(action)) {
return new PluginResult(PluginResult.Status.OK, result);
}
return new PluginResult(PluginResult.Status.INVALID_ACTION);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
final String result = args.getString(0);
if ("echo".equals(action)) {
callbackContext.success(result);
return true;
} else if ("echoAsync".equals(action)) {
cordova.getThreadPool().execute(new Runnable() {
@Override public void run() {
callbackContext.success(result);
}
});
return true;
}
}
/**
* Identifies if action to be executed returns a value and should be run synchronously.
*
* @param action The action to execute
* @return T=returns value
*/
public boolean isSynch(String action) {
return "echo".equals(action);
return false;
}
}

View File

@ -44,7 +44,8 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
@ -55,7 +56,7 @@ import android.os.Build;
import android.util.Log;
import android.webkit.CookieManager;
public class FileTransfer extends Plugin {
public class FileTransfer extends CordovaPlugin {
private static final String LOG_TAG = "FileTransfer";
private static final String LINE_START = "--";
@ -116,7 +117,7 @@ public class FileTransfer extends Plugin {
* @see org.apache.cordova.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
*/
@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
if (action.equals("upload") || action.equals("download")) {
String source = null;
String target = null;
@ -129,15 +130,18 @@ public class FileTransfer extends Plugin {
}
if (action.equals("upload")) {
return upload(URLDecoder.decode(source), target, args, callbackId);
upload(URLDecoder.decode(source), target, args, callbackContext);
} else {
return download(source, target, args, callbackId);
download(source, target, args, callbackContext);
}
return true;
} else if (action.equals("abort")) {
return abort(args);
} else {
return new PluginResult(PluginResult.Status.INVALID_ACTION);
String objectId = args.getString(0);
abort(objectId);
callbackContext.success();
return true;
}
return false;
}
/**
@ -145,7 +149,7 @@ public class FileTransfer extends Plugin {
* @param source Full path of the file on the file system
* @param target URL of the server to receive the file
* @param args JSON Array of args
* @param callbackId callback id for optional progress reports
* @param callbackContext callback id for optional progress reports
*
* args[2] fileKey Name of file request parameter
* args[3] fileName File name to be used on server
@ -153,7 +157,7 @@ public class FileTransfer extends Plugin {
* args[5] params key:value pairs of user-defined parameters
* @return FileUploadResult containing result of upload request
*/
private PluginResult upload(String source, String target, JSONArray args, String callbackId) {
private PluginResult upload(String source, String target, JSONArray args, CallbackContext callbackContext) {
Log.d(LOG_TAG, "upload " + source + " to " + target);
HttpURLConnection conn = null;
@ -350,7 +354,7 @@ public class FileTransfer extends Plugin {
progress.setLoaded(totalBytes);
PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
progressResult.setKeepCallback(true);
success(progressResult, callbackId);
callbackContext.sendPluginResult(progressResult);
}
synchronized (abortTriggered) {
if (objectId != null && abortTriggered.contains(objectId)) {
@ -536,7 +540,7 @@ public class FileTransfer extends Plugin {
* @param target Full path of the file on the file system
* @return JSONObject the downloaded file
*/
private PluginResult download(String source, String target, JSONArray args, String callbackId) {
private PluginResult download(String source, String target, JSONArray args, CallbackContext callbackContext) {
Log.d(LOG_TAG, "download " + source + " to " + target);
HttpURLConnection connection = null;
@ -617,7 +621,7 @@ public class FileTransfer extends Plugin {
progress.setLoaded(totalBytes);
PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
progressResult.setKeepCallback(true);
success(progressResult, callbackId);
callbackContext.sendPluginResult(progressResult);
}
synchronized (abortTriggered) {
if (objectId != null && abortTriggered.contains(objectId)) {

View File

@ -0,0 +1,90 @@
package org.apache.cordova.api;
import android.util.Log;
import org.apache.cordova.CordovaWebView;
import org.json.JSONObject;
public class CallbackContext {
private static final String LOG_TAG = "CordovaPlugin";
private String callbackId;
private CordovaWebView webView;
private boolean finished;
private int changingThreads;
public CallbackContext(String callbackId, CordovaWebView webView) {
this.callbackId = callbackId;
this.webView = webView;
}
public boolean isFinished() {
return finished;
}
public boolean isChangingThreads() {
return changingThreads > 0;
}
public String getCallbackId() {
return callbackId;
}
public void sendPluginResult(PluginResult pluginResult) {
synchronized (this) {
if (finished) {
Log.w(LOG_TAG, "Attempted to send a second callback for ID: " + callbackId + "\nResult was: " + pluginResult.getMessage());
return;
} else {
finished = !pluginResult.getKeepCallback();
}
}
webView.sendPluginResult(pluginResult, callbackId);
}
/**
* Helper for success callbacks that just returns the Status.OK by default
*
* @param message The message to add to the success result.
*/
public void success(JSONObject message) {
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
}
/**
* Helper for success callbacks that just returns the Status.OK by default
*
* @param message The message to add to the success result.
*/
public void success(String message) {
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
}
/**
* Helper for success callbacks that just returns the Status.OK by default
*
* @param message The message to add to the success result.
*/
public void success() {
sendPluginResult(new PluginResult(PluginResult.Status.OK));
}
/**
* Helper for error callbacks that just returns the Status.ERROR by default
*
* @param message The message to add to the error result.
*/
public void error(JSONObject message) {
sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
}
/**
* Helper for error callbacks that just returns the Status.ERROR by default
*
* @param message The message to add to the error result.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void error(String message) {
sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
}
}

View File

@ -38,15 +38,14 @@ public interface CordovaInterface {
* @param intent The intent to start
* @param requestCode The request code that is passed to callback to identify the activity
*/
abstract public void startActivityForResult(Plugin command, Intent intent, int requestCode);
abstract public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode);
/**
* Set the plugin to be called when a sub-activity exits.
*
* @param plugin The plugin on which onActivityResult is to be called
*/
abstract public void setActivityResultCallback(Plugin plugin);
abstract public void setActivityResultCallback(CordovaPlugin plugin);
/**
* Get the Android activity.

View File

@ -0,0 +1,151 @@
/*
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 org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
/**
* Plugins must extend this class and override one of the execute methods.
*/
public class CordovaPlugin {
public String id;
public CordovaWebView webView; // WebView object
public CordovaInterface cordova;
/**
* @param ctx The context of the main Activity.
*/
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
assert this.cordova == null;
this.cordova = cordova;
this.webView = webView;
}
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action The action to execute.
* @param rawArgs The exec() arguments in JSON form.
* @param callbackId The callback id used when calling back into JavaScript.
* @return Whether the action was valid.
*/
public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
JSONArray args = new JSONArray(rawArgs);
return execute(action, args, callbackContext);
}
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action The action to execute.
* @param args The exec() arguments.
* @param callbackId The callback id used when calling back into JavaScript.
* @return Whether the action was valid.
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
return false;
}
/**
* 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) {
}
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onResume(boolean multitasking) {
}
/**
* Called when the activity receives a new intent.
*/
public void onNewIntent(Intent intent) {
}
/**
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
}
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
* @return Object to stop propagation or null
*/
public Object onMessage(String id, Object data) {
return null;
}
/**
* Called when an activity you launched exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
*
* @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
}
/**
* By specifying a <url-filter> in plugins.xml you can map a URL (using startsWith atm) to this method.
*
* @param url The URL that is trying to be loaded in the Cordova webview.
* @return Return true to prevent the URL from loading. Default is false.
*/
public boolean onOverrideUrlLoading(String url) {
return false;
}
/**
* Called when the WebView does a top-level navigation or refreshes.
*
* Plugins should stop any long-running processes and clean up internal state.
*
* Does nothing by default.
*/
public void onReset() {
}
}

View File

@ -65,13 +65,13 @@ public class LegacyContext implements CordovaInterface {
}
@Deprecated
public void setActivityResultCallback(Plugin arg0) {
public void setActivityResultCallback(CordovaPlugin arg0) {
Log.i(LOG_TAG, "Replace ctx.setActivityResultCallback() with cordova.setActivityResultCallback()");
this.cordova.setActivityResultCallback(arg0);
}
@Deprecated
public void startActivityForResult(Plugin arg0, Intent arg1, int arg2) {
public void startActivityForResult(CordovaPlugin arg0, Intent arg1, int arg2) {
Log.i(LOG_TAG, "Replace ctx.startActivityForResult() with cordova.startActivityForResult()");
this.cordova.startActivityForResult(arg0, arg1, arg2);
}

View File

@ -20,42 +20,29 @@ package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Intent;
import android.util.Log;
/**
* Plugin interface must be implemented by any plugin classes.
*
* The execute method is called by the PluginManager.
* Legacy Plugin class. This acts as a shim to support the old execute() signature.
* New plugins should extend CordovaPlugin directly.
*/
public abstract class Plugin {
public String id;
public CordovaWebView webView; // WebView object
@Deprecated
public abstract class Plugin extends CordovaPlugin {
public LegacyContext ctx; // LegacyContext object
public CordovaInterface cordova;
/**
* 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 abstract PluginResult execute(String action, JSONArray args, String callbackId);
/**
* Identifies if action to be executed returns a value and should be run synchronously.
*
* @param action The action to execute
* @return T=returns value
*/
public boolean isSynch(String action) {
return false;
}
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
this.setContext(cordova);
this.setView(webView);
}
/**
* Sets the context of the Plugin. This can then be used to do things like
@ -77,66 +64,35 @@ public abstract class Plugin {
public void setView(CordovaWebView webView) {
this.webView = webView;
}
/**
* 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) {
}
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking Flag indicating if multitasking is turned on for app
*/
public void onResume(boolean multitasking) {
}
/**
* Called when the activity receives a new intent.
*/
public void onNewIntent(Intent intent) {
}
/**
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
}
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
* @return Object to stop propagation or null
*/
public Object onMessage(String id, Object data) {
return null;
}
/**
* Called when an activity you launched exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
*
* @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
}
/**
* By specifying a <url-filter> in plugins.xml you can map a URL (using startsWith atm) to this method.
*
* @param url The URL that is trying to be loaded in the Cordova webview.
* @return Return true to prevent the URL from loading. Default is false.
*/
public boolean onOverrideUrlLoading(String url) {
return false;
@Override
public boolean execute(final String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
final String callbackId = callbackContext.getCallbackId();
boolean runAsync = !isSynch(action);
if (runAsync) {
// Run this on a different thread so that this one can return back to JS
cordova.getThreadPool().execute(new Runnable() {
public void run() {
PluginResult cr;
try {
cr = execute(action, args, callbackId);
} catch (Throwable e) {
cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
}
sendPluginResult(cr, callbackId);
}
});
} else {
PluginResult cr = execute(action, args, callbackId);
// Interpret a null response as NO_RESULT, which *does* clear the callbacks on the JS side.
if (cr == null) {
cr = new PluginResult(PluginResult.Status.NO_RESULT);
}
callbackContext.sendPluginResult(cr);
}
return true;
}
/**
@ -161,8 +117,8 @@ public abstract class Plugin {
* that execute should return null and the callback from the async operation can
* call success(...) or error(...)
*
* @param pluginResult The result to return.
* @param callbackId The callback id used when calling back into JavaScript.
* @param pluginResult The result to return.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void success(PluginResult pluginResult, String callbackId) {
this.webView.sendPluginResult(pluginResult, callbackId);
@ -171,8 +127,8 @@ public abstract class Plugin {
/**
* Helper for success callbacks that just returns the Status.OK by default
*
* @param message The message to add to the success result.
* @param callbackId The callback id used when calling back into JavaScript.
* @param message The message to add to the success result.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void success(JSONObject message, String callbackId) {
this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK, message), callbackId);
@ -181,8 +137,8 @@ public abstract class Plugin {
/**
* Helper for success callbacks that just returns the Status.OK by default
*
* @param message The message to add to the success result.
* @param callbackId The callback id used when calling back into JavaScript.
* @param message The message to add to the success result.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void success(String message, String callbackId) {
this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK, message), callbackId);
@ -191,8 +147,8 @@ public abstract class Plugin {
/**
* Call the JavaScript error callback for this plugin.
*
* @param pluginResult The result to return.
* @param callbackId The callback id used when calling back into JavaScript.
* @param pluginResult The result to return.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void error(PluginResult pluginResult, String callbackId) {
this.webView.sendPluginResult(pluginResult, callbackId);
@ -201,8 +157,8 @@ public abstract class Plugin {
/**
* Helper for error callbacks that just returns the Status.ERROR by default
*
* @param message The message to add to the error result.
* @param callbackId The callback id used when calling back into JavaScript.
* @param message The message to add to the error result.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void error(JSONObject message, String callbackId) {
this.webView.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message), callbackId);
@ -211,20 +167,11 @@ public abstract class Plugin {
/**
* Helper for error callbacks that just returns the Status.ERROR by default
*
* @param message The message to add to the error result.
* @param callbackId The callback id used when calling back into JavaScript.
* @param message The message to add to the error result.
* @param callbackId The callback id used when calling back into JavaScript.
*/
public void error(String message, String callbackId) {
this.webView.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message), callbackId);
}
/**
* Called when the WebView does a top-level navigation or refreshes.
*
* Plugins should stop any long-running processes and clean up internal state.
*
* Does nothing by default.
*/
public void onReset() {
}
}

View File

@ -43,7 +43,7 @@ public class PluginEntry {
* 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 Plugin plugin = null;
public CordovaPlugin plugin = null;
/**
* Flag that indicates the plugin object should be created when PluginManager is initialized.
@ -69,7 +69,7 @@ public class PluginEntry {
*
* @return The plugin object
*/
public Plugin createPlugin(CordovaWebView webView, CordovaInterface ctx) {
public CordovaPlugin createPlugin(CordovaWebView webView, CordovaInterface ctx) {
if (this.plugin != null) {
return this.plugin;
}
@ -77,9 +77,8 @@ public class PluginEntry {
@SuppressWarnings("rawtypes")
Class c = getClassByName(this.pluginClass);
if (isCordovaPlugin(c)) {
this.plugin = (Plugin) c.newInstance();
this.plugin.setContext(ctx);
this.plugin.setView(webView);
this.plugin = (CordovaPlugin) c.newInstance();
this.plugin.initialize(ctx, webView);
return plugin;
}
} catch (Exception e) {
@ -106,16 +105,12 @@ public class PluginEntry {
}
/**
* 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
* Returns whether the given class extends CordovaPlugin.
*/
@SuppressWarnings("rawtypes")
private boolean isCordovaPlugin(Class c) {
if (c != null) {
return org.apache.cordova.api.Plugin.class.isAssignableFrom(c) || org.apache.cordova.api.Plugin.class.isAssignableFrom(c);
return org.apache.cordova.api.CordovaPlugin.class.isAssignableFrom(c);
}
return false;
}

View File

@ -32,6 +32,7 @@ import org.xmlpull.v1.XmlPullParserException;
import android.content.Intent;
import android.content.res.XmlResourceParser;
import android.util.Log;
/**
* PluginManager is exposed to JavaScript in the Cordova WebView.
@ -207,59 +208,31 @@ public class PluginManager {
* 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
* @param rawArgs An Array literal string containing any arguments needed in the
* plugin execute method.
* @return Whether the task completed synchronously.
*/
public boolean exec(final String service, final String action, final String callbackId, final String jsonArgs) {
PluginResult cr = null;
final Plugin plugin = this.getPlugin(service);
boolean runAsync = !plugin.isSynch(action);
try {
final JSONArray args = new JSONArray(jsonArgs);
//final CordovaInterface ctx = this.ctx;
if (plugin != null) {
if (runAsync) {
// Run this on a different thread so that this one can return back to JS
ctx.getThreadPool().execute(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);
app.sendPluginResult(cr, callbackId);
} catch (Exception e) {
PluginResult cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
app.sendPluginResult(cr, callbackId);
}
}
});
return false;
} 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 true;
}
}
}
} 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);
}
public boolean exec(String service, String action, String callbackId, String rawArgs) {
CordovaPlugin plugin = this.getPlugin(service);
if (plugin == null) {
PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
app.sendPluginResult(cr, callbackId);
return true;
}
if (cr == null) {
cr = new PluginResult(PluginResult.Status.NO_RESULT);
try {
CallbackContext callbackContext = new CallbackContext(callbackId, app);
boolean wasValidAction = plugin.execute(action, rawArgs, callbackContext);
if (!wasValidAction) {
PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION);
app.sendPluginResult(cr, callbackId);
return true;
}
return callbackContext.isFinished();
} catch (JSONException e) {
PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
app.sendPluginResult(cr, callbackId);
return true;
}
app.sendPluginResult(cr, callbackId);
return true;
}
@Deprecated
@ -273,14 +246,14 @@ public class PluginManager {
* If the service doesn't exist, then return null.
*
* @param service The name of the service.
* @return Plugin or null
* @return CordovaPlugin or null
*/
private Plugin getPlugin(String service) {
private CordovaPlugin getPlugin(String service) {
PluginEntry entry = this.entries.get(service);
if (entry == null) {
return null;
}
Plugin plugin = entry.plugin;
CordovaPlugin plugin = entry.plugin;
if (plugin == null) {
plugin = entry.createPlugin(this.app, this.ctx);
}
@ -403,7 +376,7 @@ public class PluginManager {
public void onReset() {
Iterator<PluginEntry> it = this.entries.values().iterator();
while (it.hasNext()) {
Plugin plugin = it.next().plugin;
CordovaPlugin plugin = it.next().plugin;
if (plugin != null) {
plugin.onReset();
}