Bri*_*nam 21 javascript android postmessage android-webview
我通常使用HTML5 PostMessage API将iframed内容中的信息传递给父框架.最近我在Android WebView中使用了我的内容(据我所知,这是iframe的原生Android相当).本机应用程序是否有办法监听我发送给他们的PostMessage事件?
我知道addJavascriptInterface存在,我只是希望有一种方法可以重用我现有的PostMessage代码,而无需编写新的东西.
Mau*_*Lam 11
这里的答案在发布时是很好的答案,但现在 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!");
Run Code Online (Sandbox Code Playgroud)
// 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);
}
Run Code Online (Sandbox Code Playgroud)
我知道这个问题很旧,但是我遇到了,所以我想在这里回答。简而言之-我发现postMessage至少对从子iframe到父窗口的通信有效,但是...
事实证明,我们确实不喜欢iframe在android的WebView中的表现方式,因此我们直接渲染了iframe的内容(如您所建议)。这给我们带来了两个问题-首先,从该iframe到它的父级,我们有很多消息挂钩;其次,我们仍然需要调出android对这些事件做出反应。
这是我们代码中的示例消息-遍及整个iframe:
parent.postMessage(JSON.stringify({
action : 'openModal',
source : embedId
}), '*');
Run Code Online (Sandbox Code Playgroud)
当我们使用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");
Run Code Online (Sandbox Code Playgroud)
现在,在此WebView中运行时totDevice将存在,而在iframe中运行时将不存在。因此,现在我们可以创建一个包装器来检查这种情况,并在两种方法之间干净地切换,而不是parent.postMessage直接调用。在这里,我们还为我们的Android实现添加了一个布尔型开关,以防您只想处理某些消息:
function postMessage(parent, json, transferlist) {
if (!totDevice || !totDevice.postMessage(json, transferList)) {
parent.postMessage(json, transferlist);
}
}
Run Code Online (Sandbox Code Playgroud)
我们上面的原始postMessage可以被重写:
postMessage(parent, JSON.stringify({
action : 'openModal',
source : embedId
}), '*');
Run Code Online (Sandbox Code Playgroud)
现在,我们有一组代码可以在iframe或android WebView中运行,而无需更改(至少对代码的这一部分而言)。
希望对您有所帮助。
我面临类似的问题,我想听.postMessage网络视图中发生的事件。我在原始 html 中检查了该事件是这样触发的
window.parent.postMessage(JSON.stringify(message), '*');
因此,我深入研究了 postMessage 并找到了用于添加 eventListener 的链接
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://example.org:8080")
return;
// ...
}
Run Code Online (Sandbox Code Playgroud)
首先是像这样的 JavascriptInterface 的自定义类
class JsObject {
@JavascriptInterface
public void receiveMessage(String data) {
Log.i("JsObject", "postMessage data="+data);
//handle data here
}
}
Run Code Online (Sandbox Code Playgroud)
在加载 url/html 之前将 javascriptInterface 添加到 webview
webView.addJavascriptInterface(new JsObject(), "Android"); //"Android" is just a name
Run Code Online (Sandbox Code Playgroud)
onPageStarted然后在回调中调用javascript,WebViewClient如下所示
@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);
}
Run Code Online (Sandbox Code Playgroud)
最近,我们必须开发一个项目,需要将我们的本机 Android 应用程序与第三方的外部 webview集成进行通信。
\n这个问题在 stackoverflow 中提出的想法非常有趣,如果你无法触及该 webview 的 JS 代码,则更是如此。
\n我描述了我们做了什么,以便能够通过 JS PostMessage API通过消息步骤与本机应用程序进行通信。
\n使用我们的 webview 实现。我们实现了onPageFinished方法来注入 JS 代码来加载网页。
\noverride fun onPageFinished(url: String?) {\nwebview.loadUrl(\n"javascript:(function() {" +\n "window.parent.addEventListener (\'message\', function(event) {" +\n " Android.receiveMessage(JSON.stringify(event.data));});" +\n "})()"\n)\n}\nRun Code Online (Sandbox Code Playgroud)\n基本上,我们正在做的是创建一个侦听器,将这些消息发送到我们自己的 JS 和Android Bridge 接口。我们之前在 Android 活动的 webview 设置中创建了它,就像我们通常使用addJavascriptInterface所做的那样
\nwebview.addJavascriptInterface(JsObject(presenter), "Android\xe2\x80\x9d)\nRun Code Online (Sandbox Code Playgroud)\n这样,我们就已经有了这个通信桥梁,并且 postMessage 发送的所有消息都将通过该侦听器订阅的接口到达我们。
\nclass JsObject(val presenter: Presenter) {\n @JavascriptInterface\n fun receiveMessage(data: String): Boolean {\n presenter.onDataReceived(data)\n Log.d("Data from JS", data)\n return true\n }\nRun Code Online (Sandbox Code Playgroud)\n
小智 1
您需要使用中间抽象接口,在一种实现中通过 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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8862 次 |
| 最近记录: |