Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to control the Android WebView history/back stack?

Tags:

android

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?

like image 337
Paula Bean Avatar asked Jan 18 '13 01:01

Paula Bean


3 Answers

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();
    }
}
like image 55
sihrc Avatar answered Oct 18 '22 02:10

sihrc


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

like image 7
Narasimha Avatar answered Oct 18 '22 01:10

Narasimha


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! :)

like image 1
theWook Avatar answered Oct 18 '22 02:10

theWook