javascript - sure - ¿Se puede utilizar la API de PostMessage para comunicarse con una vista web de Android?
postmessage iframes (2)
Normalmente uso la API HTML5 PostMessage para comunicar información de mi contenido de iframed al marco principal. Recientemente, mi contenido se usó dentro de una vista web de Android (por lo que puedo decir, este es el equivalente nativo de Android de un iframe). ¿Hay alguna forma de que la aplicación nativa escuche los eventos de PostMessage que les envío?
Soy consciente de que existe addJavascriptInterface , solo espero que haya una manera de reutilizar mi código existente de PostMessage sin escribir algo nuevo.
Debe usar una interfaz abstracta intermedia que en una implementación procesa mensajes a través de PostMessage y en otro caso a través de addJavascriptInterface.
window.addEventListener("message", onReceivedPostMessage, false);
function onReceivedPostMessage(event){
//..ex deconstruct event into action & params
var action = event.data.action;
var params = event.data.params;
performAction(action, params); //performAction would be the uniform API
}
function onReceivedActivityMessageViaJavascriptInterface(json){
//..ex deconstruct data into action & params
var data = JSON.parse(json);
var action = data.action;
var params = data.params;
performAction(action, params); //performAction would be the uniform API
}
Me doy cuenta de que esta pregunta es vieja pero la encontré, así que pensé que respondería aquí. En resumen, estoy descubriendo que postMessage funciona al menos para la comunicación desde un iframe secundario a una ventana primaria, PERO ...
Resulta que realmente no nos gustó la forma en que se comportó el iframe en WebView de Android, por lo que en su lugar, representamos el contenido del iframe directamente (como usted sugiere). Esto nos dejó con dos problemas: primero teníamos muchos enlaces de mensajes desde ese iframe a su padre y, segundo, aún necesitábamos llamar a Android para reaccionar ante estos eventos.
Aquí hay un mensaje de ejemplo de nuestro código, que se esparció por todo el iframe:
parent.postMessage(JSON.stringify({
action : ''openModal'',
source : embedId
}), ''*'');
Cuando estemos en Android, lo que queremos es usar [soporte de Android para interfaces javascript] ( https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object , java. lang.String)) para inyectar un objeto para manejar esta solicitud cuando se ejecuta en un WebView.
En el lado de Android esto se verá así:
class JsObject {
@JavascriptInterface
public boolean postMessage(String json, String transferList) {
return false; // here we return true if we handled the post.
}
}
// And when initializing the webview...
webView.addJavascriptInterface(new JsObject(), "totDevice");
Ahora, cuando se ejecuta dentro de este WebView, existe totDevice
y cuando se ejecuta en un iframe no lo hará. Así que ahora podemos crear una envoltura para verificar esta condición y cambiar limpiamente entre los dos métodos en lugar de llamar directamente a parent.postMessage
. Aquí también agregamos un interruptor booleano en nuestra implementación de Android en caso de que solo quisieras manejar algunos de los mensajes:
function postMessage(parent, json, transferlist) {
if (!totDevice || !totDevice.postMessage(json, transferList)) {
parent.postMessage(json, transferlist);
}
}
Nuestro mensaje original de arriba se puede reescribir:
postMessage(parent, JSON.stringify({
action : ''openModal'',
source : embedId
}), ''*'');
Ahora tenemos un único conjunto de código que puede ejecutarse en un iframe o una aplicación WebView de Android sin ningún cambio (al menos en esta parte del código).
Espero que ayude a alguien.