了解Android的webview addjavascriptinterface [英] Understanding Android's webview addjavascriptinterface

查看:28
本文介绍了了解Android的webview addjavascriptinterface的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I know that to interact from Javascript to Java you have to inject a Java object using the addjavascriptInterface method in webview.

这是我面临的问题.

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

  1. I register a java object using addJavascriptInterface method to be available in my JS.

我使用 webview.loadURL("javascript:XXX");

我在完成注入 JS 后发送一个 JS 事件.

I send a JS event when I am done with injecting the JS.

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

The problem is that if immediately after step 1, if I execute the following Javascript:

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

我的控制台日志中显示未找到我的对象".

I get "myobject not found" in my console's log.

我想知道是否还有一段时间才能访问我的对象,如果是,我如何知道我应该等待多长时间来调用我的对象?

I want to know that if there is some time before I can access my object and if so, how do I get to know how much time should I wait to call my object?

推荐答案

我想知道是否还有一段时间才能访问我的对象

I want to know that if there is some time before i can access my object

是的,我认为有延迟,因为 WebView.addJavascriptInterface 将在 WebView 的内部工作线程中运行.或许你已经想过这个,意识到WebView至少要维护一个工作线程来做异步网络IO.也许您在使用 WebView 时也注意到了 DDMS 中的这些线程.

Yes, I think there is a delay, because WebView.addJavascriptInterface will run in the WebView's internal worker thread. Perhaps you've thought about this, and realized that WebView has to maintain at least one worker thread to do asynchronous network IO. Maybe you also noticed these threads in DDMS while using a WebView.

事实证明,它还使用一个线程来为许多其他公共方法工作.我真的希望 Google 的文档更清楚地说明这一点!但我希望我能帮上忙,并向您展示我是如何尝试为自己确认这一点的.

It turns out that it also uses a thread to do work for a number of other public methods. I really wish the docs from Google made this clearer! But I hope I can help and show you how I tried to confirm this for myself.

跟我来看看 WebView 的源代码.它具有合理的可读性,即使您无法准确了解正在发生的事情,也可以通过回答有关线程的一些问题进行追踪.

Follow me as I take a look at the source for WebView. It's reasonably readable, even if you can't follow exactly what's going on, it's possible to trace through answer some questions with respect to threads.

您可以通过 SDK 管理器工具下载 Android 框架源代码,但它也已在 Github 上进行了镜像,因此我已将其链接到此处.我猜测并选择了一个接近某些版本的 ICS 的标签.不难找到WebView.addJavascriptInterface.我刚刚在 Google 上搜索了WebView.java 站点:github.com/android".

You can download the Android framework source through the SDK manager tool, but it's also mirrored on Github, so that's what I've linked to here. I guessed and picked a tag that's close to some version of ICS. It's not hard to find WebView.addJavascriptInterface. I just Googled "WebView.java site:github.com/android".

方法 WebView.addJavascriptInterfaceWebViewCore 的实例发送消息:

The method WebView.addJavascriptInterface sends a message to an instance of WebViewCore:

mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);

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

In WebViewCore.java there are a bunch of overloaded methods called sendMessage, but we don't really need to know which exactly is being called, since they do pretty much the same thing. There's even a nice comment to give us a hint that we're in the right place! All of them are delegating to an instance of EventHub which is some inner class. This method turns out to be synchronized, and is sending a message to an instance of Handler, which is a good indication that this is probably running in another thread, but for completeness sake, let's find out!

那个 HandlerEventHub.transferMessagesWebViewCore.initialize.这里还有一些跳跃,但最终我发现这是从 WebCoreThread(Runnable 的子类)中的 run 调用的,它是与新的 Thread 一起实例化 这里.

That Handler is instantiated in EventHub.transferMessages which is called from WebViewCore.initialize. There are a few more hops here, but eventually I found out that this is called from run in WebCoreThread (subclass of Runnable), which is instantiated along with a new Thread right here.

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

What an adventure! So, even though I really can't say for sure what's going on with all these moving parts, I am pretty confident to say that this method is not synchronous, and sends a message to the WebView's worker thread. I hope that makes sense!

如果是这样,我如何知道我应该等待多长时间来调用我的对象?

if so, how do i get to know how much time should i wait to call my object?

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

Unfortunately, I don't know the answer to this. I was researching this exact issue and found this question on StackOverflow in the course of my Googling. I think you have the following options, some of which are nicer or easier than others:

1) 只需 Thread.sleep 100 毫秒或介于 addJavascriptInterfaceloadUrl("javascript:...") 之间的时间.Blech,我不喜欢这个,但它可能是最简单的.

1) Just Thread.sleep for 100 ms or something between addJavascriptInterface and loadUrl("javascript:..."). Blech, I don't like this, but it is potentially the easiest.

2) 另一种可能性是您可以使用一段 JavaScript 调用 WebView.loadUrl 专门测试接口是否已设置,并捕获如果尚未设置则抛出的 ReferenceError.然而,正如您可能已经猜到的,这种涉及向 WebView 添加 JavaScript 接口!

2) Another possibility is that you could call WebView.loadUrl with a snippet of JavaScript that specifically tests if the interface is set, and catches the ReferenceError that is thrown if it's not set yet. However, as you might have guessed, this kind of involves adding a JavaScript interface to the WebView!

3) 改为调用 WebView.setWebChromeClient,并改为捕获 JavaScript 的 alert()console.log.根据我的实验,这个方法是同步的,所以没有延迟.(我已经在源代码中确认了这一点,但我会将细节留给读者作为练习)您可能应该想出一些特殊的字符串来调用 alert 并在 onJsAlert 中检查它,因此您不只是捕获所有 alert().

3) Call WebView.setWebChromeClient instead, and catch JavaScript's alert() or console.log instead. From my experiments, this method is synchronous, so there is no delay. (I have confirmed this in source, but I'll leave details as an exercise for the reader) You should probably come up with some special string to call alert with and check for it inside onJsAlert, so you aren't just catching all alert()s.

抱歉这个答案太长了,希望能帮到你.祝你好运!

Sorry for the length of this answer, I hope that helps. Good luck!

这篇关于了解Android的webview addjavascriptinterface的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆