了解Android的webview addjavascript接口

我知道要从Javascript到Java进行交互,您必须使用webview中的addjavascriptInterface方法注入Java对象。

这是我面临的问题。

  1. 我使用addJavascriptInterface方法注册一个java对象,以便在我的JS中使用。

  2. 我使用webview.loadURL("javascript:XXX");在webview中注入了几个JS webview.loadURL("javascript:XXX");

  3. 当我完成注入JS时,我发送了一个JS事件。

问题是如果在第1步之后立即执行以下Javascript:

 mWebView.loadUrl("javascript:if(window.myobject) console.log('myobject found---------'); else {console.log('myobject not found----');}"); 

我在控制台的日志中find“myobject not found”。

我想知道如果有一段时间我可以访问我的对象,如果是这样,我怎么知道我应该等多少时间来调用我的对象?

Solutions Collecting From Web of "了解Android的webview addjavascript接口"

我想知道如果有一段时间我可以访问我的对象

是的,我认为有一个延迟,因为WebView.addJavascriptInterface将在WebView的内部工作线程中运行。 也许您已经考虑过这一点,并意识到WebView必须至少维护一个工作线程来执行异步网络IO。 也许您在使用WebView时也注意到DDMS中的这些线程。

事实certificate,它还使用一个线程为许多其他公共方法工作。 我真的希望谷歌的文档更清楚! 但我希望我可以帮助并向您展示我是如何为自己确认的。

跟我来看看WebView的源代码。 它具有相当的可读性,即使您无法完全按照正在进行的操作,也可以通过回答有关线程的一些问题进行追踪。

您可以通过SDK管理器工具下载Android框架源代码,但它也在Github上进行镜像,这就是我在这里链接的内容。 我猜测并挑选了一个与某些版本的ICS接近的标签。 findWebView.addJavascriptInterface并不难。 我只是用Google搜索“WebView.java网站:github.com/android”。

WebView.addJavascriptInterface方法将消息发送到WebViewCore的实例:

 mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg); 

WebViewCore.java有一堆称为sendMessage的重载方法,但我们并不需要知道究竟是哪个被调用,因为它们几乎完全相同。 甚至有一个很好的评论给我们一个提示,我们是在正确的地方! 所有这些都委托给一个内部类的EventHub实例。 这个方法结果是同步的,并且正在向Handler一个实例发送消息,这很好地表明这可能在另一个线程中运行,但为了完整起见,让我们找出答案!

HandlerEventHub.transferMessages中实例化,该调用是从WebViewCore.initialize调用的。 这里还有一些跳,但最终我发现这是从WebCoreThreadRunnable子类)中run调用的,它在这里实例化了一个新的Thread

多么冒险! 所以,即使我真的不能确定所有这些移动部件发生了什么,我很自信地说这个方法不是同步的,并向WebView的工作线程发送消息。 我希望这是有道理的!

如果是这样,我怎么知道我应该等多少时间来调用我的对象?

不幸的是,我不知道答案。 我正在研究这个确切的问题,并在我的谷歌搜索过程中在StackOverflow上发现了这个问题。 我认为您有以下选项,其中一些比其他选项更好或更容易:

1)Just Thread.sleep持续100毫秒或addJavascriptInterfaceloadUrl("javascript:...")之间的东西loadUrl("javascript:...") 。 Blech,我不喜欢这个,但它可能是最简单的。

2)另一种可能性是你可以使用一段JavaScript来调用WebView.loadUrl ,该片段专门测试接口是否已设置,如果尚未设置则捕获引发的ReferenceError。 但是,正如您可能已经猜到的那样,这种方法涉及向WebView添加JavaScript接口!

3)改为调用WebView.setWebChromeClient而是捕获JavaScript的alert()console.log 。 从我的实验来看,这种方法同步的,所以没有延迟。 (我已经在源代码中证实了这一点,但我会将细节作为练习留给读者)你应该想出一些特殊的字符串来调用alert ,并在onJsAlert检查它,所以你不仅仅是捕捉所有alert() s。

对不起这个答案的长度,我希望有所帮助。 祝你好运!

确保您需要从Java访问的HTML / Javascript中声明的Javascript对象被声明为全局,否则很可能会收集它们。 我有代码执行此操作(Android是我的界面添加addJavascriptInterface):

  

getLocation方法调用Android的LocationManager.requestSingleUpdate,然后在LocationListener触发时调用回调。

没有“var”,我发现当位置查找调用回调时,回调函数已被垃圾收集。

(从我对类似问题的回复中复制)

我把Jason Shah和S先生的实现作为我修复的基石,并对其进行了很大的改进。

我只想链接到这个评论的代码太多了。

  • 详情: http : //twigstechtips.blogspot.com/2013/09/android-webviewaddjavascriptinterface.html
  • 资料来源: https : //github.com/twig/twigstechtips-snippets/blob/master/GingerbreadJSFixExample.java

要点是:

  • 适用于所有版本的Gingerbread(2.3.x)
  • 从JS到Android的调用现在是同步的
  • 不再需要手动映射接口方法
  • 修复了字符串分隔符破坏代码的可能性
  • 更容易更改JS签名和接口名称