Android WebView评估未调用JavaScript回调 [英] Android WebView evaluateJavaScript Callback is not being invoked

查看:291
本文介绍了Android WebView评估未调用JavaScript回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

evaluateJavascript(String script, ValueCallback<String> resultCallback)方法已添加到SDK 19中Android上的WebView中.

evaluateJavascript(String script, ValueCallback<String> resultCallback) method is added to WebView on Android in SDK 19.

Android文档引号:

Android documentation quotes:

如果非null,则resultCallback将与任何 该执行返回的结果.

If non-null, resultCallback will be invoked with any result returned from that execution.

我正在使用此方法,如下所示,但是不知何故我的回调没有被调用.从调试中我可以看到evaluateJavascript()被调用,但是未在Android API 19、20& 21 .从API 22(LOLLIPOP_MR1)开始,一切正常.

I am using this method as shown below, but somehow my callback is not being invoked. I can see from debugging that the evaluateJavascript() is called, but the call back is not being invoked in Android API 19, 20 & 21. From API 22 (LOLLIPOP_MR1) onwards, everything is working as expected.

evaluateJavascript()之前调用webview.loadURL("")使其可以在所有API级别上使用.我想了解原因,如果有人可以阐明/分享与此有关的任何链接,我将不胜感激.如果我能理解为什么,我想看看是否可以避免调用loadURL().还有另一个不相关的问题使loadURL()成为不受欢迎的解决方案.

Calling webview.loadURL("") before evaluateJavascript() makes it work on all the API levels. I want to understand why and would appreciate if somebody can shed some light / share any links about this. If I can understand why, I want to see if calling loadURL() could be avoided. There is another unrelated problem which makes loadURL() a non-preferable solution.

代码:

Code:

    private void webViewTest() {
        WebView webview = new WebView(this);
        webview.getSettings().setJavaScriptEnabled(true);
        Log.d("TEST", "BEFORE"); // LOGGED
        // webview.loadUrl(""); // Enabling this makes it work on all Android versions
        webview.evaluateJavascript("(function(){return 'test'})()", new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String s) {
                Log.d("TEST", "From JS: " + s); // NEVER LOGGED on API 19-21
            }
        });
        Log.e("TEST", "AFTER"); // LOGGED
    }


    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            webViewTest();
        }
    });

请在 https://github.com/bashok001/TestApp 中找到此问题的示例.

Please find an example of this problem at https://github.com/bashok001/TestApp

推荐答案

来自当前显示的页面的上下文中异步评估JavaScript.在ContentViewCore EvaluateJavascript中检查renderview.看起来像19,20,21中集成的WebView的特定版本-在调用loadUrl之前,不会创建RenderView.

Asynchronously evaluates JavaScript in the context of the currently displayed page. In ContentViewCore EvaluateJavascript checks for renderview. Looks like for that particular versions of WebView integrated within 19,20,21 - the RenderView is just not created until loadUrl get called.

我发现以下 FIX 可能相关:

它已修改 WebContentsAndorid 的EvaluateJavaScript本地实现:

It's modify WebContentsAndorid native implementation of EvaluateJavaScript from :

void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
                                             jobject obj,
                                             jstring script,
                                            jobject callback,
                                            jboolean start_renderer) {

   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   DCHECK(rvh);

   if (start_renderer && !rvh->IsRenderViewLive()) {

     if (!static_cast<WebContentsImpl*>(web_contents_)->
         CreateRenderViewForInitialEmptyDocument()) {
         ... 
     }
   }
   ...

至:

 void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
                                                jobject obj,
                                                jstring script,
                                                jobject callback) {
   RenderViewHost* rvh = web_contents_->GetRenderViewHost();
   DCHECK(rvh);
   if (!rvh->IsRenderViewLive()) {
     if (!static_cast<WebContentsImpl*>(web_contents_)->
         CreateRenderViewForInitialEmptyDocument()) {
         ...
        }
      }
   ....

ContentViewCore中,有以下代码将false传递为start_renderer:

And in ContentViewCore there was following code which passing false as start_renderer:

public void evaluateJavaScript(String script, JavaScriptCallback callback) {
    assert mWebContents != null;
    mWebContents.evaluateJavaScript(script, callback, false);
}

这意味着在提到的对evaluateJavaScript的修复调用之前构建的WebView上,不会创建RenderView,因此,WebContext无法处理Java脚本执行. 因此,当您使用loadUrl时,将强制创建渲染视图,并且所有视图都将按预期开始工作.

This mean that on WebView built prior to mentioned fix calls to evaluateJavaScript does not create RenderView and as result WebContext can't handle java script execution. So when you use loadUrl you force creation of render view and all starts working as expected.

这篇关于Android WebView评估未调用JavaScript回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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