WebView shouldOverrideUrlLoading and redirect问题

本文探讨了在Android平台上,当使用WebView加载链接时,API级别小于11的情况会导致shouldOverrideUrlLoading方法未被调用的问题。文章提出了平台适配方案及替代方法onPageStarted,确保下载逻辑在所有Android版本中都能正常工作。

问题:客户端界面中打开安卓市场某款产品的下载界面。点击下载按钮后,并不走客户端写在shouldOverrideUrlLoading中的处理逻辑。导致该包不能下载。

ps:安卓市场下载按钮是通过js跳转的。


原来,android平台下,在ApiLevel小于11的情况下,webview的shouldOverrideUrlLoading并不是每次都会调用。

所以需要添加平台适配。或者将放在shouldOverrideUrlLoading中的逻辑放在onPageStarted方法中去处理。


Androids WebView class provides a method called shouldOverrideUrlLoading to intercept the loading of the requested URLs.
This gives us the ability to suppress loading of the given URL or handle a URL in the external browser for example.

If you want to prevent the webview from loading the URL you have to return true. Otherwise the url is forwarded to the webview as usual.

  1. _webView.setWebViewClient(new WebViewClient() {  
  2.   @Override  
  3.   public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  4.     boolean shouldOverride = false;  
  5.     if (url.startsWith("https://")) { //NON-NLS  
  6.       // DO SOMETHING  
  7.       shouldOverride = true;  
  8.     }  
  9.     return shouldOverride;  
  10.   }  
  11. }  

This mechanism works fine for all URLs triggered by a user tapping on a link.

Unfortunately this method does not get invoked if the URLs source is a redirect on devices running Android < 3.0 (API Level 10 and lower).
Although it will be invoked an works just fine on devices with Android >= 3.0 (API Level 11 and up).

Android < 3.0 -> shouldOverrideUrlLoading will not be called on redirects

Android >= 3.0 -> shouldOverrideUrlLoading will be called even on redirects

You can find some fellow developers facing the same issue.

As a Workaround we use the recommended onPageStarted(WebView view, String url, Bitmap favicon)

Usage is quite the same as shouldOverrideUrlLoading:

  1. _webView.setWebViewClient(new WebViewClient() {  
  2.   @Override  
  3.   public void onPageStarted(WebView view, String url, Bitmap favicon){  
  4.     if (url.startsWith("https://")) { //NON-NLS  
  5.       view.stopLoading();  
  6.       // DO SOMETHING  
  7.     }  
  8.   }  
  9. }   

With view.stopLoading the webview will stop loading of the new URL and still show the current content. This equals the behavior of shouldOverrideUrlLoading returning true.

The advantage is it works on all Android versions.

However the drawback is onPageStarted is invoked AFTER the page was requested form server. That means, the request is already sent to the server even if the response is afterward ignored.

The method shouldOverrideUrlLoading would let you omit the request BEFORE it is sent. So you would be able to save the outgoing web request.


<think>好的,我现在需要回答用户关于Android WebViewshouldOverrideUrlLoading方法的触发条件和使用场景的问题。首先,我需要回顾一下这个方法的定义和它在WebView中的作用。 用户提到了几个引用,其中引用[1]和[3]提到shouldOverrideUrlLoading是在自定义WebViewClient时重写的方法,用于拦截URL加载。引用[4]讨论了重定向问题,说明在重定向过程中会多次触发这个方法。引用[2]则涉及Cookie同步,虽然相关,但可能和触发条件关系不大。 首先,触发条件方面,根据官方文档,当WebView要加载新的URL时,无论是用户点击链接、表单提交、JavaScript重定向,还是通过location.href等方式触发的导航,都会调用shouldOverrideUrlLoading。此外,重定向链中的每一步都会触发这个方法。例如,一个页面多次重定向,每次都会调用该方法,直到返回false允许WebView处理,或者返回true由应用处理。 使用场景方面,用户可能需要拦截特定的URLscheme,比如应用内跳转或与JavaScript通信,处理第三方链接(如支付、登录),以及防止恶意重定向。例如,引用[3]提到的scheme方式就是通过拦截URL来实现原生代码调用。 需要注意的是,不同版本的Android可能行为不同。在API24及以上,shouldOverrideUrlLoading有两个重载方法,分别处理String和WebResourceRequest参数,后者能获取更多请求信息。此外,重定向时可能会多次触发,需要正确处理以避免循环问题。 最后,用户可能需要示例代码来说明如何正确使用这个方法,比如判断URL是否以特定scheme开头,然后处理并返回true,否则交由WebView处理。同时,需要注意避免处理所有URL导致性能问题,或者错误处理重定向导致页面无法加载。</think>### Android WebView shouldOverrideUrlLoading 触发条件及使用场景分析 #### 一、触发条件 1. **页面跳转事件** 当 WebView 加载新 URL 时触发,包括: - 用户点击页面内的超链接(`<a>`标签) - 表单提交(`<form>`提交) - JavaScript 调用 `window.location` 或 `location.href` - HTML5 的 `history.pushState` 导航(需 API 21+) - 重定向操作(HTTP 3xx 状态码或 `<meta http-equiv="refresh">`)[^4] 2. **重定向链处理** 在重定向链中,**每次跳转都会触发该方法**。例如: `A页面 → 302重定向到B页面 → 再次重定向到C页面`,会触发两次 `shouldOverrideUrlLoading`[^4]。 3. **跨框架加载** iframe 内触发的页面跳转也会触发该方法。 #### 二、使用场景 1. **拦截自定义协议** 处理 `myapp://` 等应用内协议,实现原生功能调用: ```java @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("myapp://")) { // 解析协议执行原生操作 return true; // 拦截请求 } return super.shouldOverrideUrlLoading(view, url); } ``` (参考 scheme 拦截方案[^3]) 2. **第三方登录/支付处理** 拦截支付宝、微信等第三方服务的 URL,跳转到对应 App: ```java if (url.contains("alipay.com")) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } ``` 3. **安全控制** 阻止加载危险域名: ```java if (isMaliciousDomain(url)) { view.stopLoading(); return true; } ``` 4. **混合导航管理** 根据 URL 路径决定使用 WebView 还是原生页面: ```java if (url.endsWith("/native_page")) { startActivity(new Intent(this, NativeActivity.class)); return true; } ``` #### 三、版本差异说明 | 特性 | API <24 | API ≥24 | |---------------------|----------------------------------|----------------------------------| | 方法签名 | `shouldOverrideUrlLoading(WebView, String)` | 新增 `shouldOverrideUrlLoading(WebView, WebResourceRequest)` | | 请求信息获取 | 仅 URL | 可获取 headers、是否重定向等元数据 | #### 四、注意事项 1. **重定向循环风险** 若在拦截逻辑中主动触发新跳转(如调用 `loadUrl`),需确保不会形成死循环。 2. **同步 Cookie 策略** 拦截后若跳转到原生页面,需手动同步 Cookie: ```java CookieManager.getInstance().flush(); // 见引用[2] ``` 3. **返回值的含义** - `return true`:WebView 不处理该 URL,由开发者接管 - `return false`:WebView 继续加载该 URL
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值