Android在WebView中调用JavaScript函数
我想调用一些javascript
函数坐在一个运行在一个android webview
的html
页面。 很简单,下面的代码试图做的 – 从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; } }