【问题标题】:How to control the Android WebView history/back stack?如何控制 Android WebView 历史/回栈?
【发布时间】:2013-01-01 16:33:59
【问题描述】:

我正在尝试找出一种方法来处理 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 网页浏览器是如何处理这个问题的?

【问题讨论】:

    标签: android


    【解决方案1】:

    这个 sn-p 对我有用,试试吧:

    @Override
    public void onBackPressed() {
        BlankFragment fragment = (BlankFragment)
                getSupportFragmentManager().findFragmentByTag("webView");
        if (fragment.canGoBack()) {
            fragment.goBack();
        } else {
            super.onBackPressed();
        }
      }
    

    【讨论】:

      【解决方案2】:
      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;
          }
      }
      

      【讨论】:

        【解决方案3】:
        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);
        }
        

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

        【讨论】:

        • 我没有完全理解你在说什么。你能澄清一下吗?
        • 抱歉这么晚才回复。我修改了我的帖子。
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          我遇到了与您类似的问题,并找到了解决方法。这里是my answer

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

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

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

          【讨论】:

            【解决方案6】:

            检测用户何时触发 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();
                }
            }
            

            【讨论】:

            • 此解决方案存在一个问题。即使用户滚动 webview,它也会在 arrayList 中保存相同的 url。当我们点击 backpress 时,会加载相同的 url。
            【解决方案7】:

            你的 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中声明的

            【讨论】:

              猜你喜欢
              • 2012-12-18
              • 1970-01-01
              • 2012-01-17
              • 2014-06-10
              • 1970-01-01
              • 2011-02-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多