Android 的 WebView 中的 JavascriptInterface : multiple calls to JS cause deadlock

标签 javascript android webview

这是我使用过的全部 Java 代码。我将在下面更详细地解释...

public class Test7 extends Activity {
    //debug
    private final static String TAG = "JSInterface";

    private WebView wv;

    private class JSInterface {
        private WebView wv;

        // Variables to manage interfacing with JS
        private String returnValue;
        private boolean canReadReturnValue;
        private Lock lockOnJS;
        private Condition condVarOnJS;

        public JSInterface (WebView wv) {
            this.wv = wv;       
            this.canReadReturnValue = false;
            this.lockOnJS = new ReentrantLock();
            this.condVarOnJS = lockOnJS.newCondition();
        }

        public void setReturnValue(String ret) {
            lockOnJS.lock();
            returnValue = ret;
            canReadReturnValue = true;
            condVarOnJS.signal();
            lockOnJS.unlock();
            Log.d(TAG, "returnValue = " + returnValue);
        }

        public String getReturnValue() {
            Log.d(TAG, "enter in getReturnValue");
            lockOnJS.lock();
            while (!canReadReturnValue) {
                try {
                    Log.d(TAG, "get wait...");
                    condVarOnJS.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            lockOnJS.unlock();
            Log.d(TAG, "returnValue: " + returnValue);
            return returnValue;
        }

        public String getNewString() {
            wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");         
            return getReturnValue();
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        wv = (WebView) findViewById(R.id.webView1);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.addJavascriptInterface(new JSInterface(wv), "JSInterface");
        wv.loadUrl("file:///android_asset/prova7.html");
    }

    public void button1(View v) {
        wv.loadUrl("javascript:func('1')");
    }
}

而且看起来工作正常。

你可以看到我有一个按钮(我们可以称之为button1),点击它,它会尝试执行一个JS方法,叫做func().

public void button1(View v) {
    wv.loadUrl("javascript:func('1')");
}

在这个 JS 方法中,我必须调用另一个 Java 方法。这是代码:

function func(id) {
    document.getElementById(id).innerHTML = JSInterface.getNewString();
}

我需要将 JSInterface.getNewString() 的结果返回给 innerHTML 变量。

JSInterface.getNewString()的代码是这样的:

public String getNewString() {
    wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");         
    return getReturnValue();
}

你可以看到我使用方法setReturnValuegetReturnValue来返回另一个JS方法返回的值。这是代码:

function createNewString() {
    return "my New String";
}

问题是,当我尝试设置 returnValue 时,函数 createNewString 永远不会执行!如果我添加 console.log() 行,我的 logCat 什么都不显示!

我不明白为什么会这样。

最佳答案

所有 javascript 和从 javascript 调用的 JSInterface 方法都在 Android WebView 中的单线程上运行。因此,当您在 condVarOnJS.await() 中等待时,无法执行任何 javascript,因为它是在同一线程上执行的。

此外,您应用程序中的所有 webview 实例共享同一个 javascript 线程。

关于Android 的 WebView 中的 JavascriptInterface : multiple calls to JS cause deadlock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7981400/

相关文章:

javascript - 小数组拼图。解释不清楚

Android 11 无法获取文件路径

android - 错误:.dex文件中方法引用的数量不能超过64k

Android:检测导航栏可见性

android - 在 webview 中播放本地视频

javascript - 将javascript变量从一个html页面传递到另一个页面

javascript - 为什么我无法在 Tracker.Autorun 中访问 React 状态?

javascript - 如何解决nodejs uncaughtException : Connection already released error and MaxListenersExceededWarning?

Android WebView.loadDataWithBaseURL 第一页加载一团糟。如何解决?

android - 如何强制 WebView 将长行文本分成多行?