WebView loadUrl ("javascript: ...") doesn't work

I am playing with an Android WebView: I have a sample text "asdf" that needs to be colored when the user clicks a button (red, green, or blue). To make things a little more complicated, the WebView first tells the Java code to initiate a color change, and then from within Java the WebView changes:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final WebView myWebView = (WebView) findViewById(R.id.webview);
        WebSettings webSettings = myWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }

        final WebAppInterface webAppInterface = new WebAppInterface(this, myWebView);
        myWebView.addJavascriptInterface(webAppInterface, "Android");
        myWebView.loadUrl("file:///android_asset/index.html");
    }
}

      

This is the interface:

public class WebAppInterface {

    Context context;
    WebView webView;

    WebAppInterface(Context context, WebView webView) {
        this.context = context;
        this.webView = webView;
    }

    @JavascriptInterface
    public void dye(String color) {
        switch (color) {
            case "red":
                webView.loadUrl("javascript:dyeRed()");
                break;
            case "green":
                webView.loadUrl("javascript:dyeGreen()");
                break;
            case "blue":
                webView.loadUrl("javascript:dyeBlue()");
                break;
        }
    }
}

      

There are 3 buttons in my html file:

<button onClick="callDyeRed()">
    RED
</button> 

      

And inside a javascript file that is loaded successfully, I have functions like this:

function callDyeRed() {
  Android.dye("red");
}
function dyeRed() {
  document.getElementsByTagName('body')[0].style.color = 'red';
}

      

When I click on the button, I see that a line is being executed inside the WebAppInterface webView.loadUrl("javascript:dyeRed()")

. This way js-> Java linking works. However, the opposite is not true: after that, the JavaScript code is not executed.

What am I missing here?

If I change the color from the WebViewClient the communication works:

myWebView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView webView, String url) {
        webView.loadUrl("javascript:dyeGreen()");
    } 
}); 

      

+3


source to share


1 answer


The JavaScript-related object runs on a different thread ("JavaBridge") than the thread ("Looper") in which it was created. All WebView methods must be called on the same thread. Therefore, you cannot call the loadUrl method on a newly created thread.

Possible workaround:

Webappinterface.java



class WebAppInterface {  

    Context context;
    WebView webView;

    WebAppInterface(Context context, WebView webView) {
        this.context = context;
        this.webView = webView;
    }

    @JavascriptInterface
    public String dye(String color) {
        switch (color) {
            case "red":
                return "dyeRed";
            case "green":
                return "dyeGreen";
            case "blue":
                return "dyeBlue";
            default:
                return "alert";

        }
    }
}

      

script.js

function callDyeRed() {
  window[Android.dye("red")]();
}
function dyeRed() {
  document.getElementsByTagName('body')[0].style.backgroundColor = 'red';
}

      

0


source







All Articles