未调用Android WebView evaluateJavaScript回调

时间:2016-12-26 01:29:26

标签: java android webview android-webview chromium

在SDK 19中将

evaluateJavascript(String script, ValueCallback<String> resultCallback)方法添加到Android上的WebView。

Android文档引用:

  

如果为非null,则将使用any调用resultCallback   从执行中返回的结果。

我正在使用如下所示的方法,但不知何故我的回调没有被调用。我可以从调试中看到evaluateJavascript()已被调用,但未在Android API中调用回调 19,20&amp; 21 即可。从API 22(LOLLIPOP_MR1)开始,一切都按预期工作。

webview.loadURL("")之前调用evaluateJavascript()使其适用于所有API级别。我想了解为什么,如果有人能够解决这个问题或者分享关于此的任何链接,我将不胜感激。如果我能理解原因,我想看看是否可以避免调用loadURL()。另一个不相关的问题使loadURL()成为不可取的解决方案。

代码:

    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

找到此问题的示例

1 个答案:

答案 0 :(得分:2)

来自docs

当前显示的页面的上下文中异步评估JavaScript。在ContentViewCore EvaluateJavascript检查渲染视图。对于19,20,21中集成的WebView特定版本的外观 - RenderView只有在loadUrl被调用之后才会创建。

我发现以下FIX可能是相关的:

它从以下位置修改了EvaluateJavaScript的WebContentsAndorid本机实现:

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传递:

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

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