最近做项目,遇到一个需求,因为是国际化项目,在新的国家部署机房,在该机房部署的H5域名和原来的不一样,要求客户端拦截H5,并更改Host。

尝试了几种方案如下:

重写WebView loadUrl()方法,在该方法中更改Url。

@Override

public void loadUrl(String url) {

......

url = convertUrl(url);

......

// 必须调用super,让系统继续加载新的url

super.loadUrl(url);

}

复制代码

上面的方案,在测试中发现,H5页面中有跳转二级页面时,没有走。

重写WebViewClient shouldOverrideUrlLoading()方法

先来看下源码的注释

/**

* Give the host application a chance to take over the control when a new

* url is about to be loaded in the current WebView. If WebViewClient is not

* provided, by default WebView will ask Activity Manager to choose the

* proper handler for the url. If WebViewClient is provided, return true

* means the host application handles the url, while return false means the

* current WebView handles the url.

* This method is not called for requests using the POST "method".

*

* @param view The WebView that is initiating the callback.

* @param url The url to be loaded.

* @return True if the host application wants to leave the current WebView

* and handle the url itself, otherwise return false.

* @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)

* shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.

*/

@Deprecated

public boolean shouldOverrideUrlLoading(WebView view, String url) {

return false;

}

/**

* Give the host application a chance to take over the control when a new

* url is about to be loaded in the current WebView. If WebViewClient is not

* provided, by default WebView will ask Activity Manager to choose the

* proper handler for the url. If WebViewClient is provided, return true

* means the host application handles the url, while return false means the

* current WebView handles the url.

*

*

Notes:

*

*

This method is not called for requests using the POST "method".

*

This method is also called for subframes with non-http schemes, thus it is

* strongly disadvised to unconditionally call {@link WebView#loadUrl(String)}

* with the request's url from inside the method and then return true,

* as this will make WebView to attempt loading a non-http url, and thus fail.

*

*

*

* @param view The WebView that is initiating the callback.

* @param request Object containing the details of the request.

* @return True if the host application wants to leave the current WebView

* and handle the url itself, otherwise return false.

*/

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {

return shouldOverrideUrlLoading(view, request.getUrl().toString());

}

复制代码

如果开发没有设置WebViewClient,WebView会让Activity Manager选择合适的处理方法(可能使用浏览器)。如果设置了WebViewClient,该方法返回true,则主程序处理改url,如果返回false,则当前WebView处理,即系统默认处理。(不会执行WebView的loadUrl方法)

最开始的想法是在shouldOverrideUrlLoading()方法更改url,不过发现,这里可以拦截到,但更改后的url,无法让系统默认加载。只能主程序显示调用加载。

@Override

public boolean shouldOverrideUrlLoading(final String url) {

if (isInterceptUrlLoading(url)) {

// 重点处理二级页面跳转的情况

// 如果直接返回false,会由系统默认加载,则无法改变url,且也不会走到loadUrl中,无法在该方法中更改url

getWebView().loadUrl(url);

return true;

}

return false;

}

复制代码寻找其他更优解法

上面方法2的解法,会改变原来url的加载方式,所以找了找有没有其他更好的办法。

重写WebViewClient的shouldInterceptRequest方法。

/**

* Notify the host application of a resource request and allow the

* application to return the data. If the return value is null, the WebView

* will continue to load the resource as usual. Otherwise, the return

* response and data will be used. NOTE: This method is called on a thread

* other than the UI thread so clients should exercise caution

* when accessing private data or the view system.

*

* @param view The {@link android.webkit.WebView} that is requesting the

* resource.

* @param url The raw url of the resource.

* @return A {@link android.webkit.WebResourceResponse} containing the

* response information or null if the WebView should load the

* resource itself.

* @deprecated Use {@link #shouldInterceptRequest(WebView, WebResourceRequest)

* shouldInterceptRequest(WebView, WebResourceRequest)} instead.

*/

@Deprecated

public WebResourceResponse shouldInterceptRequest(WebView view,

String url) {

return null;

}

/**

* Notify the host application of a resource request and allow the

* application to return the data. If the return value is null, the WebView

* will continue to load the resource as usual. Otherwise, the return

* response and data will be used. NOTE: This method is called on a thread

* other than the UI thread so clients should exercise caution

* when accessing private data or the view system.

*

* @param view The {@link android.webkit.WebView} that is requesting the

* resource.

* @param request Object containing the details of the request.

* @return A {@link android.webkit.WebResourceResponse} containing the

* response information or null if the WebView should load the

* resource itself.

*/

public WebResourceResponse shouldInterceptRequest(WebView view,

WebResourceRequest request) {

return shouldInterceptRequest(view, request.getUrl().toString());

}

复制代码

该方法可以拦截所有请求,除了Html的页面,其他资源js、css都会拦截到。

通过注释,如果返回null,则WebView还是会默认加载原来的url,需要自己创建WebResourceResponse。

可以在此处做离线资源的加载,但不适合只更改url,因为无法创建WebResourceResponse。

结论

最后使用方法1和方法2的结合来处理的。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[Android WebView拦截且更改Url]http://www.zyiz.net/tech/detail-131790.html

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐