【问题标题】:How does evaluateJavascript work?evaluateJavascript 是如何工作的?
【发布时间】:2013-11-16 06:51:47
【问题描述】:

我正在尝试在 Android 4.4 中使用新的 evaluateJavascript 方法,但我得到的只是一个空结果:

webView1.evaluateJavascript("return \"test\";", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Log is written, but s is always null
    }
});

如何将结果返回给该方法?

更新:更多信息:

  1. 我设置了 INTERNET 权限
  2. 我有setJavascriptEnabled(true);
  3. 尝试过的撇号字符串:return 'test';,
  4. 尝试过的 JS 对象:return { test: 'this' }
  5. console.log('test'); 执行良好。
  6. targetSdkVersion 设置为 19,如下所示:If your app uses WebView

设备: Nexus 7 和 Nexus 5(库存)

【问题讨论】:

  • 你试过去掉javascript中的return关键字吗?所以:webView1.evaluateJavascript("\"test\"", new ValueCallback&lt;String&gt;() { /*callback code here*/ });
  • 我已经阅读了WebView 文档,并试图了解evaluateJavascript 函数的实际用例?

标签: android android-webview android-4.4-kitkat


【解决方案1】:

本示例中使用了 evaluateJavascript 方法的示例:

https://github.com/GoogleChrome/chromium-webview-samples/tree/master/jsinterface-example

基本上,如果您在 WebView 中执行的 javascript 返回一个值,它将在回调中传递。

需要注意的主要是 OnReceiveValue 中返回的字符串是 JSON 值、JSON 对象或 JSON 数组,具体取决于您返回的内容。

需要注意的是,如果您返回单个值,则需要在 JSON 读取器上使用 setLenient(true) 才能使其工作。

     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // In KitKat+ you should use the evaluateJavascript method
        mWebView.evaluateJavascript(javascript, new ValueCallback<String>() {
            @TargetApi(Build.VERSION_CODES.HONEYCOMB)
            @Override
            public void onReceiveValue(String s) {
                JsonReader reader = new JsonReader(new StringReader(s));

                // Must set lenient to parse single values
                reader.setLenient(true);

                try {
                    if(reader.peek() != JsonToken.NULL) {
                        if(reader.peek() == JsonToken.STRING) {
                            String msg = reader.nextString();
                            if(msg != null) {
                                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                            }
                        }
                    }
                } catch (IOException e) {
                    Log.e("TAG", "MainActivity: IOException", e);
                } finally {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        // NOOP
                    }
                }
            }
        });
    }

您可能仍希望对字符串响应使用解析器的原因是它被转换为 JSON 值,这意味着它将用引号括起来。

例如,如果你去了:

mWebView.evaluateJavascript("(function() { return 'this'; })();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints: "this"
    }
});

它会打印字符串 this,用双引号括起来:“this”。

其他值得注意的例子:

mWebView.evaluateJavascript("(function() { return null; })();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints the string 'null' NOT Java null
    }
});

mWebView.evaluateJavascript("(function() { })();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); //s is Java null
    }
});

mWebView.evaluateJavascript("(function() { return ''; })();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints "" (Two double quotes)
    }
});

【讨论】:

  • @TargetApi(Build.VERSION_CODES.HONEYCOMB)在evaluateJavascript里面有什么用?
  • 它涵盖了使用 Honeycomb 中引入的 JSONReader 类的编译器警告
  • 我们如何评估 KITKAT 之前的 JavaScript?当您检查 API 时 - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
  • @KaluKhanLuhar 你可以使用webview.loadurl("javascript:(function () {document.body.background='red';});");
  • +1 用于说明 onReceiveValue 返回例如JSON 值。花了很多时间试图弄清楚为什么在 HTML 元素上调用 innerHTML 会返回 qoutes 中的内容
【解决方案2】:

好的,原来resultJavascript 调用的结果 - 就像将命令输入到 Javascript 控制台一样。

所以为了得到一个结果,需要将其包装在一个函数中:

webView1.evaluateJavascript("(function() { return \"this\"; })();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints 'this'
    }
});

这也可以:

webView1.evaluateJavascript("window.variable = \"asd\";", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints asd
    }
});

该方法还处理 Javascript 对象:

webView1.evaluateJavascript("(function() { return { var1: \"variable1\", var2: \"variable2\" }; })();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String s) {
        Log.d("LogName", s); // Prints: {"var1":"variable1","var2":"variable2"}
    }
});

【讨论】:

    【解决方案3】:

    AndroidJSCore 是评估不使用 WebView 的 JavaScript 的不错选择。

    如果你想坚持使用 WebView 并需要在早期版本的 Android (4+) 上评估 JavaScript,这里有一个小库:

    https://github.com/evgenyneu/js-evaluator-for-android

    jsEvaluator.evaluate("put your JavaScript code", new JsCallback() {
      @Override
      public void onResult(final String result) {
        // get result here (optional)
      }
    });
    

    【讨论】:

    • 当我在 onPageFinished(WebView view, String url) 方法中使用它与 webview.evaluareJavaScript() 非常相似时,我没有得到与 evaluareJavaScript() 方法相同的 html
    【解决方案4】:

    总结@GauntFace的答案,提供不使用JSON解析器的替代方案:

    如果您的 JS 函数只返回一个 String 并且您想知道为什么该字符串在 Java 中被破坏,那是因为它是 JSON 转义的。

    mWebView.evaluateJavascript("(function() { return 'Earvin \"Magic\" Johnson'; })();", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String s) {
            Log.d("LogName", s);
            // expected: s == Earvin "Magic" Johnson
            // actual:   s == "Earvin \"Magic\" Johnson"
        }
    });
    

    (注意onReceiveValue 总是提供String 而JS 函数可能返回null、数字字面量等)

    要获得与 JS 中相同的字符串值,如果您 100% 确定您期望返回正确的 String,则需要对其进行 JSON 转义,例如:

    String unescaped = s.substring(1, s.length() - 1)  // remove wrapping quotes
                         .replace("\\\\", "\\")        // unescape \\ -> \
                         .replace("\\\"", "\"");       // unescape \" -> "
    

    但是,请注意,如果 JS 返回正确的 nulls 可能是一个字符串 "null",因此您显然需要在第一步进行检查。

    if ("null".equals(s)) {
       ...
    } else {
       // unescape JSON
    }
    

    【讨论】:

      【解决方案5】:

      每个人的回答都很棒。我只是再补充一点。不要像这样将evaluateJavascript放在带有@JavascripInterface注解的方法中

          @JavascriptInterface  //this is the right annotation
          public void onData(){ 
                  mWebView.evaluateJavascript("javascript:executeNext()",null);
          }  
      

      因为它会阻塞 JavaBridge 线程。 如果你想把evaluateJavascript放在里面。用这种方法做

          @JavascriptInterface
          public void onData(){
              mWebView.post(new Runnable() {
                  @Override
                  public void run() {
                      mWebView.evaluateJavascript("javascript:executeNext()",null);
                  }
              });
      
          }
      

      【讨论】:

      • 我已经阅读了WebView 文档,并试图了解evaluateJavascript 函数的实际用例?
      • @AdamHurwitz 例如,向 webview 注入一些脚本以与网站显示进行交互
      【解决方案6】:

      重要提示:
      在调用 evaluateJavascript 之前,您必须为您的 WebView 启用 JavaScript。否则你不会得到任何结果。

      WebSettings settings = yourWebview.getSettings();
      settings.setJavaScriptEnabled(true);
      

      【讨论】:

        猜你喜欢
        • 2013-12-31
        • 2012-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多