Можно ли использовать PostMessage API для связи с Android WebView?

Я обычно использую HTML5 PostMessage API для передачи информации из моего iframed-контента в родительский фрейм. Недавно у меня был контент, который использовался в Android WebView (насколько я могу судить, это родной Android-эквивалент iframe). Есть ли способ для собственного приложения прослушивать события PostMessage, которые я отправляю им?

Я знаю, что addJavascriptInterface существует, я просто надеюсь, что есть способ повторно использовать мой существующий код PostMessage без написания чего-то нового.

Ответы

Ответ 1

Я понимаю, что этот вопрос старый, но я столкнулся с ним, поэтому решил, что отвечу. Короче говоря, я нахожу, что postMessage работает как минимум для связи с дочерним iframe в родительском окне BUT...

Оказывается, нам действительно не понравилось, как iframe вел себя в android WebView, поэтому мы отображали содержимое iframe напрямую (как вы предлагаете). Это оставило нам две проблемы - сначала у нас было много перехватов сообщений из этого iframe, чтобы он был родительским, а во-вторых, нам все еще нужно было обратиться к android, чтобы реагировать на эти события.

Вот пример сообщения из нашего кода, который был посыпан в iframe:

    parent.postMessage(JSON.stringify({
        action    : 'openModal',
        source    : embedId
    }), '*');

Когда мы на Android, мы хотим использовать [поддержку android для javascript-интерфейсов] (https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object, java.lang. String)), чтобы ввести объект для обработки этого запроса при работе в WebView.

На стороне Android это будет выглядеть примерно так:

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");

Теперь при запуске внутри этого WebView totDevice будет существовать, а при запуске в iframe это не будет. Итак, теперь мы можем создать обертку для проверки этого условия и чисто переключаться между двумя методами, а не напрямую называть parent.postMessage. Здесь мы также добавили логический переключатель в нашу реализацию Android, если вы только хотели обработать некоторые из сообщений:

function postMessage(parent, json, transferlist) {
    if (!totDevice || !totDevice.postMessage(json, transferList)) {
        parent.postMessage(json, transferlist);
    }
}

Наше оригинальное postMessage сверху можно переписать:

    postMessage(parent, JSON.stringify({
        action    : 'openModal',
        source    : embedId
    }), '*');

Теперь у нас есть один набор кода, который может работать в iframe или Android WebView без изменений (по крайней мере, до этой части кода).

Я надеюсь, что это поможет кому-то.

Ответ 2

Вам нужно использовать промежуточный абстрактный интерфейс, который в одной реализации обрабатывает сообщения через PostMessage и в другом случае через 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
}