13

我试图找出一种处理 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 Web 浏览器可以很好地处理 Javascript 重定向的后退按钮!它遵循重定向很好,但后退按钮执行用户期望它执行的操作。这意味着可以正确处理这种情况。Android 网络浏览器如何处理这个问题?

4

7 回答 7

9

检测用户何时触发 url 加载,并将其添加到 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();
    }
}
于 2014-06-12T16:56:45.983 回答
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 中声明的

于 2013-05-22T00:32:25.773 回答
1

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

当我单击第一个链接(www.new.a)时,它会自动重定向其他链接(mobile.new.a)。通常链接重定向两个或三个,我的解决方案几乎适用于每个重定向链接。我希望这个答案可以帮助您解决 annyoing 重定向链接。

我终于想通了。您需要一个具有四个 API 的 WebViewClient。WebViewClient中有shouldOverrideUrlLoading()、onPageStarted()、onPageFinished()和doUpdateVisitedHistory()。您需要的所有 API 都是 API 1,所以不用担心。

这是我的答案。看看那个!:)

于 2014-07-23T01:33:35.777 回答
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会自动加载url。如果您手动加载 url,历史记录将不正确。

于 2018-05-30T01:38:08.983 回答
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;
    }
}
于 2019-12-09T02:28:32.030 回答
0

正确的答案是按照https://stackoverflow.com/a/8644978/5022858https://developer.android.com/reference/android/webkit/WebViewClient.htmlfalse中的shouldOverrideUrlLoading()描述返回。这可以防止重定向被添加到历史列表中。

于 2017-05-17T07:56:57.597 回答
0

这个片段对我有用,试试吧:

@Override
public void onBackPressed() {
    BlankFragment fragment = (BlankFragment)
            getSupportFragmentManager().findFragmentByTag("webView");
    if (fragment.canGoBack()) {
        fragment.goBack();
    } else {
        super.onBackPressed();
    }
  }
于 2016-09-09T14:13:11.897 回答