我想从Android中的Javascript获取返回值.我可以用iPhone做到这一点,但我不能用Android.我使用了loadUrl,但它返回的是void而不是object.有谁能够帮我?谢谢.
与Keith
更短的答案相同
webView.addJavascriptInterface(this, "android"); webView.loadUrl("javascript:android.onData(functionThatReturnsSomething)");
并实现该功能
@JavascriptInterface public void onData(String value) { //.. do something with the data }
不要忘了删除onData
从proguard
列表(如果启用的ProGuard)
这是一个关于如何实现它的黑客攻击:
将此客户端添加到WebView:
final class MyWebChromeClient extends WebChromeClient { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d("LogTag", message); result.confirm(); return true; } }
现在在你的javascript调用中执行:
webView.loadUrl("javascript:alert(functionThatReturnsSomething)");
现在在onJsAlert调用"message"中将包含返回的值.
使用addJavascriptInterface()
Java对象添加到JavaScript环境.让您的Javascript调用该Java对象上的方法来提供其"返回值".
这就是我今天想出的.它是线程安全的,合理有效的,并允许从Java WebView查看同步Javascript执行.
适用于Android 2.2及更高版本.(需要commons-lang,因为我需要将我的代码片段作为Javascript字符串传递给eval().您可以通过将代码包装在引号中来删除此依赖关系,但是在中function(){}
)
首先,将其添加到您的Javascript文件中:
function evalJsForAndroid(evalJs_index, jsString) { var evalJs_result = ""; try { evalJs_result = ""+eval(jsString); } catch (e) { console.log(e); } androidInterface.processReturnValue(evalJs_index, evalJs_result); }
然后,将其添加到您的Android活动中:
private Handler handler = new Handler(); private final AtomicInteger evalJsIndex = new AtomicInteger(0); private final MapjsReturnValues = new HashMap (); private final Object jsReturnValueLock = new Object(); private WebView webView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); webView = (WebView) findViewById(R.id.webView); webView.addJavascriptInterface(new MyJavascriptInterface(this), "androidInterface"); } public String evalJs(final String js) { final int index = evalJsIndex.incrementAndGet(); handler.post(new Runnable() { public void run() { webView.loadUrl("javascript:evalJsForAndroid(" + index + ", " + "\"" + StringEscapeUtils.escapeEcmaScript(js) + "\")"); } }); return waitForJsReturnValue(index, 10000); } private String waitForJsReturnValue(int index, int waitMs) { long start = System.currentTimeMillis(); while (true) { long elapsed = System.currentTimeMillis() - start; if (elapsed > waitMs) break; synchronized (jsReturnValueLock) { String value = jsReturnValues.remove(index); if (value != null) return value; long toWait = waitMs - (System.currentTimeMillis() - start); if (toWait > 0) try { jsReturnValueLock.wait(toWait); } catch (InterruptedException e) { break; } else break; } } Log.e("MyActivity", "Giving up; waited " + (waitMs/1000) + "sec for return value " + index); return ""; } private void processJsReturnValue(int index, String value) { synchronized (jsReturnValueLock) { jsReturnValues.put(index, value); jsReturnValueLock.notifyAll(); } } private static class MyJavascriptInterface { private MyActivity activity; public MyJavascriptInterface(MyActivity activity) { this.activity = activity; } // this annotation is required in Jelly Bean and later: @JavascriptInterface public void processReturnValue(int index, String value) { activity.processJsReturnValue(index, value); } }
@Felix Khazin建议的解决方案有效,但有一个关键点缺失.
应该在WebView
加载网页后进行javascript调用.将此添加WebViewClient
到WebView
,以及WebChromeClient
.
完整示例:
@Override public void onCreate(Bundle savedInstanceState) { ... WebView webView = (WebView) findViewById(R.id.web_view); webView.getSettings().setJavaScriptEnabled(true); webView.setWebViewClient(new MyWebViewClient()); webView.setWebChromeClient(new MyWebChromeClient()); webView.loadUrl("http://example.com"); } private class MyWebViewClient extends WebViewClient { @Override public void onPageFinished (WebView view, String url){ view.loadUrl("javascript:alert(functionThatReturnsSomething())"); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } } private class MyWebChromeClient extends WebChromeClient { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.d("LogTag", message); result.confirm(); return true; } }
在API 19+,要做到这一点的最好方法是调用evaluateJavascript您的WebView:
webView.evaluateJavascript("foo.bar()", new ValueCallback() { @Override public void onReceiveValue(String value) { // value is the result returned by the Javascript as JSON } });
更详细的相关答案:https : //stackoverflow.com/a/20377857