我知道要从Javascript到Java进行交互,你必须使用webview中的addjavascriptInterface方法注入一个Java对象。
这是我面临的问题。
我使用addJavascriptInterface
方法注册一个java对象,以便在我的JS中使用。
我使用webview.loadURL("javascript:XXX");
当我完成注入JS时,我发送了一个JS事件。
问题是如果在第1步之后立即执行以下Javascript:
mWebView.loadUrl("javascript:if(window.myobject) console.log('myobject found---------'); else {console.log('myobject not found----');}");
我在控制台的日志中找到了“myobject not found”。
我想知道如果有一段时间我可以访问我的对象,如果有,我怎么知道应该等多少时间来调用我的对象?
答案 0 :(得分:46)
我想知道如果有一段时间我可以访问我的对象
是的,我认为存在延迟,因为WebView.addJavascriptInterface
将在WebView的内部工作线程中运行。也许您已经考虑过这一点,并意识到WebView必须至少维护一个工作线程来执行异步网络IO。也许您在使用WebView时也注意到了DDMS中的这些线程。
事实证明,它还使用一个线程为许多其他公共方法工作。我真的希望谷歌的文档更清晰!但我希望我可以帮助并向您展示我是如何为自己确认的。
跟我来看看WebView的源代码。它具有相当的可读性,即使你无法完全按照正在发生的事情进行操作,也可以通过回答关于线程的一些问题进行追踪。
您可以通过SDK管理器工具下载Android框架源代码,但它也会在Github上进行镜像,这就是我在此处链接的内容。我猜测并选择了一个与某些版本的ICS接近的标签。找到WebView.addJavascriptInterface
并不难。我刚用Googled“WebView.java site:github.com/android”。
方法WebView.addJavascriptInterface
向WebViewCore
的实例发送消息:
mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
在WebViewCore.java
中有一堆称为sendMessage
的重载方法,但我们并不需要知道究竟是哪个被调用,因为它们几乎完全相同。甚至有一个很好的评论给我们一个提示,我们在正确的地方!所有这些都委托给EventHub
的实例,这是一个内部类。 This method结果是同步的,并且正在向Handler
的实例发送消息,这很好地表明这可能在另一个线程中运行,但为了完整起见,让我们找出来! / p>
EventHub.transferMessages
中Handler
实例化了run
。这里还有一些跳,但最终我发现这是从WebCoreThread
Runnable
的子类中的Thread
调用的,它与新的{{1}一起实例化}右WebViewCore.initialize
。
多么冒险!所以,即使我真的无法确定所有这些移动部件的发生情况,我很自信地说这个方法不是同步的,并向WebView的工作线程发送消息。我希望这是有道理的!
如果是这样,我怎么知道应该等多久才能打电话给我的对象?
不幸的是,我不知道答案。我正在研究这个确切的问题,并在我的谷歌搜索过程中在StackOverflow上发现了这个问题。我认为您有以下选择,其中一些比其他选项更好或更容易:
1)只需Thread.sleep
100毫秒或addJavascriptInterface
和loadUrl("javascript:...")
之间的内容。 Blech,我不喜欢这个,但它可能是最简单的。
2)另一种可能性是,您可以使用JavaScript片段调用WebView.loadUrl
,该片段专门测试接口是否已设置,并捕获在尚未设置的情况下引发的ReferenceError。但是,正如您可能已经猜到的那样,这种方法涉及向WebView添加JavaScript接口!
3)改为调用WebView.setWebChromeClient
,然后抓住JavaScript的alert()
或console.log
。从我的实验来看,这种方法是是同步的,所以没有延迟。 (我已经在源代码中确认了这一点,但我会将详细信息作为练习留给读者)你应该想出一些特殊字符串来调用alert
并在onJsAlert
内检查它,所以你不只是抓住所有alert()
。
对不起这个答案的长度,我希望有所帮助。祝你好运!
答案 1 :(得分:1)
确保您需要从Java访问的HTML / Javascript中声明的Javascript对象被声明为全局,否则很可能会收集它们。我有代码执行此操作(Android是我的界面添加了addJavascriptInterface):
<script>
var cb = function(location) {
alert('location is ' + location);
}
Android.getLocation('cb');
</script>
getLocation方法调用Android的LocationManager.requestSingleUpdate,然后在LocationListener触发时调用回调。
如果没有“var”,我发现当位置查找调用回调时,回调函数已被垃圾收集。
答案 2 :(得分:0)
(从a similar question上的回复中复制)
我把Jason Shah和S先生的实施作为我修复的基石,并对其进行了很大的改进。
我只是链接到这个评论的代码太多了。
要点是: