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();
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
}
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With