如何控制Android WebView历史/后台堆栈?

时间:2013-01-18 01:01:09

标签: android

我正在尝试找出一种处理WebView后台堆栈的方法,类似于在我自己的应用程序的WebView中按下后退按钮时Android Web浏览器如何处理它。

问题与 Javascript重定向有关。 WebView后备堆栈似乎包含只是重定向的URL。这是我的相关代码:

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);
}

如您所见,按后退按钮可选择堆栈中的上一个URL,该URL在调用shouldOverrideUrlLoading()之后加载到WebView本身。我实际上在shouldOverrideUrlLoading()中做了很多与这个特定问题无关的事情,所以“删除我的WebViewClient实现”对我来说不起作用。无论如何,当前一个URL是Javascript重定向时,该URL加载,然后Javascript立即重定向到WebView所在的URL。我无法禁用Javascript,因为网站依赖于它。我也无法更改网站(第三方)。

此重定向问题的结果是最终用户的恶性循环,他们疯狂地回击只是为了比Android网页处理引擎稍快。

现在这里有趣的地方:Android网页浏览器处理后退按钮就好了Javascript重定向!它遵循重定向很好,但后退按钮执行用户期望它做的事情。这意味着可以正确处理这种情况。 Android Web浏览器如何处理此问题?

7 个答案:

答案 0 :(得分:6)

你的onKeyDown应该看起来像这些

@Override
   public boolean onKeyDown(int keyCode, KeyEvent event)
  {
    if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
        myWebView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
   }

这里myWebView在Activity的onCreate

中声明

答案 1 :(得分:6)

检测用户是否触发了网址加载,然后将其添加到Backstack中。

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();
    }
}

答案 2 :(得分:1)

我和你的问题有类似的问题,并找到了解决问题的方法。这是my answer

当我点击第一个链接(www.new.a)时,它会自动重定向其他链接(mobile.new.a)。通常链接重定向两个或三个,我的解决方案几乎在每个重定向链接上都有效。我希望这个答案可以帮助你改进重定向链接。

我终于明白了。您需要一个包含四个API的WebViewClient。 WebViewClient中有shouldOverrideUrlLoading(),onPageStarted(),onPageFinished()和doUpdateVisitedHistory()。您需要的所有API都是API 1,所以不要担心。

这是my answer。看看那个! :)

答案 3 :(得分:0)

this snippet work for me, try this. 
@Override
public void onBackPressed() {
    BlankFragment fragment = (BlankFragment)
            getSupportFragmentManager().findFragmentByTag("webView");
    if (fragment.canGoBack()) {
        fragment.goBack();
    } else {
        super.onBackPressed();
    }
  }

答案 4 :(得分:0)

正确的答案是按https://stackoverflow.com/a/8644978/5022858https://developer.android.com/reference/android/webkit/WebViewClient.html中的说明在false上返回shouldOverrideUrlLoading()。这可以防止重定向添加到历史列表中。

答案 5 :(得分:0)

private class ArticleWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        return false;
    }
}

@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);
}

如果你想在webview而不是系统浏览器中处理链接,这个shouldOverrideUrlLoading方法返回 false,并且不要拨打view.loadUrl(url),你的如果您返回false,webview将自动加载网址。如果您手动加载网址,则历史记录将不正确。

答案 6 :(得分:0)

boolean isGoBack = false;    //back key is pressed

private long goBackTime = 0; //

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
        isGoBack = true;
        goBackTime = System.currentTimeMillis();
        mWebView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

Webview mWebView.

setWebViewClient(new WebViewClient() { //setWebViewClient
    @Override
    public boolean shouldOverrideUrlLoading (WebView view, String url){
        if (!TextUtils.isEmpty(startUrl) && !startUrl.equals(url) && isGoBack && System.currentTimeMillis() - goBackTime < 600) {
            isGoBack = false;
            if (mWebView.canGoBack()) {
                mWebView.goBack();
            } else {
                finish(); //activity finish
            }
        } else {
            view.loadUrl(url);
            isGoBack = false;
            return true;
        }

        return false;
    }
    @Override
    public void onPageStarted (WebView view, String url, Bitmap favicon){
        super.onPageStarted(view, url, favicon);

        startUrl = url;
    }
}