Android的同步的Javascript的WebView的棒棒糖 [英] Android Synchronous Javascript with WebView on Lollipop
问题描述
从使用的http://www.gutterbling.com/blog/synchronous-javascript-evaluation-in-android-webview/我们已经成功地实现我们的应用程序,让我们的Android应用同步从网页视图获取数据中的多项功能。
下面是从gutterbling的例子:
进口java.util.concurrent.CountDownLatch;
进口java.util.concurrent.TimeUnit中;进口android.content.Context;
进口android.util.Log;
进口android.webkit.WebView;
/ **
*提供用于获取同步的JavaScript调用的接口
* @author btate
*
* /
公共类SynchronousJavascriptInterface {/ **用于记录的标记。 * /
私有静态最后弦乐TAG =SynchronousJavascriptInterface;/ **添加到Web视图中的JavaScript接口名称。 * /
私人最终字符串接口名=SynchJS;/ **用于倒计时锁等待的结果。 * /
私人CountDownLatch闩锁= NULL;/ **返回值等待。 * /
私人字符串的returnValue;/ **
*基础构造。
* /
公共SynchronousJavascriptInterface(){}
/ **
*评估除权pression和返回值。
* @参数web视图
* @参数前pression
* @返回
* /
公共字符串getJSValue(web视图网页视图,字符串前pression)
{
锁存=新CountDownLatch(1);
字符串code =JavaScript的:窗口。 +接口名+.setValue((函数(){尝试{返回+ EX pression
++ \\\\;}赶上(js_eval_err){返回'';}})());;
webView.loadUrl(code); 尝试{
//设置1秒超时的情况下,有一个错误
latch.await(1,TimeUnit.SECONDS);
返回的returnValue;
}赶上(InterruptedException的E){
Log.e(TAG,中断,E);
}
返回null;}
/ **
*接收来自JavaScript中的价值。
* @参数值
* /
公共无效的setValue(字符串值)
{
的returnValue =价值;
尝试{latch.countDown(); }赶上(例外五){}
}/ **
*获取接口名称
* @返回
* /
公共字符串getInterfaceName(){
返回this.interfaceName;
}
}
这JS接口用于这样的:
的WebView web视图=新的WebView(背景);
SynchronousJavascriptInterface jsInterface =新jsInterface();
webView.addJavascriptInterface(jsInterface,jsInterface.getInterfaceName());字符串jsResult = jsInterface.getJSValue(web视图,2 + 5);
尽管在Android 4.0的工作很好 - 4.4.4。这不是为我们工作了Android 5.0(棒棒堂)
看来好像在棒棒堂JS执行锁存倒计时完成后,而previously会倒计时结束之前的返回值。
有事与JS在网页视图执行螺纹上的改变?而有没有什么办法,我可以解决这个问题,而无需重新编写我们的应用程序的大块依赖于能够同步调用JS?
使用loadURL(JavaScript的:+ code)
不符合API> 19的工作,而不是使用方法:
evaluateJavascript(code,NULL);
或者,你可以提高你的code使用由evaluateJavascript提供的回调,虽然。
Using a technique borrowed from http://www.gutterbling.com/blog/synchronous-javascript-evaluation-in-android-webview/ we have successfully implemented a number of features within our app that allow our Android app to synchronously get data from a Webview.
Here's the example from gutterbling:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.util.Log;
import android.webkit.WebView;
/**
* Provides an interface for getting synchronous javascript calls
* @author btate
*
*/
public class SynchronousJavascriptInterface {
/** The TAG for logging. */
private static final String TAG = "SynchronousJavascriptInterface";
/** The javascript interface name for adding to web view. */
private final String interfaceName = "SynchJS";
/** Countdown latch used to wait for result. */
private CountDownLatch latch = null;
/** Return value to wait for. */
private String returnValue;
/**
* Base Constructor.
*/
public SynchronousJavascriptInterface() {
}
/**
* Evaluates the expression and returns the value.
* @param webView
* @param expression
* @return
*/
public String getJSValue(WebView webView, String expression)
{
latch = new CountDownLatch(1);
String code = "javascript:window." + interfaceName + ".setValue((function(){try{return " + expression
+ "+\"\";}catch(js_eval_err){return '';}})());";
webView.loadUrl(code);
try {
// Set a 1 second timeout in case there's an error
latch.await(1, TimeUnit.SECONDS);
return returnValue;
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted", e);
}
return null;
}
/**
* Receives the value from the javascript.
* @param value
*/
public void setValue(String value)
{
returnValue = value;
try { latch.countDown(); } catch (Exception e) {}
}
/**
* Gets the interface name
* @return
*/
public String getInterfaceName(){
return this.interfaceName;
}
}
This JS Interface is used like this:
WebView webView = new WebView(context);
SynchronousJavascriptInterface jsInterface = new jsInterface();
webView.addJavascriptInterface(jsInterface, jsInterface.getInterfaceName());
String jsResult = jsInterface.getJSValue(webView, "2 + 5");
Despite working nicely in Android 4.0 - 4.4.4 this is not working for us with Android 5.0 (Lollipop).
It appears as though in Lollipop the JS executes after the latch countdown has completed, whereas previously it would return a value prior to the countdown completing.
Has something changed with the threads that JS in an Webview executes on? And is there any way that I can fix this without re-writing the large chunks of our app that depend on being able to call the JS synchronously?
loadUrl("javascript:" + code)
don't work with API > 19, instead use:
evaluateJavascript(code, null);
Or, you can improve your code to use the callback provided by evaluateJavascript, though.
这篇关于Android的同步的Javascript的WebView的棒棒糖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!