Com*_*are 10 android android-webview
Google 针对Android应用开发者的安全指南包含以下内容:
WebView不
addJavaScriptInterface()与不受信任的内容一起使用.在Android M及更高版本上,可以使用HTML消息通道.
近我可以告诉大家,"HTML消息通道"是指喜欢的东西createWebMessageChannel(),WebMessagePort,WebMessage,和亲属.
但是,它们没有提供任何示例.他们所做的只是链接到WhatWG规范,这是相当不清楚的.而且,基于谷歌的搜索createWebMessageChannel,它似乎还没有被广泛使用 - 我的博客文章描述了Android 6.0 SDK中的变化,使得排名前十的搜索结果,我只是顺便提一下.
addJavascriptInterface()用于允许a中的JavaScript WebView使用应用程序调用应用程序提供的Java代码WebView.我们如何使用"HTML消息频道"代替它?
Com*_*are 10
好吧,我有这个工作,虽然它有点糟糕.
第1步:填充你的WebView使用loadDataWithBaseURL().loadUrl()不行,因为错误.您需要为第一个参数使用http或httpsURL loadDataWithBaseURL()(或者,至少不是file,因为错误).您稍后将需要该URL,因此请保留它(例如,private static final String值).
步骤2:确定何时要初始化从JavaScript到Java的通信.随着addJavascriptInterface(),这是立即可用.但是,使用WebMessagePort并不是那么好.特别是,在页面加载之前(例如,onPageFinished()在a上WebViewClient),您无法尝试初始化通信.
步骤3:在您想要初始化这些通信时,请createWebMessageChannel()打开WebView,创建一个WebMessagePort[].该数组中的第0个元素是通信管道的末尾,您可以调用setWebMessageCallback()它来响应从JavaScript发送给您的消息.
第4步:手的第1个要素WebMessagePort[]通过在包装它的JavaScript WebMessage和调用postWebMessage()上WebView.postWebMessage()将a Uri作为第二个参数,并且Uri必须从您在步骤1中使用的相同URL作为基本URL loadDataWithBaseURL().
@TargetApi(Build.VERSION_CODES.M)
private void initPort() {
final WebMessagePort[] channel=wv.createWebMessageChannel();
port=channel[0];
port.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override
public void onMessage(WebMessagePort port, WebMessage message) {
postLux();
}
});
wv.postWebMessage(new WebMessage("", new WebMessagePort[]{channel[1]}),
Uri.parse(THIS_IS_STUPID));
}
Run Code Online (Sandbox Code Playgroud)
(其中,wv是WebView和THIS_IS_STUPID与所使用的URL loadDataWithBaseURL())
步骤5:您的JavaScript可以为全局onmessage事件分配一个函数,该函数将在调用时postWebMessage()调用.ports您在事件上获得的数组的第0个元素将是通信管道的JavaScript端,您可以将其填充到某个变量中.如果需要,您可以为该onmessage端口分配一个函数,如果Java代码将使用它WebMessagePort来发送未来数据.
步骤#6:当您想要从JavaScript向Java发送消息时,请postMessage()从步骤#5中调用端口,该消息将被传递到您setWebMessageCallback()在步骤3中注册的回调.
var port;
function pull() {
port.postMessage("ping");
}
onmessage = function (e) {
port = e.ports[0];
port.onmessage = function (f) {
parse(e.data);
}
}
Run Code Online (Sandbox Code Playgroud)
此示例应用程序演示了该技术.它有一个WebView显示基于环境光传感器的当前光级.传感器数据WebView在推送的基础上(当传感器改变时)或在拉动的基础上(用户点击网页上的"光级"标签)输入.此应用程序WebMessagePort在Android 6.0+设备上使用这些应用程序,虽然推送选项已注释掉,因此您可以确认拉动方法正在通过端口工作.我将在即将出版的本书中详细介绍示例应用程序.
在CTS中有一个测试
// Create a message channel and make sure it can be used for data transfer to/from js.
public void testMessageChannel() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
loadPage(CHANNEL_MESSAGE);
final WebMessagePort[] channel = mOnUiThread.createWebMessageChannel();
WebMessage message = new WebMessage(WEBVIEW_MESSAGE, new WebMessagePort[]{channel[1]});
mOnUiThread.postWebMessage(message, Uri.parse(BASE_URI));
final int messageCount = 3;
final CountDownLatch latch = new CountDownLatch(messageCount);
runTestOnUiThread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < messageCount; i++) {
channel[0].postMessage(new WebMessage(WEBVIEW_MESSAGE + i));
}
channel[0].setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override
public void onMessage(WebMessagePort port, WebMessage message) {
int i = messageCount - (int)latch.getCount();
assertEquals(WEBVIEW_MESSAGE + i + i, message.getData());
latch.countDown();
}
});
}
});
// Wait for all the responses to arrive.
boolean ignore = latch.await(TIMEOUT, java.util.concurrent.TimeUnit.MILLISECONDS);
}
Run Code Online (Sandbox Code Playgroud)
档案:cts/tests/tests/webkit/src/android/webkit/cts/PostMessageTest.java.至少有一些起点.
小智 5
这是使用 compat 库的 解决方案:以 Android Studio 格式下载完整解决方案
此示例使用存储在资产文件夹中的 index.html 和 index.js 文件。
这是JS:
const channel = new MessageChannel();
var nativeJsPortOne = channel.port1;
var nativeJsPortTwo = channel.port2;
window.addEventListener('message', function(event) {
if (event.data != 'capturePort') {
nativeJsPortOne.postMessage(event.data)
} else if (event.data == 'capturePort') {
/* The following three lines form Android class 'WebViewCallBackDemo' capture the port and assign it to nativeJsPortTwo
var destPort = arrayOf(nativeToJsPorts[1])
nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY) */
if (event.ports[0] != null) {
nativeJsPortTwo = event.ports[0]
}
}
}, false);
nativeJsPortOne.addEventListener('message', function(event) {
alert(event.data);
}, false);
nativeJsPortTwo.addEventListener('message', function(event) {
alert(event.data);
}, false);
nativeJsPortOne.start();
nativeJsPortTwo.start();
Run Code Online (Sandbox Code Playgroud)
这是 HTML:
<!DOCTYPE html>
<html lang="en-gb">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebView Callback Demo</title>
<script src="js/index.js"></script>
</head>
<body>
<div style="font-size: 24pt; text-align: center;">
<input type="button" value="Test" onclick="nativeJsPortTwo.postMessage(msgFromJS.value);" style="font-size: inherit;" /><br />
<input id="msgFromJS" type="text" value="JavaScript To Native" style="font-size: 16pt; text-align: inherit; width: 80%;" />
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
最后这里是原生 Android 代码:
class PostMessageHandler(webView: WebView) {
private val nativeToJsPorts = WebViewCompat.createWebMessageChannel(webView)
private var nativeToJs: WebMessagePortCompat.WebMessageCallbackCompat? = null
init {
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE)) {
nativeToJs = object : WebMessagePortCompat.WebMessageCallbackCompat() {
override fun onMessage(port: WebMessagePortCompat, message: WebMessageCompat?) {
super.onMessage(port, message)
Toast.makeText(webView.context, message!!.data, Toast.LENGTH_SHORT).show()
}
}
}
var destPort = arrayOf(nativeToJsPorts[1])
nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY)
}
}
Run Code Online (Sandbox Code Playgroud)
从 'WebViewClient.onPageFinished(webView: WebView, url: String)' 回调执行本机代码很重要。有关完整详细信息,请参阅上面的下载链接。该项目显示 postMessage 以两种方式工作(本机到 JS 和 JS 到本机)希望这会有所帮助。
| 归档时间: |
|
| 查看次数: |
2613 次 |
| 最近记录: |