Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android webview not loading URL for second time

I have dynamic URL that I load into a webview. I have used a WebChromeClient to handle java script events as I need to redirect the user depending on the events from the javascript in onJsAlert(). The webpage is loading for the first time. When I go back and load the same url, its loading. But, when I complete the action and receive the javascript event, I'm starting a new activity and finishing the webview activity. Now, when I load another URL, its not loading. When I kill the app and navigate to the webview activity, its loading again.

Below are my settings for the webview

        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setBuiltInZoomControls(true);
        webView.getSettings().setDisplayZoomControls(false);
        webView.getSettings().setDomStorageEnabled(true);

        webView.getSettings().setLoadWithOverviewMode(true);
        webView.getSettings().setUseWideViewPort(true);
        webView.getSettings().setAppCacheEnabled(false);

        webView.setWebViewClient(new myWebClient());
        webView.setWebChromeClient(new MyJavaScriptChromeClient());
        webView.loadUrl(signatureURL);
        webView.setHorizontalScrollBarEnabled(false);

This is the WebViewClient I'm using to show progress dialog


public class myWebClient extends WebViewClient {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            // TODO Auto-generated method stub
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            if (((BaseActivity) activity).checkConnection()) {
                // TODO Auto-generated method stub
                progressBar.setVisibility(View.VISIBLE);
                view.loadUrl(url);
            }
            return true;

        }

        @Override
        public void onPageFinished(WebView view, String url) {
            // TODO Auto-generated method stub
            super.onPageFinished(view, url);
            progressBar.setVisibility(View.GONE);
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
            progressBar.setVisibility(View.GONE);
        }
    }

This is how I'm handing JS events


private class MyJavaScriptChromeClient extends WebChromeClient {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
            //Check message for success/failure of payment
           Log.i("message",message);
           if (message.equals("Payment Fail")){
               dgAlert("Payment Failed");
           }
           else if (message.equals("Payment Success")){
               dgAlert("Payment Success");
           }
            return true;
        }
    }

This is what I'm doing on tapping OK button on the Alert Dialog

Intent intent=new Intent(Payment.this, DashBoardActivity.class);
startActivity(intent);
if (message.equals(Constants.CANCELLED)) {
   activity.finishAffinity();
   System.exit(0);
 } else
activity.finish();
like image 512
rko Avatar asked May 31 '26 13:05

rko


2 Answers

I had the same issue, reloading the url multiple times fixed the issue, override following method specially error related method in the WebViewClient and reload the url if you encounter an error, keep a max reload threshold to avoid infinite reload error loop. Also make sure webview is properly released/destroyed after use to avoid memory leak.

override fun onReceivedSslError(
                view: WebView?,
                handler: SslErrorHandler,
                error: SslError?
            ) {
                Log.e("webview", "onReceivedSslError")
                handler.proceed() // Ignore SSL certificate errors

            }
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
                Log.e("webview", "onPageStarted")
                onPageLoadStarted = true
                progressBar.visibility = View.VISIBLE
            }

            override fun onReceivedError(
                view: WebView?,
                request: WebResourceRequest?,
                error: WebResourceError?
            ) {
                super.onReceivedError(view, request, error)
                Log.e("webview", "onReceivedError" + error.toString())
                progressBar.visibility = View.GONE
                reload()

            }
            
            override fun onReceivedHttpError(
                view: WebView?,
                request: WebResourceRequest?,
                errorResponse: WebResourceResponse?
            ) {
                super.onReceivedHttpError(view, request, errorResponse)
                Log.d("webview", "onReceivedHttpError" + errorResponse?.toString())
                progressBar.visibility = View.GONE
                reload()
            } 

and Add a reload function to activity or fragment and override lifecycle method like below

var reloadCount=0
const val MAX_RELOAD_TRY = 6
fun reload() {
        if ((reloadCount <= MAX_RELOAD_TRY)) {
            reloadCount++
            webView?.clearCache(true);
            webView?.clearView();
            webView?.clearHistory()
            webView?.resumeTimers()
            webView?.reload()
        }
    }

  override fun onPause() {
        super.onPause()
        webView?.onPause()
    }
    override fun onResume() {
        super.onResume()
        webView?.onResume()
    }

    override fun onBackPressed() {
        webView?.let {
            if (it.canGoBack()) {
                it.goBack()
            } else {
                super.onBackPressed()
            }
        } ?: run {
            super.onBackPressed()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("onDestroy", "onDestroy")
        destroyWebView()
    }

    private fun destroyWebView() {
        Log.d("destroyWebView", "destroyWebView");
        // Make sure you remove the WebView from its parent view before doing anything.
        webView?.clearHistory()
        // NOTE: clears RAM cache, if you pass true, it will also clear the disk cache.
        // Probably not a great idea to pass true if you have other WebViews still alive.
        webView?.clearCache(true)
        // Loading a blank page is optional, but will ensure that the WebView isn't doing anything when you destroy it.
        //webView?.loadUrl("about:blank")
        // NOTE: This pauses JavaScript execution for ALL WebViews,
        // do not use if you have other WebViews still alive.
        // If you create another WebView after calling this,
        // make sure to call mWebView.resumeTimers().
        webView?.pauseTimers()
        webView?.removeAllViews()
        webViewContainerRL?.removeAllViews()
        webView?.destroy()
        webViewClient = null
        webChromeClient = null
        webView = null

    }
like image 81
44kksharma Avatar answered Jun 02 '26 03:06

44kksharma


For me nothing worked, just solution from here WebView doesn't load my HTML the second time?.

In Kotlin, I put this in my refresh button:

val handler = Handler()
handler.postDelayed(Runnable {
    myWebview.loadUrl("https://www.example.com")
}, 10)

or with binding, one line:

binding.myWebview.handler.postDelayed({binding.myWebview.loadUrl("https://www.example.com")},10)
like image 21
ThomasV Avatar answered Jun 02 '26 04:06

ThomasV



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!