Android在WebView中调用JavaScript函数

我想调用一些javascript函数坐在一个运行在一个android webviewhtml页面。 很简单,下面的代码试图做的 – 从android应用程序,调用一个测试消息的javascript函数,inturn调用一个java功能回到android应用程序,通过吐司显示测试消息。

javascript函数如下所示:

 function testEcho(message){ window.JSInterface.doEchoTest(message); } 

从WebView,我已经尝试调用javascript下面的方式没有运气:

 myWebView.loadUrl("javascript:testEcho(Hello World!)"); mWebView.loadUrl("javascript:(function () { " + "testEcho(Hello World!);" + "})()"); 

我没有在WebView上启用javascript

 myWebView.getSettings().setJavaScriptEnabled(true); // register class containing methods to be exposed to JavaScript myWebView.addJavascriptInterface(myJSInterface, "JSInterface"); 

还有Java Class

 public class JSInterface{ private WebView mAppView; public JSInterface (WebView appView) { this.mAppView = appView; } public void doEchoTest(String echo){ Toast toast = Toast.makeText(mAppView.getContext(), echo, Toast.LENGTH_SHORT); toast.show(); } } 

我花了很多时间在网上搜寻,看看我可能做错了什么。 我发现的所有例子都使用这种方法。 有没有人在这里看到错误?

编辑:还有几个其他的外部javascript文件被引用和在html ,他们可能是问题?

我找出了问题所在:在testEcho()参数中缺少引号。 这就是我打电话工作的方式:

 myWebView.loadUrl("javascript:testEcho('Hello World!')"); 

从kitkat开始,使用evaluateJavascript方法,而不是loadUrl来调用下面的javascript函数

  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { webView.evaluateJavascript("enable();", null); } else { webView.loadUrl("javascript:enable();"); } 
 public void run(final String scriptSrc) { webView.post(new Runnable() { @Override public void run() { webView.loadUrl("javascript:" + scriptSrc); } }); } 

是的,你有语法错误。 如果你想在你的logcat中得到你的Javascript错误和打印语句,你必须在onConsoleMessage(ConsoleMessage cm)实现onConsoleMessage(ConsoleMessage cm)方法。 它提供了像Web控制台(Inspect元素)的完整堆栈跟踪。 这是方法。

 public boolean onConsoleMessage(ConsoleMessage cm) { Log.d("ShowMote", cm.message() + " -- From line " + cm.lineNumber() + " of " + cm.sourceId() ); return true; } 

实现后,你会得到你的Javascript错误和打印语句( console.log )在你的logcat。

我创建了一个漂亮的包装来调用JavaScript方法; 它也显示日志中的JavaScript错误:

 private void callJavaScript(String methodName, Object...params){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("javascript:try{"); stringBuilder.append(methodName); stringBuilder.append("("); for (int i = 0; i < params.length; i++) { Object param = params[i]; if(param instanceof String){ stringBuilder.append("'"); stringBuilder.append(param); stringBuilder.append("'"); } if(i < params.length - 1){ stringBuilder.append(","); } } stringBuilder.append(")}catch(error){Android.onError(error.message);}"); webView.loadUrl(stringBuilder.toString()); } 

你也需要添加这个:

 private class WebViewInterface{ @JavascriptInterface public void onError(String error){ throw new Error(error); } } 

并将此界面添加到您的webview:

 webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new WebViewInterface(), "AndroidErrorReporter"); 

@Ilya_Gazman答案的修改

  private void callJavaScript(WebView view, String methodName, Object...params){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("javascript:try{"); stringBuilder.append(methodName); stringBuilder.append("("); String separator = ""; for (Object param : params) { stringBuilder.append(separator); separator = ","; if(param instanceof String){ stringBuilder.append("'"); } stringBuilder.append(param); if(param instanceof String){ stringBuilder.append("'"); } } stringBuilder.append(")}catch(error){console.error(error.message);}"); final String call = stringBuilder.toString(); Log.i(TAG, "callJavaScript: call="+call); view.loadUrl(call); } 

将正确地创建JS调用,例如

 callJavaScript(mBrowser, "alert", "abc", "def"); //javascript:try{alert('abc','def')}catch(error){console.error(error.message);} callJavaScript(mBrowser, "alert", 1, true, "abc"); //javascript:try{alert(1,true,'abc')}catch(error){console.error(error.message);} 

请注意,对象不会被正确传递 – 但是可以在传递参数之前序列化它们。

此外,我已经改变了错误的地方,我已经转移到控制台日志,可以通过:

  webView.setWebChromeClient(new CustomWebChromeClient()); 

和客户

 class CustomWebChromeClient extends WebChromeClient { private static final String TAG = "CustomWebChromeClient"; @Override public boolean onConsoleMessage(ConsoleMessage cm) { Log.d(TAG, String.format("%s @ %d: %s", cm.message(), cm.lineNumber(), cm.sourceId())); return true; } }