在Android环境下WebView中拦截所有请求并替换URL示例详解

需求背景

接到这样一个需求,需要在 WebView 的所有网络请求中,在请求的url中,加上一个xxx=1的标志位。

例如 http://www.baidu.com 加上标志位就变成了 http://www.baidu.com?xxx=1

寻找解决方案

从 Android API 11 (3.0) 开始,WebView 开始在 WebViewClient 内提供了这样一条 API ,如下:

public WebResourceResponse shouldInterceptRequest(WebView view, String url)

就是说只要实现 WebViewClient 的 shouldInterceptRequest 方法,然后调用 WebView 的setWebViewClient 就可以了。

但是,在 API21 以上又弃用了上述 API,使用了一条新的 API,如下:

public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request)

好吧,为了支持尽量多的版本,看来两个都需要实现了,发现一看就非常好用的 String url 变成了一个WebResourceRequest request。WebResourceRequest 这个东西是一个接口,并且是这样定义的:

public interface WebResourceRequest {
 Uri getUrl();
 boolean isForMainFrame();
 boolean hasGesture();
 String getMethod();
 Map<String, String> getRequestHeaders();
}

在其中没有发现任何可以直接替换请求的方法。

然后搜索了一下 Android 代码中对他的引用,点我搜索。然后发现 private static class WebResourceRequestImpl implements WebResourceRequest 它的内部实现仅仅是一个单纯的实体。那这个东西要替换就非常好办了,三个方法都可以做:

  1. 动态代理
  2. 反射
  3. 重新实现

实现

方案确定了,剩下的就简单了。直接上代码。

首先是往URL字符串加那个标志位的方法

public static String injectIsParams(String url) {
 if (url != null && !url.contains("xxx=") {
  if (url.contains("?")) {
   return url + "&xxx=1";
  } else {
   return url + "?xxx=1";
  }
 } else {
  return url;
 }
}

然后要拦截所有请求了

webView.setWebViewClient(new WebViewClient() {

 @SuppressLint("NewApi")
 @Override
 public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request) {
  if (request != null && request.getUrl() != null) {
   String scheme = request.getUrl().getScheme().trim();
   if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
    return super.shouldInterceptRequest(view, new WebResourceRequest() {
     @Override
     public Uri getUrl() {
      return Uri.parse(injectIsParams(request.getUrl().toString()));
     }

     @SuppressLint("NewApi")
     @Override
     public boolean isForMainFrame() {
      return request.isForMainFrame();
     }

     @SuppressLint("NewApi")
     @Override
     public boolean hasGesture() {
      return request.hasGesture();
     }

     @SuppressLint("NewApi")
     @Override
     public String getMethod() {
      return request.getMethod();
     }

     @SuppressLint("NewApi")
     @Override
     public Map<String, String> getRequestHeaders() {
      return request.getRequestHeaders();
     }
    });
   }
  }
  return super.shouldInterceptRequest(view, request);
 }

 @Override
 public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
  if (!TextUtils.isEmpty(url) && Uri.parse(url).getScheme() != null) {
   String scheme = Uri.parse(url).getScheme().trim();
   if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
    return super.shouldInterceptRequest(view, injectIsParams(url));
   }
  }
  return super.shouldInterceptRequest(view, url);
 }

});

大功告成。

欢迎指出代码中的问题~~一起学习进步

注意: 注意保护 URL 的 Scheme,在代码中特地过滤了 http 和 https。

引申

上边的 API 中发现还能有更多的玩法,比如:

  • 替换 WebResourceResponse,构造一个自己的 WebResourceResponse。比如下列代码,用一个包里的本地文件替换掉要请求的网络图片。
WebResourceResponse response = null;
if (url.contains("logo")) {
 try {
  InputStream is = getAssets().open("test.png");
  response = new WebResourceResponse("image/png", "UTF-8", is);
 } catch (IOException e) {
  e.printStackTrace();
 }
}
return response;

在 API 21 (5.0) 以上的版本使用了 WebResourceRequest 接口,这个接口能修改发出请求的 Header

@Override
public Map<String, String> getRequestHeaders() {
 return request.getRequestHeaders();
}

在 API 21 (5.0) 以上的版本中可以区分 GET 请求和 POST 请求,在某些情况下,需要区分 AJAX 的不同种类请求的时候可以用到。

到此这篇关于在Android环境下WebView中拦截所有请求并替换URL示例详解的文章就介绍到这了,更多相关Android WebView拦截所有请求并替换URL内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-07-17

解决Android WebView拦截url,视频播放加载失败的问题

需求:Android调用webView加载网页的时候,拦截某一个链接不执行此链接,执行指定跳转到其他activity页面. webview的setWebViewClient方法中提供了几个api: // 此回调是拦截点击要跳转的url链接,并对请求的url链接做修改(添加删除字段) public WebResourceResponse shouldInterceptRequest(WebView view, String url) // 在点击请求的是链接是才会调用,重写此方法返回true表明点

Android中的webview监听每次URL变化实例

通过这个可以监听Android中webview访问的URL变化: webView.setWebViewClient(new WebViewClient(){ @Override public void onLoadResource(WebView view, String url) { Log.e("hao","WebView3:"+view.getUrl()+"\\n"+" URL3:"+url); super.onLoad

android教程使用webview访问https的url处理sslerror示例

在Android中,WebView是用来load http和https网页到本地应用的控件.在默认情况下,通过loadUrl(String url)方法,可以顺利load诸如,http://www.baidu.com之类的页面.但是,当load有ssl层的https页面时,如https://money.183.com.cn/,如果这个网站的安全证书在Android无法得到认证,WebView就会变成一个空白页,而并不会像PC浏览器中那样跳出一个风险提示框.因此,我们必须针对这种情况进行处理. A

在Android系统中使用WebViewClient处理跳转URL的方法

前言 最近代码里和WebView有很多的交互,webview是android中的浏览器控件,这里主要介绍一下webview如何重载WebViewClient类来控制URL加载. 使用WebViewClient 使用WebViewClinet主要是继承WebViewClient父类,根据需要重写其中的方法,并在WebView中进行配置,示例代码如下: webView = (WebView) findViewById(R.id.webview); webView.setWebViewClient(n

Android获取WebView加载url的请求错误码 【推荐】

例如需求,我有一个WebView 加载一个url, 该url对应的网页本身自带下拉刷新 ,但是网页本身会有出现400 500 等异常请求错误码 这时候网页加载失败,页面本身的下拉是无法使用的,要求重新加载页面的话就需要在webview外层套一个android下拉控件(SwipeRefreshLayout) 这样导致下拉一定用的SwipeRefreshLayout的下拉 最终要求是如果页面加载成功的话,用页面本身的下拉,如果页面加载失败的话,用android下拉控件的下拉 ------------

Android Webview的postUrl与loadUrl加载页面实例

关于Android的webview,用过的想必都不会陌生.这里我就不说webview的基本用法了,想要知道的可以去网上百多,有很多介绍webview基本用法的. 本文要介绍的主要是在项目过程中使用webview的postUrl遇到的坑. 1.使用场景如下: webview在加载H5链接时,默认是使用loadUrl进行加载,如果你设置了缓存属性(进行缓存),在显示的H5页面内点击跳转到另外一个页面后,按回退键,可以正常的返回到上一个页面,因为进行了缓存设置.但是如果使用postUrl进行加载,即使

Android编程实现webview执行loadUrl时隐藏键盘的workround效果

本文实例讲述了Android编程实现webview执行loadUrl时隐藏键盘的workround效果.分享给大家供大家参考,具体如下: webview执行loadUrl时隐藏键盘的workround 在写webapp的时候,经常需要用JS调用Java方法,java方法执行完毕以后,再回调JS函数来做一些事情,而webview调用js的时候是通过loadUrl方法的,一执行loadUrl就会隐藏软键盘.因为每次loadUrl操作都会调用clearHelpers方法 clearHelpers方法中

Android编程实现WebView全屏播放的方法(附源码)

本文实例讲述了Android编程实现WebView全屏播放的方法.分享给大家供大家参考,具体如下: 最近因为项目要用webview加载html5的视频,开始不能全屏播,做了很久才做出来!那按我的理解说下怎么实现全屏吧. 首先写布局文件activity_main.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.

Android编程实现webview将网页打包成apk的方法

本文实例讲述了Android编程实现webview将网页打包成apk的方法.分享给大家供大家参考,具体如下: 功能非常简单,而且乍一看没什么特别大的用处,因为实际上就是浏览器而已...但如果说网页一开始就是针对手机开发的呢?是不是可以将android的开发转变为网页的开发了?有待研究,不过据说也可以用这种方法将html5打包哦,先记录一下可能以后也可以赶下潮流. public class MainActivity extends Activity { private WebView webvie

Android编程使用WebView实现文件下载功能的两种方法

本文实例讲述了Android编程使用WebView实现文件下载功能的两种方法.分享给大家供大家参考,具体如下: 在应用中,通常会使用到文件下载功能,一般我们都是写一个下载操作工具类,在异步任务中执行下载功能. 今天我们来看下如何使用WebView的文件下载功能! 方法1,自定义下载操作 1. 先来布局 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&qu

Android编程实现WebView添加进度条的方法

本文实例讲述了Android编程实现WebView添加进度条的方法.分享给大家供大家参考,具体如下: 标准的XML界面 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

Android编程使WebView支持HTML5 Video全屏播放的解决方法

本文实例讲述了Android编程使WebView支持HTML5 Video全屏播放的解决方法.分享给大家供大家参考,具体如下: 1)需要在AndroidManifest.xml文件中声明需要使用HardwareAccelerate, 可以细化到Activity级别,如果不需要的View可以声明不要用加速,但是需要在代码中做,具体如下: a. 如果要声明整个应用都要加速: 复制代码 代码如下: <application ... android:hardwareAccelerated ="tr

Android编程使用WebView实现与Javascript交互的方法【相互调用参数、传值】

本文实例讲述了Android编程使用WebView实现与Javascript交互的方法.分享给大家供大家参考,具体如下: Android中可以使用WebView加载网页,同时Android端的Java代码可以与网页上的JavaScript代码之间相互调用. 效果图: (一)Android部分: 布局代码: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&qu

Android编程实现横竖屏切换时不销毁当前activity和锁定屏幕的方法

本文实例讲述了Android编程实现横竖屏切换时不销毁当前activity和锁定屏幕的方法.分享给大家供大家参考,具体如下: 首先在Mainifest.xml的Activity元素中加入android:configChanges="orientation|keyboardHidden"属性 <activityandroid:name=".FileBrowser"android:label="@string/app_name"android:

Android编程向服务器发送请求时出现中文乱码问题的解决方法

本文实例讲述了Android编程向服务器发送请求时出现中文乱码问题的解决方法.分享给大家供大家参考,具体如下: 我们在andorid项目中通过get方式向服务器发送请求,其中url参数带有中文,将会产生乱码,乱码产生的原因有两种: 1. 在提交参数时,没有对中文参数进行URL编码 2. Tomcat服务器默认采用的是IOS8859-1编码(不支持中文)得到参数值 解决: 1. 进入android项目,在其中要提交参数的时候,对参数的值进行编码: 复制代码 代码如下: URLEncoder.enc

Android编程实现WebView自适应全屏方法小结

本文实例讲述了Android编程实现WebView自适应全屏的方法.分享给大家供大家参考,具体如下: 第一种: settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); 第二种: WebSetting settings = webView.getSettings(); settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); 把所有内容放在we