PostMessage API 是否可用于与 Android WebView 通信
Can the PostMessage API be used to communicate with an Android WebView?
我通常使用 HTML5 PostMessage API 将信息从我的 iframed 内容传达到父框架。最近,我的内容在Android WebView中使用(据我所知,这是iframe的原生Android等价物(。本机应用程序有没有办法侦听我发送给他们的 PostMessage 事件?
我知道addJavascriptInterface存在,我只是希望有一种方法可以在不编写新东西的情况下重用我现有的PostMessage代码。
我知道这个问题很旧,但我遇到了它,所以我想我会在这里回答。简而言之 - 我发现 postMessage 至少适用于从子 iframe 到父窗口的通信,但是......
事实证明,我们真的不喜欢iframe在android的WebView中的行为方式,所以我们直接渲染了iframe的内容(如你所建议的(。这给我们留下了两个问题 - 首先,我们有很多从iframe到它的父级的消息钩子,其次我们仍然需要调用android来对这些事件做出反应。
下面是来自我们代码的示例消息 - 它散布在整个 iframe 中:
parent.postMessage(JSON.stringify({
action : 'openModal',
source : embedId
}), '*');
当我们在Android上时,我们想要的是使用android对javascript接口的支持来注入一个对象,以便在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(parent, JSON.stringify({
action : 'openModal',
source : embedId
}), '*');
现在我们有一组代码可以在iframe或android WebView中运行,而无需更改(至少对这部分代码而言(。
我希望这对某人有所帮助。
这里的答案在发布时是很好的答案,但现在androidx.webkit可用,我相信这是推荐的方法。
特别是,WebViewCompat.addWebMessageListener
和WebViewCompat.postWebMessage
将是javascript PostMessage API的对应项。
下面是从文档中复制的代码示例:
// Web page (in JavaScript)
myObject.onmessage = function(event) {
// prints "Got it!" when we receive the app's response.
console.log(event.data);
}
myObject.postMessage("I'm ready!");
// App (in Java)
WebMessageListener myListener = new WebMessageListener() {
@Override
public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
boolean isMainFrame, JavaScriptReplyProxy replyProxy) {
// do something about view, message, sourceOrigin and isMainFrame.
replyProxy.postMessage("Got it!");
}
};
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
WebViewCompat.addWebMessageListener(webView, "myObject", rules, myListener);
}
最近,我们不得不开发一个项目,该项目需要将我们的原生 Android 应用程序与来自第三方的外部 Web 视图集成进行通信。
这个问题在stackoverflow中提出的想法非常有趣,如果你不能触摸该web视图的JS代码,那就更是如此。
我描述了我们做了什么,以便能够通过 JS PostMessage API 的消息步骤与本机应用程序进行 Web 视图通信。
使用我们的网络视图实现。我们实现了onPageDone方法,以便注入我们的JS代码来加载Web。
override fun onPageFinished(url: String?) {
webview.loadUrl(
"javascript:(function() {" +
"window.parent.addEventListener ('message', function(event) {" +
" Android.receiveMessage(JSON.stringify(event.data));});" +
"})()"
)
}
基本上,我们正在做的是创建一个侦听器,将这些消息发送到我们自己的JS和Android Bridge接口。我们之前在Android活动的webview设置中创建的,就像我们通常使用addJavascriptInterface所做的那样。
webview.addJavascriptInterface(JsObject(presenter), "Android”)
这样,我们已经有了该通信桥,并且postMessage发送的所有消息都将在该侦听器订阅的接口中到达我们。
class JsObject(val presenter: Presenter) {
@JavascriptInterface
fun receiveMessage(data: String): Boolean {
presenter.onDataReceived(data)
Log.d("Data from JS", data)
return true
}
我遇到了类似的问题,我想听听网络视图中发生的.postMessage
事件。我在原始 html 中检查了事件是否像这样触发
window.parent.postMessage(JSON.stringify(message), '*');
因此,我对postMessage进行了更多挖掘,并找到了用于添加事件监听器的链接
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://example.org:8080")
return;
// ...
}
德班的回答帮助我建立了安卓JS界面。
首先是像这样的JavascriptInterface的自定义类
class JsObject {
@JavascriptInterface
public void receiveMessage(String data) {
Log.i("JsObject", "postMessage data="+data);
//handle data here
}
}
在加载url/html之前将javascriptInterface添加到webview。
webView.addJavascriptInterface(new JsObject(), "Android"); //"Android" is just a name
然后在WebViewClient
的onPageStarted
回调中调用javascript,如下所示
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
webView.loadUrl("javascript:(function() {" +
"function receiveMessage(event) {'n" +
"Android.receiveMessage(JSON.stringify(event.data));'n" +
"}" +
"window.addEventListener('"message'", receiveMessage, false);"+
"})()"
);
Log.i(TAG, "onPageStarted "+url);
}
你需要使用一个中间抽象接口,在一个实现中通过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
}
- window.onload没有'无法在Android WebView中工作
- Android Webview通过Javascript注入CSS
- 在Android WebView中通过javascript检测点击HTML选项标记
- 用JavaScript替换Android WebView模板上的html文本
- Hammer.js阻止在Android Webview中点击超链接
- 在Android WebView中运行Javascript-onPageFinished循环
- Chrome 50的Android WebView在触摸页面之前会阻止Javascript
- HTML5画布支持和Android Webview
- 带有javascript的HTML没有加载到android webview中
- 带有iframe嵌入的Android WebView;t显示在4.2.2及以下
- 如果没有互联网连接,Android WebView离线消息
- Android Webview没有'有时不会加载HTML
- 如何在Android WebView中嵌入Youtube视频
- 检查登录错误Android WebView Javascript
- Injecting JQuery into Android Webview
- 为什么可以't我在Android WebView onLayout中设置了最大宽度
- Android Webview触摸内容
- 了解 Android webview JavaScript 界面
- 控制在 Android WebView 中执行的 JS
- 在 Android WebView 中过滤 DOM 元素,而无需 jQuery