Llamadas Javascript desde Android usando PhoneGap

Tengo y aplicación construida con PhoneGap , y estoy tratando de comunicarse con Javascript de código nativo.

en mi clase extendiendo DroidGap :

 @Override public void onCreate(Bundle savedInstanceState) { Logger.log("oncreate"); super.onCreate(savedInstanceState); super.init(); super.appView.getSettings().setJavaScriptEnabled(true); super.appView.getSettings().setSupportZoom(true); super.appView.getSettings().setBuiltInZoomControls(true); super.appView.getSettings().setDisplayZoomControls(false); jsinterface = new CommunicationInterface(this, appView); super.appView.addJavascriptInterface(jsinterface, "communicationinterface"); } 

el javascriptinterface:

 public class CommunicationInterface { private WebView mAppView; private DroidGap mGap; public CommunicationInterface(DroidGap gap, WebView view) { mAppView = view; mGap = gap; } public String getTestString() { return "teststring"; } public void parse(Object o) { Logger.log(o); } } 

El Javacript se encuentra en un archivo externo (creo un archivo HTML que tiene esta línea en el header : <script type="text/javascript" src="scripts.js"></script> )

Scripts.js :

 function sendToInterface() { alert("alert"); var map = new Object(); (...) window.communicationinterface.parse(map); //communication js -> android seems to work. } 

He leído en otros puestos que es posible comunicarse entre PhoneGap y Android, pero así no he tenido ningún éxito. loadUrl("javascript:alert('Alert');") crear una alerta, pero eso fue con loadUrl("javascript:alert('Alert');") , pero también he leído que no debes hacer porque eso es lo que sendJavascript() es para provoca pérdidas, vuelve a cargar la página, etc.). He intentado disparar un par de cadenas a través del método sendJavascript() , pero sin éxito:

  • sendJavascript("javascript:alert('Alert');")
  • sendJavascript("javascript:sendToInterface();")
  • sendJavascript("sendToInterface();")
  • sendJavascript("window.sendToInterface();")

Cómo comunicarse desde el nativo -> PhoneGap (o lo que está mal con lo que ya tengo)? Por lo tanto, otros mensajes y preguntas no me han ayudado con este problema en particular.

Leer:

  • http://www.jumpbyte.com/2012/phonegap-native-to-javascript/
  • Phonegap: "processMessage failed" no puede enviar la función javascript (Cordova 2.5.0)
  • ¿Comunicación entre Android Java y Phonegap Javascript? (aunque esta es la otra dirección, pero estoy tratando de hacer ambas cosas)
  • http://www.intelligrape.com/blog/2013/01/31/using-sendjavscript-to-inject-javascript-into-android-phonegap-application/
  • Phonegap – Android – Llamando a javascript de causas nativas leakedwindow
  • cómo llamar a la función javascript desde android utilizando plugin phonegap

EDITAR

Escribí un proyecto de trabajo:

Parte Java

 import org.apache.cordova.DroidGap; import org.json.JSONException; import org.json.JSONObject; import android.os.Bundle; import android.util.Log; public class App extends DroidGap { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.loadUrl("file:///sdcard/ds/index.html"); System.out.println("loading from sdcard"); Thread t = new Thread() { public void run() { try { for (int i = 0; i < 3; i++) { sleep(2000); sendValue("value " + i, "another vlaue " + i); } } catch (Exception e) { e.printStackTrace(); } }; }; t.start(); } public void sendValue(String value1, String value2) { System.out.println("sendvalue in app"); JSONObject data = new JSONObject(); try { data.put("value1", value1); data.put("value2", value2); } catch (JSONException e) { Log.e("CommTest", e.getMessage()); } String js = String.format("window.plugins.appcomm.updateValues('%s');", data.toString()); this.sendJavascript(js); } } import org.apache.cordova.api.Plugin; import org.apache.cordova.api.PluginResult; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.util.Log; public class AppComm extends Plugin{ private static AppComm instance; public AppComm () { instance = this; } public static AppComm getInstance() { return instance; } @Override public PluginResult execute(String action, JSONArray args, String callbackId) { System.out.println("in execute from appcomm"); return null; } public void sendValue(String value1, String value2) { System.out.println("sendvalue in appComm"); JSONObject data = new JSONObject(); try { data.put("value1", value1); data.put("value2", value2); } catch (JSONException e) { Log.e("CommTest", e.getMessage()); } String js = String.format( "window.plugins.commtest.updateValues('%s');", data.toString()); this.sendJavascript(js); } } 

res / xml / plugins.xml

 <plugins> <plugin name="App" value="org.apache.cordova.App"/> <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/> <plugin name="Device" value="org.apache.cordova.Device"/> <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/> <plugin name="Compass" value="org.apache.cordova.CompassListener"/> <plugin name="Media" value="org.apache.cordova.AudioHandler"/> <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/> <plugin name="Contacts" value="org.apache.cordova.ContactManager"/> <plugin name="File" value="org.apache.cordova.FileUtils"/> <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/> <plugin name="Notification" value="org.apache.cordova.Notification"/> <plugin name="Storage" value="org.apache.cordova.Storage"/> <plugin name="Temperature" value="org.apache.cordova.TempListener"/> <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/> <plugin name="Capture" value="org.apache.cordova.Capture"/> <plugin name="Battery" value="org.apache.cordova.BatteryListener"/> <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/> <plugin name="AppComm" value="com.example.plugin.AppComm"/> </plugins> 

cordova.xml

 <?xml version="1.0" encoding="utf-8"?> <cordova> <access origin=".*"/> <!-- allow local pages --> <log level="DEBUG"/> <preference name="classicRender" value="true" /> </cordova> 

Encabezado Index.html

 <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0" /> <title> </title> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.css" /> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"> </script> <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"> </script> <script type="text/javascript" charset="utf-8" src="cordova.js"></script> <script type="text/javascript" charset="utf-8"> var AppComm=function(){}; AppComm.prototype.updateValues=function(a){ var map = new Object(); map["X1"] = "hallo"; map["X2"] = "hi"; cordova.exec(null, null, null); }; cordova.addConstructor(function(){cordova.addPlugin("appcomm",new AppComm)}); </script> </head> 

Uno de los problemas fue que javascript estaba en un archivo separado (creo que fue uno de los problemas). Si no es mucho pedir, ¿cómo puedo llamar correctamente a java, y con qué valores? ¿Cómo implementar el método de ejecución y cómo llamarla (soy realmente malo en JQuery)?

En primer lugar, está utilizando una subclase de Plugin . Plugin ha sido descontinuado y ha sido reemplazado por CordovaPlugin . Si utilizas una versión antigua de PhoneGap, te recomendamos que actualices.

En segundo lugar, su llamada de exec es incorrecta. Los documentos para el desarrollo de plugins indican claramente que tienes que pasar 5 parámetros, mientras estás pasando 3 nulos. ¿Cómo espera que se maneje?

 cordova.exec(function(winParam) {}, function(error) {}, "service", "action", ["firstArgument", "secondArgument", 42, false]); 

Aquí, el service , la action y la matriz de parámetros determinan qué sucederá en su código Java. Los dos primeros determinan qué sucederá en JavaScript bajo ciertas condiciones. Por lo tanto, aunque puede utilizar null para los dos primeros, debe especificar los tres últimos.

Tengo un plugin de ejemplo que funciona con PhoneGap 2.3.0. Vea el siguiente código:

 public class ExampleJSCommunicator extends CordovaPlugin { public boolean execute (final String action, final JSONArray args, CallbackContext callbackContext) throws JSONException { PluginResult.Status status = PluginResult.Status.OK; String result = ""; cordova.getActivity ().runOnUiThread (new Runnable () { @Override public void run() { try { String displayText = ""; if (action.equals ("buttonClicked")) { displayText = args.getString(0) + " was clicked"; } else if (action.equals ("animationRunning")) { displayText = args.getBoolean(0) ? "Animation started running" : "Animation stopped running"; } TextView label = (TextView) cordova.getActivity().findViewById (R.id.textView); label.setText (displayText + " and the Activity knows it!"); } catch (JSONException e) { e.printStackTrace(); } } }); return true; } } 

Con el código anterior, tiene su complemento Java-side capaz de manejar dos "acciones" personalizadas – buttonClicked y animationRunning . Estas acciones sirven a mis propósitos, pero podrías nombrarlos de otra manera.

Ahora, todavía necesitas registrar tu plugin, para que Cordova lo sepa. Esto se hace en el archivo xml/config.xml . En plugins , tienes que agregar lo siguiente:

 <plugin name="ExampleJSCommunicator" value="com.example.phonegap.ExampleJSCommunicator"/> 

A continuación, puede pasar datos (o "acciones") de JavaScript de la siguiente manera. Tenga en cuenta que los parámetros ( which.id y animationRunning se pasan en una matriz):

 cordova.exec (null, null, "ExampleJSCommunicator", "buttonClicked", [which.id]); // my first action cordova.exec (null, null, "ExampleJSCommunicator", "animationRunning", [animationRunning]); // my second action 

Estas dos llamadas exec activarán el método execute en la clase ExampleJSCommunicator y se manejarán en los respectivos bloques if. No importa dónde llame a exec, siempre y cuando declare su código JavaScript después de incluir el archivo cordova.js. Mi JavaScript está contenido dentro de un archivo main.js separado y funciona muy bien:

 <script type="text/javascript" charset="utf-8" src="cordova.js"></script> <script type="text/javascript" charset="utf-8" src="main.js"></script> 

Hasta el momento no estás usando ninguna de las herramientas que Apache Cordova te da para crear plugins y solo estás intentando probar una clase con el SDK estándar de Android. Si está buscando agregar funcionalidad, recomiendo escribir un complemento, debido a las siguientes razones:

  • Apache Cordova tiene formas alternativas de comunicación entre WebView y Java para que siga funcionando incluso cuando addJavascriptInterface falla
  • No es necesario anular las cosas

Le recomiendo que lea esto y mueva su código personalizado de Java a un complemento: http://docs.phonegap.com/es/2.5.0/guide_plugin-development_android_index.md.html

Sin embargo, el error principal en su ejemplo es mediante el uso de un WebView en su clase en lugar de un CordovaWebView. Un WebView no tiene un método de trabajo sendJavascript y la única forma sencilla de enviar el Javascript de nuevo es mediante loadUrl.

  • ¿Cómo determinar cuándo Android WebView está completamente cargado?
  • Acceso a la interfaz de usuario de JavaScript en Android
  • Detectar la rotación del teléfono Android en el navegador con JavaScript
  • La imagen de contacto de Phonegap no se muestra
  • Deshabilitar el almacenamiento en caché, las cookies y todo lo demás en un WebView
  • React Native en Android no encontró Herramientas de compilación
  • ¿Puedo ejecutar JavaScript sin un WebView, o un WebView puede ejecutarse sin un contexto de actividad, como en un servicio?
  • ¿Por qué es el evento touchstart después de hacer clic?
  • Detectar un dedo deslizar a través de JavaScript en el iPhone y Android
  • ¿Cómo medir el uso de datos de mi aplicación en reaccionar nativo?
  • Ejecución de JavaScript dentro de un servicio en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.