Updated Branches: refs/heads/2.9.x 04ff14e62 -> 7cde444ff (forced update)
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/7cde444f/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 083e882..d7fddfe 100755 --- a/framework/src/org/apache/cordova/api/PluginManager.java +++ b/framework/src/org/apache/cordova/api/PluginManager.java @@ -18,421 +18,10 @@ */ package org.apache.cordova.api; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.cordova.CordovaArgs; import org.apache.cordova.CordovaWebView; -import org.apache.cordova.UriResolver; -import org.json.JSONException; -import org.xmlpull.v1.XmlPullParserException; - -import android.content.Intent; -import android.content.res.XmlResourceParser; - -import android.net.Uri; -import android.util.Log; -import android.webkit.WebResourceResponse; - -/** - * PluginManager is exposed to JavaScript in the Cordova WebView. - * - * Calling native plugin code can be done by calling PluginManager.exec(...) - * 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 CordovaWebView app; - // Flag to track first time through - private boolean firstRun; - - // 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>(); - - private AtomicInteger numPendingUiExecs; - - /** - * Constructor. - * - * @param app - * @param ctx - */ +public class PluginManager extends org.apache.cordova.PluginManager { public PluginManager(CordovaWebView app, CordovaInterface ctx) { - this.ctx = ctx; - this.app = app; - this.firstRun = true; - this.numPendingUiExecs = new AtomicInteger(0); - } - - /** - * Init when loading a new HTML page into webview. - */ - public void init() { - LOG.d(TAG, "init()"); - - // If first time, then load plugins from config.xml file - if (this.firstRun) { - this.loadPlugins(); - this.firstRun = false; - } - - // Stop plugins on current HTML page and discard plugin objects - else { - this.onPause(false); - this.onDestroy(); - this.clearPluginObjects(); - } - - // Insert PluginManager service - this.addService(new PluginEntry("PluginManager", new PluginManagerService())); - - // Start up all plugins that have onload specified - this.startupPlugins(); - } - - /** - * Load plugins from res/xml/config.xml - */ - public void loadPlugins() { - int id = this.ctx.getActivity().getResources().getIdentifier("config", "xml", this.ctx.getActivity().getPackageName()); - if(id == 0) - { - id = this.ctx.getActivity().getResources().getIdentifier("plugins", "xml", this.ctx.getActivity().getPackageName()); - LOG.i(TAG, "Using plugins.xml instead of config.xml. plugins.xml will eventually be deprecated"); - } - if (id == 0) { - this.pluginConfigurationMissing(); - //We have the error, we need to exit without crashing! - return; - } - XmlResourceParser xml = this.ctx.getActivity().getResources().getXml(id); - int eventType = -1; - String service = "", pluginClass = "", paramType = ""; - boolean onload = false; - boolean insideFeature = false; - while (eventType != XmlResourceParser.END_DOCUMENT) { - if (eventType == XmlResourceParser.START_TAG) { - String strNode = xml.getName(); - //This is for the old scheme - if (strNode.equals("plugin")) { - service = xml.getAttributeValue(null, "name"); - pluginClass = xml.getAttributeValue(null, "value"); - Log.d(TAG, "<plugin> tags are deprecated, please use <features> instead. <plugin> will no longer work as of Cordova 3.0"); - onload = "true".equals(xml.getAttributeValue(null, "onload")); - } - //What is this? - else if (strNode.equals("url-filter")) { - this.urlMap.put(xml.getAttributeValue(null, "value"), service); - } - else if (strNode.equals("feature")) { - //Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc) - //Set the bit for reading params - insideFeature = true; - service = xml.getAttributeValue(null, "name"); - } - else if (insideFeature && strNode.equals("param")) { - paramType = xml.getAttributeValue(null, "name"); - if (paramType.equals("service")) // check if it is using the older service param - service = xml.getAttributeValue(null, "value"); - else if (paramType.equals("package") || paramType.equals("android-package")) - pluginClass = xml.getAttributeValue(null,"value"); - else if (paramType.equals("onload")) - onload = "true".equals(xml.getAttributeValue(null, "value")); - } - } - else if (eventType == XmlResourceParser.END_TAG) - { - String strNode = xml.getName(); - if (strNode.equals("feature") || strNode.equals("plugin")) - { - PluginEntry entry = new PluginEntry(service, pluginClass, onload); - this.addService(entry); - - //Empty the strings to prevent plugin loading bugs - service = ""; - pluginClass = ""; - insideFeature = false; - } - } - try { - eventType = xml.next(); - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - /** - * Delete all plugin objects. - */ - public void clearPluginObjects() { - for (PluginEntry entry : this.entries.values()) { - entry.plugin = null; - } - } - - /** - * 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. - * - * @param service String containing the service to run - * @param action String containing 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 rawArgs An Array literal string containing any arguments needed in the - * plugin execute method. - */ - public void exec(final String service, final String action, final String callbackId, final String rawArgs) { - if (numPendingUiExecs.get() > 0) { - numPendingUiExecs.getAndIncrement(); - this.ctx.getActivity().runOnUiThread(new Runnable() { - public void run() { - execHelper(service, action, callbackId, rawArgs); - numPendingUiExecs.getAndDecrement(); - } - }); - } else { - execHelper(service, action, callbackId, rawArgs); - } - } - - private void execHelper(final String service, final String action, final String callbackId, final String rawArgs) { - CordovaPlugin plugin = getPlugin(service); - if (plugin == null) { - Log.d(TAG, "exec() call to unknown plugin: " + service); - PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION); - app.sendPluginResult(cr, callbackId); - return; - } - 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); - } - } catch (JSONException e) { - PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION); - app.sendPluginResult(cr, callbackId); - } - } - - @Deprecated - public void exec(String service, String action, String callbackId, String jsonArgs, boolean async) { - exec(service, action, callbackId, jsonArgs); - } - - /** - * 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 service The name of the service. - * @return CordovaPlugin or null - */ - public CordovaPlugin getPlugin(String service) { - PluginEntry entry = this.entries.get(service); - if (entry == null) { - return null; - } - CordovaPlugin plugin = entry.plugin; - if (plugin == null) { - plugin = entry.createPlugin(this.app, this.ctx); - } - return plugin; - } - - /** - * Add a plugin class that implements a service to the service entry table. - * This does not create the plugin object instance. - * - * @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 (PluginEntry entry : this.entries.values()) { - if (entry.plugin != null) { - entry.plugin.onPause(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) { - for (PluginEntry entry : this.entries.values()) { - if (entry.plugin != null) { - entry.plugin.onResume(multitasking); - } - } - } - - /** - * The final call you receive before your activity is destroyed. - */ - public void onDestroy() { - for (PluginEntry entry : this.entries.values()) { - if (entry.plugin != null) { - entry.plugin.onDestroy(); - } - } - } - - /** - * Send a message to all plugins. - * - * @param id The message id - * @param data The message data - * @return - */ - public Object postMessage(String id, Object data) { - Object obj = this.ctx.onMessage(id, data); - if (obj != null) { - return obj; - } - for (PluginEntry entry : this.entries.values()) { - if (entry.plugin != null) { - obj = entry.plugin.onMessage(id, data); - if (obj != null) { - return obj; - } - } - } - return null; - } - - /** - * Called when the activity receives a new intent. - */ - public void onNewIntent(Intent 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. - */ - public boolean onOverrideUrlLoading(String url) { - 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 false; - } - - /** - * Called when the app navigates or refreshes. - */ - public void onReset() { - Iterator<PluginEntry> it = this.entries.values().iterator(); - while (it.hasNext()) { - CordovaPlugin plugin = it.next().plugin; - if (plugin != null) { - plugin.onReset(); - } - } - } - - - private void pluginConfigurationMissing() { - LOG.e(TAG, "====================================================================================="); - LOG.e(TAG, "ERROR: config.xml is missing. Add res/xml/config.xml to your project."); - LOG.e(TAG, "https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=blob;f=framework/res/xml/plugins.xml"); - LOG.e(TAG, "====================================================================================="); - } - - /* Should be package private */ public UriResolver resolveUri(Uri uri) { - for (PluginEntry entry : this.entries.values()) { - if (entry.plugin != null) { - UriResolver ret = entry.plugin.resolveUri(uri); - if (ret != null) { - return ret; - } - } - } - return null; - } - - private class PluginManagerService extends CordovaPlugin { - @Override - public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException { - if ("startup".equals(action)) { - // The onPageStarted event of CordovaWebViewClient resets the queue of messages to be returned to javascript in response - // to exec calls. Since this event occurs on the UI thread and exec calls happen on the WebCore thread it is possible - // that onPageStarted occurs after exec calls have started happening on a new page, which can cause the message queue - // to be reset between the queuing of a new message and its retrieval by javascript. To avoid this from happening, - // javascript always sends a "startup" exec upon loading a new page which causes all future exec calls to happen on the UI - // thread (and hence after onPageStarted) until there are no more pending exec calls remaining. - numPendingUiExecs.getAndIncrement(); - ctx.getActivity().runOnUiThread(new Runnable() { - public void run() { - numPendingUiExecs.getAndDecrement(); - } - }); - return true; - } - return false; - } + super(app, ctx); } } http://git-wip-us.apache.org/repos/asf/cordova-android/blob/7cde444f/framework/src/org/apache/cordova/api/PluginResult.java ---------------------------------------------------------------------- diff --git a/framework/src/org/apache/cordova/api/PluginResult.java b/framework/src/org/apache/cordova/api/PluginResult.java index a642200..39d3983 100755 --- a/framework/src/org/apache/cordova/api/PluginResult.java +++ b/framework/src/org/apache/cordova/api/PluginResult.java @@ -21,159 +21,40 @@ package org.apache.cordova.api; import org.json.JSONArray; import org.json.JSONObject; -import android.util.Base64; - -public class PluginResult { - private final int status; - private final int messageType; - private boolean keepCallback = false; - private String strMessage; - private String encodedMessage; - +public class PluginResult extends org.apache.cordova.PluginResult { public PluginResult(Status status) { - this(status, PluginResult.StatusMessages[status.ordinal()]); + super(status); } public PluginResult(Status status, String message) { - this.status = status.ordinal(); - this.messageType = message == null ? MESSAGE_TYPE_NULL : MESSAGE_TYPE_STRING; - this.strMessage = message; + super(status, message); } public PluginResult(Status status, JSONArray message) { - this.status = status.ordinal(); - this.messageType = MESSAGE_TYPE_JSON; - encodedMessage = message.toString(); + super(status, message); } public PluginResult(Status status, JSONObject message) { - this.status = status.ordinal(); - this.messageType = MESSAGE_TYPE_JSON; - encodedMessage = message.toString(); + super(status, message); } public PluginResult(Status status, int i) { - this.status = status.ordinal(); - this.messageType = MESSAGE_TYPE_NUMBER; - this.encodedMessage = ""+i; + super(status, i); } public PluginResult(Status status, float f) { - this.status = status.ordinal(); - this.messageType = MESSAGE_TYPE_NUMBER; - this.encodedMessage = ""+f; + super(status, f); } public PluginResult(Status status, boolean b) { - this.status = status.ordinal(); - this.messageType = MESSAGE_TYPE_BOOLEAN; - this.encodedMessage = Boolean.toString(b); + super(status, b); } public PluginResult(Status status, byte[] data) { - this(status, data, false); + super(status, data); } public PluginResult(Status status, byte[] data, boolean binaryString) { - this.status = status.ordinal(); - this.messageType = binaryString ? MESSAGE_TYPE_BINARYSTRING : MESSAGE_TYPE_ARRAYBUFFER; - this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP); - } - - public void setKeepCallback(boolean b) { - this.keepCallback = b; - } - - public int getStatus() { - return status; - } - - public int getMessageType() { - return messageType; - } - - public String getMessage() { - if (encodedMessage == null) { - encodedMessage = JSONObject.quote(strMessage); - } - return encodedMessage; - } - - /** - * If messageType == MESSAGE_TYPE_STRING, then returns the message string. - * Otherwise, returns null. - */ - public String getStrMessage() { - return strMessage; - } - - public boolean getKeepCallback() { - return this.keepCallback; - } - - @Deprecated // Use sendPluginResult instead of sendJavascript. - public String getJSONString() { - return "{\"status\":" + this.status + ",\"message\":" + this.getMessage() + ",\"keepCallback\":" + this.keepCallback + "}"; - } - - @Deprecated // Use sendPluginResult instead of sendJavascript. - public String toCallbackString(String callbackId) { - // If no result to be sent and keeping callback, then no need to sent back to JavaScript - if ((status == PluginResult.Status.NO_RESULT.ordinal()) && keepCallback) { - return null; - } - - // Check the success (OK, NO_RESULT & !KEEP_CALLBACK) - if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) { - return toSuccessCallbackString(callbackId); - } - - return toErrorCallbackString(callbackId); - } - - @Deprecated // Use sendPluginResult instead of sendJavascript. - public String toSuccessCallbackString(String callbackId) { - return "cordova.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");"; - } - - @Deprecated // Use sendPluginResult instead of sendJavascript. - public String toErrorCallbackString(String callbackId) { - return "cordova.callbackError('"+callbackId+"', " + this.getJSONString()+ ");"; - } - - public static final int MESSAGE_TYPE_STRING = 1; - public static final int MESSAGE_TYPE_JSON = 2; - public static final int MESSAGE_TYPE_NUMBER = 3; - public static final int MESSAGE_TYPE_BOOLEAN = 4; - public static final int MESSAGE_TYPE_NULL = 5; - public static final int MESSAGE_TYPE_ARRAYBUFFER = 6; - // Use BINARYSTRING when your string may contain null characters. - // This is required to work around a bug in the platform :(. - public static final int MESSAGE_TYPE_BINARYSTRING = 7; - - public static String[] StatusMessages = new String[] { - "No result", - "OK", - "Class not found", - "Illegal access", - "Instantiation error", - "Malformed url", - "IO error", - "Invalid action", - "JSON error", - "Error" - }; - - public enum Status { - NO_RESULT, - OK, - CLASS_NOT_FOUND_EXCEPTION, - ILLEGAL_ACCESS_EXCEPTION, - INSTANTIATION_EXCEPTION, - MALFORMED_URL_EXCEPTION, - IO_EXCEPTION, - INVALID_ACTION, - JSON_EXCEPTION, - ERROR + super(status, data, binaryString); } }
