Android 未调用 WebView evaluateJavaScript 回调

Android WebView evaluateJavaScript Callback is not being invoked

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

Android 文档引用:

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

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

evaluateJavascript() 之前调用 webview.loadURL("") 使其适用于所有 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

找到此问题的示例

来自docs

当前显示页面的上下文中异步计算JavaScript。在 ContentViewCore EvaluateJavascript 中检查渲染视图。看起来像集成在 19、20、21 中的 WebView 的特定版本 - RenderView 直到 loadUrl 被调用才创建。

我发现以下 FIX 可能相关:

它修改了 WebContentsAndorid EvaluateJavaScript 的本机实现,来自:

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 无法处理 java 脚本执行。 因此,当您使用 loadUrl 时,您会强制创建渲染视图,并且所有内容都会按预期开始工作。