I am trying to figure out a way to handle the WebView back stack similar to how the Android web browser handles it when the back button is pressed from within my own app's WebView.
The problem has to do with Javascript redirects. The WebView back stack appears to contain URLs that simply redirect. Here is my relevant code:
private class ArticleWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK)
{
WebView wv = (WebView)findViewById(R.id.web);
if (wv.canGoBack())
{
wv.goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
As you can see, pressing the back button selects the previous URL in the stack, which loads in the WebView itself after shouldOverrideUrlLoading() is called. I'm actually doing a lot more inside shouldOverrideUrlLoading() that isn't relevant for this particular question, so "remove my WebViewClient implementation" won't work for me. At any rate, when the previous URL is a Javascript redirect, that URL loads and then Javascript immediately redirects to the URL the WebView was just at. I can't disable Javascript because the website depends on it. I also can't change the website (third-party).
The result of this redirection issue is a vicious cycle for the end-user who is frantically pressing back just to be slightly faster than the Android webpage processing engine.
Now here is where it gets interesting: The Android web browser handles the back button just fine for Javascript redirects! It follows the redirects just fine but the back button does what a user expects it to do. That means it is possible to correctly handle this scenario. How does the Android web browser handle this problem?
Detect when url loading is triggered by the user, and add those to the backstack instead.
private List<String> previous = new ArrayList<String>();
private String mLastUrl;
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
Log.i("DebugDebug", "OnPageFinished " + url);
mLastUrl = url;
super.onPageFinished(view, url);
}
});
webview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
WebView.HitTestResult hr = ((WebView)view).getHitTestResult();
if (hr != null && mLastUrl != null) {
if (previous.isEmpty() || !previous.get(previous.size() - 1).equals(mLastUrl)) {
previous.add(mLastUrl);
}
Log.i("DebugDebug", "getExtra = " + hr.getExtra() + "\t\t Type = " + hr.getType());
}
return false;
}
});
@Override
public void onBackPressed() {
Log.i("DebugDebug", "onBackPressed");
int size = previous.size();
if (size > 0){
webview.loadUrl(previous.get(size - 1));
previous.remove(size - 1);
} else {
super.onBackPressed();
}
}
your onKeyDown should look like these
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
here myWebView is declared in the Activity's onCreate
I had a similar problem with yours and found how to figure it out. Here is my answer.
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.
Here is my answer. Check out that! :)
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