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
:
- ¿Cómo detectar el número de versión de Android en Firefox para Android?
- ¿Dónde se muestran las notificaciones en Chrome en Android?
- Cómo almacenar datos de json de forma segura en phonegap android?
- ¿Cómo comunicarse entre WebView y JavaScript?
- ¿Cuál es el enfoque correcto para crear una aplicación para Android?
@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)?
- Establecer arrastrar audiencia en SpannableString
- Detección de dispositivos de pantalla táctil con Javascript
- Funciones de JavaScript de Android Calling en WebView
- Auto Android sólo completa después de espacio?
- Cambio de hoja de estilo con Javascript basado en navegador
- Cómo detectar el contacto del usuario con el espacio telefónico usando JS
- Nuevo PhoneGap 3.0 No se puede resolver la importación org.apache.cordova
- Evitar que la barra de direcciones se oculte en los navegadores móviles
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.
- Error al analizar XML: prefijo no enlazado con barra de herramientas sdk 21
- android convertir mapa de bits a bufferedinputstream