Android的同步的Javascript的WebView的棒棒糖 [英] Android Synchronous Javascript with WebView on Lollipop

查看:920
本文介绍了Android的同步的Javascript的WebView的棒棒糖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从使用的http://www.gutterbling.com/blog/synchronous-javascript-evaluation-in-android-webview/我们已经成功地实现我们的应用程序,让我们的Andr​​oid应用同步从网页视图获取数据中的多项功能。

下面是从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆