'Android WebView - navigating back on URL redirection
I have a question on the Android webview.
Assume URL A redirects to URL B.
My android application when it tries to open URL A, webview automatically redirects to URL B.
If a URL is being redirected to some other url, I see both these urls are stored in webview history. Now my webview history consists of [, , URL A, URL B ]
On back key click from URL B webpage, webview will try to load URL A, which again redirects to URL B. We need to double click back key to go back beyond URL A
How do I solve this issue ? Struggling from the past 2 hours :(
Solution 1:[1]
I have a same problem too, and figured out how to solve it. It's like yours. When I click the first link(www.new.a) it automatically redirects other link(mobile.new.a). Usually the links redirect two or three, and my solution have been worked on almost every redirect links. I hope this answer help you out with annyoing redirecting links.
I finally figured out that. You need a WebViewClient with four APIs. There are shouldOverrideUrlLoading(), onPageStarted(), onPageFinished(), and doUpdateVisitedHistory() in the WebViewClient. All the APIs you need is API 1 so don't worry about.
It goes like this. You can use other function rather than onKeyUp().
public class MyWebView extends WebView{
...
private int mRedirectedCount=0;
....
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && this.canGoBack()) {
if(mRedirectedCount>0){
while(mRedirectedCount>0){
this.goBack();
mRedirectedCount--;
}
mRedirectedCount=0; //clear
}else{
this.goBack();
}
return true;
}
private class MyWebViewClinet extends WebViewClient{
boolean mIsPageFinished=true;
...
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
.....
if(mIsPageFinished){
mRedirectedCount=0; //clear count
}
.....
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
mIsPageFinished = false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mIsPageFinished = true;
}
@Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
super.doUpdateVisitedHistory(view, url, isReload);
if(!mIsPageFinished){
mRedirectedCount++;
}
}
Solution 2:[2]
private class HelloWebViewClient extends WebViewClient {
}
mWebView.setWebViewClient(new HelloWebViewClient());
If overriding shouldOverrideUrlLoading(), then return false.
May not be correct way but it works for me.
Solution 3:[3]
i have the problem too, now already solved the problem.
**If WebViewClient is provided, return true means the host application handles the url, while return false means the current WebView handles the url. **
Solution 4:[4]
KOTLIN 2022
(Ignore some my codes, for example "intent.extras" or "with(webView.settings)" - if you don't need these settings of webView and yes I am not using viewBinding!!!)
Tried all my best to solve this problem + also fixed: when you clicking some toolbars in webpage which is something like show something without opening a new url, it was adding('cuz onTouch see below) current url again to our arrayList and when you were clicking "back" it was refreshing -> current url to current url. Best solution is here:
class WebActivity : AppCompatActivity(), View.OnTouchListener {
private lateinit var url: String
private lateinit var webView: WebView
private lateinit var progressBar: ProgressBar
private var mLastUrl: String? = null
private val previous: ArrayList<String> = ArrayList()
@SuppressLint("SetJavaScriptEnabled", "ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_web)
url = intent.extras!!.getString("url").toString()
webView = findViewById(R.id.appWebView)
progressBar = findViewById(R.id.webViewProgressBar)
CookieManager.getInstance().setAcceptCookie(true)
webView.webViewClient = (object : WebViewClient(){
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
progressBar.visibility = View.VISIBLE
}
override fun onPageFinished(view: WebView?, url: String?) {
Log.i("DebugDebug", "OnPageFinished " + url);
super.onPageFinished(view, url)
mLastUrl = url
progressBar.visibility = View.GONE
}
})
webView.setOnTouchListener(this)
with(webView.settings) {
javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true
domStorageEnabled = true
databaseEnabled = true
loadWithOverviewMode = true
useWideViewPort = true
builtInZoomControls = true
displayZoomControls = false
setSupportZoom(true)
defaultTextEncodingName = "utf-8"
}
webView.loadUrl(url)
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, mE: MotionEvent?): Boolean {
val hr = (v as WebView).hitTestResult
if(hr != null && mLastUrl != null){
if (previous.isEmpty() || previous[previous.size - 1] != mLastUrl) previous.add(mLastUrl!!)
}
Log.i("DebugDebug", "getExtra = " + hr.getExtra() + "\t\t Type = " + hr.getType())
return false
}
override fun onBackPressed() {
Log.i("DebugDebug", "onBackPressed loaded and removed" + previous.toString());
if (previous.size > 0 && webView.url != previous[previous.size - 1]){
webView.loadUrl(previous[previous.size - 1])
previous.removeAt(previous.size - 1)
}
}
}
Solution 5:[5]
Try to overload the OnBackPressed() to overide the default hard key back action. there u can finish the current activity or control how you want.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | kapex |
| Solution 3 | Community |
| Solution 4 | Suraj Rao |
| Solution 5 | karthik |
