1

To explain what I want to achieve I wrote what I'm able to do and then - when a problem appears. What works well:

1) I have webView1 containing in loaded HTML

<button onclick="android.buttonPressed();">Click</button>

binded with interface:

private class WebAppInterface1 {
    Context context;

    WebAppInterface1(Context c) {
        context = c;
    }

    @JavascriptInterface
    public void buttonPressed() {
        Toast.makeText(context, "buttonPressed", Toast.LENGTH_LONG).show();
    }
}

The HTML button works.

2) I have webView2 containing in loaded HTML

<script>
    function f() {
        document.write("bla bla bla");
    }
</script>

Then I call

webView2.loadUrl("javascript:f();");

in android code and it works too.


Now I want to modify webView2's page by pressing button in webView1. Technically it means that I want to call f() inside webView2 when JS interface detected click in webView1. So I add this line

webView2.loadUrl("javascript:f();");

in buttonPressed() function inside JS interface. But it has no effect. What can cause the problem? Are there any limitations in connecting these reciever and sender? Maybe I missed some settings or permissions?

There are my project files, I tried to make them as simple as possible: layout, html, java. Didn't edit other files. Can give any additional information if needed.

Pavel
  • 5,374
  • 4
  • 30
  • 55

1 Answers1

0

I understood that my problem is related to another problem: one can't update UI from non-main thread (was covered on SO here and here). But in my case there isn't any errors for some reason. Maybe because of JavaScript isn't as "strict" as Java.

So solved by adding android.os.Handler in my activity class, assigning it in onCreate function:

handler = new Handler() {
    public void handleMessage(Message msg) {
        webView2.loadUrl("javascript:f()");
    }
}

and accessing it in buttonPressed function:

handler.obtainMessage(1).sendToTarget();

P.S. Another way is to wrap calling webView2.loadUrl("javascript:f()"); by Runnable and calling runOnUiThread(runnable). It looks more neat:

webView1.addJavascriptInterface(new Object() {
    @JavascriptInterface
    public void buttonPressed() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                webView2.loadUrl("javascript:f()");
            }
        });
    }
}, "android");

P.P.S. Enabling Java 8 in app/build.gradle allows to write it even more neat:

runOnUiThread(()->{webView2.loadUrl("javascript:f()");});
Community
  • 1
  • 1
Pavel
  • 5,374
  • 4
  • 30
  • 55