4ntoine
4ntoine

Reputation: 20422

Android WebView.loadUrl() freezes the page after evaluating javascript?

I'd like to modify loaded by Android WebView page with JS (in this example just show alert from JS):

private static final String script2 = "alert('hello world');";

webView.setWebChromeClient(new WebChromeClient() {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            Toast.makeText(MainActivity.this, "Alert from js:\n" + message, Toast.LENGTH_LONG).show();
            return true; // ANSWER found:should return false in order NOT to freeze
        }
    });

webView.setWebViewClient(new WebViewClient() {

        @Override
        public void onPageFinished(WebView view, String url) {
            getSupportActionBar().setTitle("Finishing ");
            getSupportActionBar().setSubtitle(url);

            if (cbScript2.isChecked()) { // true
                runScript(script2);
            }

            getSupportActionBar().setTitle("Finished");
        }
    });

private void runScript(String script) {
    if (cbApi19.isChecked())  // true
        webView.evaluateJavascript(script, null);
    else
        webView.loadUrl("javascript:" + script);
}

After evaluating javascript (using evaluateJavascript or .loadUrl("javascript:" ...) the page becomes unresponsive - it can't be scrolled or the links clicked.

According to the docs: evaluateJavascript

Asynchronously evaluates JavaScript in the context of the currently displayed page.

Why does it freeze the page? Can i execute my JS without any affect on the page behaviour?

Upvotes: 2

Views: 2633

Answers (2)

Nayan Srivastava
Nayan Srivastava

Reputation: 3725

A little late to the party but hopefully will help someone else facing the same problem.

The problem occurs when you try to handle JS alert in native and do not notify JS about your final action with alert. The JsAlert variable should be invoked with cancel or confirm action once user deals with native alert.

@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
           new AlertDialog.Builder(this)
                        .setMessage(message)
                        .setPositiveButton(R.string.ok, (dialog, which) -> {
                            dialog.dismiss();
                            result.cancel();
                        }).setCancelable(false)
                        .show();

                return true;
     }

Upvotes: 2

4ntoine
4ntoine

Reputation: 20422

The reason was that i was using WebChromeClient and alert as a way to check JS is working. I was returning true and after changing to false it's not freezing any more (updated the question with source code and comment where it can be fixed).

Docs:

/**
 * Tell the client to display a javascript alert dialog.  If the client
 * returns true, WebView will assume that the client will handle the
 * dialog.  If the client returns false, it will continue execution.
 * @param view The WebView that initiated the callback.
 * @param url The url of the page requesting the dialog.
 * @param message Message to be displayed in the window.
 * @param result A JsResult to confirm that the user hit enter.
 * @return boolean Whether the client will handle the alert dialog.
 */
public boolean onJsAlert(WebView view, String url, String message,
        JsResult result) {
    return false;
}

Upvotes: 1

Related Questions