/** * The invoke method is called when phonegap.pluginManager.exec(...) is used from the script * environment. It instantiates the appropriate plugin and invokes the specified action. * JavaScript arguments are passed in as an array of objects. * * @param service String containing the service to run * @param action String containing the action that the service 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 executed 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 PhoneGap.callbackSuccess(...) or PhoneGap.callbackError(...) * is called once the plugin code has executed. * @return JSON encoded string with a response message and status. * @see net.rim.device.api.script.ScriptableFunction#invoke(java.lang.Object, java.lang.Object[]) */ public Object invoke(Object obj, Object[] oargs) throws Exception { final String service = (String) oargs[ARG_SERVICE]; final String action = (String) oargs[ARG_ACTION]; final String callbackId = (String) oargs[ARG_CALLBACK_ID]; boolean async = (oargs[ARG_ASYNC].toString().equals("true") ? true : false); PluginResult pr = null; try { // action arguments final JSONArray args = new JSONArray((String) oargs[ARG_ARGS]); // get the class for the specified service String clazz = this.pluginManager.getClassForService(service); Class c = null; if (clazz != null) { c = getClassByName(clazz); } if (isPhoneGapPlugin(c)) { // Create a new instance of the plugin and set the context final Plugin plugin = this.addPlugin(clazz, c); async = async && !plugin.isSynch(action); if (async) { // Run this async on a background thread so that JavaScript can continue on Thread thread = new Thread( new Runnable() { public void run() { // Call execute on the plugin so that it can do it's thing final PluginResult result = plugin.execute(action, args, callbackId); if (result != null) { int status = result.getStatus(); // If plugin status is OK, // or plugin is not going to send an immediate result (NO_RESULT) if (status == PluginResult.Status.OK.ordinal() || status == PluginResult.Status.NO_RESULT.ordinal()) { PhoneGapExtension.invokeSuccessCallback(callbackId, result); } // error else { PhoneGapExtension.invokeErrorCallback(callbackId, result); } } } }); thread.start(); return ""; } else { // Call execute on the plugin so that it can do it's thing pr = plugin.execute(action, args, callbackId); } } } catch (ClassNotFoundException e) { pr = new PluginResult( PluginResult.Status.CLASSNOTFOUNDEXCEPTION, "ClassNotFoundException: " + e.getMessage()); } catch (IllegalAccessException e) { pr = new PluginResult( PluginResult.Status.ILLEGALACCESSEXCEPTION, "IllegalAccessException:" + e.getMessage()); } catch (InstantiationException e) { pr = new PluginResult( PluginResult.Status.INSTANTIATIONEXCEPTION, "InstantiationException: " + e.getMessage()); } catch (JSONException e) { pr = new PluginResult(PluginResult.Status.JSONEXCEPTION, "JSONException: " + e.getMessage()); } // if async we have already returned at this point unless there was an error... if (async) { PhoneGapExtension.invokeErrorCallback(callbackId, pr); } return (pr != null ? pr.getJSONString() : "{ status: 0, message: 'all good' }"); }