evaluateJavascript如何工作?

Cod*_*gue 45 android android-webview android-4.4-kitkat

我正在尝试在Android 4.4中使用新的evaluateJavascript方法,但我得到的所有内容都是null结果:

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
    }
});
Run Code Online (Sandbox Code Playgroud)

如何将结果返回此方法?

更新:更多信息:

  1. 我有INTERNET权限集
  2. 我有 setJavascriptEnabled(true);
  3. 试过撇号字符串:return 'test';,
  4. 试过JS对象: return { test: 'this' }
  5. console.log('test'); 正在执行罚款.
  6. 按照以下方式设置targetSdkVersion为19:如果您的应用使用WebView

设备: Nexus 7和Nexus 5(股票)

Mat*_*unt 65

这个示例中使用了evaluateJavascript方法的示例:

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

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

需要注意的是,OnReceiveValue中返回的String是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
                    }
                }
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

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

例如,如果你去了:

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

它会打印出这个字符串,用双引号括起来:"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)
    }
});
Run Code Online (Sandbox Code Playgroud)


Cod*_*gue 11

好的,所以事实证明result这里是Javascript调用结果 - 好像有人将命令输入Javascript控制台.

所以为了获得结果,它需要包含在一个函数中:

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

这也有效:

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

该方法还处理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"}
    }
});
Run Code Online (Sandbox Code Playgroud)


Evg*_*nii 8

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)
  }
});
Run Code Online (Sandbox Code Playgroud)


lit*_*333 7

每个人的答案都很棒。我再补充一点。不要像这样使用@JavascripInterface 注释将evaluateJavascript 放在方法中

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

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

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

    }
Run Code Online (Sandbox Code Playgroud)


jak*_*b.g 6

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

如果您的 JS 函数只返回 aString并且您想知道为什么该字符串在 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"
    }
});
Run Code Online (Sandbox Code Playgroud)

(请注意,onReceiveValue始终提供一个Stringwhile JS 函数可能会返回 a null,一个 Number 字面量等)

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

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

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

if ("null".equals(s)) {
   ...
} else {
   // unescape JSON
}
Run Code Online (Sandbox Code Playgroud)