监控自己APP的http/https网络请求的地址和请求耗时

关于监控http/https网络请求的思路, 目前想到两种实现思路:
第一种实现思路是hook http请求的根接口, 目前大致是分为HttpURLConnection和Apache-Http-Client这两种, 当然也有可能使用square/okhttp或者koush/AndroidAsync, 但本质上是一样的, 不过因为使用的接口的不同, 有两个方案:
  • 一个方案是URLStreamHandlerFactory, 当使用(HttpURLConnection)URL.openConnection()时, 里面是去请求URLStreamHandlerFactory获得一个URLStreamHandler, 并由URLStreamHandler提供URLConnection子类(这里是HttpURLConnection或HttpsURLConnection), 所以控制住URLStreamHandlerFactory即可使用代理模式来监控, 可喜的是URL有个静态方法setURLStreamHandlerFactory来让末端程序员注入这种控制, 这里可参考’com.squareup.okhttp3:okhttp-urlconnection:3.3.1’ 或https://github.com/square/okhttp/tree/master/okhttp-urlconnection/src/main/java/okhttp3里的OkUrlFactory.java;

  • 另一个方案比较彻底, 是通过以下三个静态方法设置默认的tcp/udp socket实现类SocketImpl和DatagramSocketImpl:
    java.net.Socket.setSocketImplFactory(SocketImplFactory);
    java.net.ServerSocket.setSocketFactory(SocketImplFactory);
    java.net.DatagramSocket.setDatagramSocketImplFactory(DatagramSocketImplFactory); //不常用
    其中, 无网络代理(比如SOCKS或http代理)的情况下SocketImpl和DatagramSocketImpl可参考java.net.PlainSocketImpl和java.net.PlainDatagramSocketImpl, 通过反射和委托实现监控;
    注意: 不是javax.net.ServerSocketFactory, javax.net.SocketFactory, javax.net.ssl.SSLServerSocketFactory, javax.net.ssl.SSLSocketFactory;
    问题: 不过也很遗憾, 这种方式基本对https(SSL方式)无效, 不过也能理解, 按理说ssl方式的请求不应该被hook拦截. 不过还是讨论一下, 仅就javax.net.ssl.SSLSocketFactory调研发现, Android中, 它是com.android.org.conscrypt.OpenSSLSocketFactoryImpl类型, 其创建的SSLSocket, 是com.android.org.conscrypt.OpenSSLSocketImpl; 而在java中, 它是sun.security.ssl.SSLSocketFactoryImpl类型, 其创建的SSLSocket, 是sun.security.ssl.SSLSocketImpl; 而且虽然这两个SSLSocket子类间接继承自Socket, 但是它们可能没有使用SocketImpl, 所以setSocketImplFactory对其无作用, 由SSLSocket的一般使用方式: SSLSocketFactory.getDefault().createSocket()而知, 可能的方法是反射SSLSocketFactory, 既然是getDefault(), 肯定里面有个私有静态属性保存这个默认的SSLSocketFactory实例, 那么将这个私有静态属性赋值你的SSLSocketFactory的实现并实现SSLSocket, 我想应该就可以了, 但是工作量比较大;

第二种实现思路是aop/动态代理, 这种实现思路有非常高的参考价值, 它可以用于其他监控, 但是目前看它又是很难实践的, 具体分静态和动态两个方案:
  • 一个方案是静态织入字节码或dex文件,可以使用aspectj或者其他处理字节码的工具, 或者使用dex2jar/smali的类库操作dex文件, 目的是在所有网络请求的调用前后座aop切面;
    理论上可行, 因为我们织入的切点在method call而非method execute, 但是使用网络库的方式多种多样, 有的是multi-part/form-data, 有的是没返回值, 如果想统计一次网络耗时的话, 很难找到合适的开始点和结束点, 比如HttpURLConnection的connect方法调用前切入, 但是用户可能会调用getOutputStream/getInputStream, 可能close这些stream, 也可能调用disconnect, 也可能不调用, 找不到合适的结束切入点, 而且如何做到匹配开始和结束切入点呢? 因为开始和结束的method显然不同, 你也许会说分装一个http网络辅助类, 但是对于你依赖的类库显然不会遵守这个规矩;

  • 另一个方案是运行时动态生成代理类或者干脆利用DexClassLoader的DexPathList实现替换http实现类, 比如动态代理出HttpURLConnection的子类并替换掉ClassLoader中现存的HttpURLConnection实现类;
    可以使用的工具有java自带的Proxy和InvocationHandler, 也可以使用ow2/asmdex或crimsonwoods/javassist-android工具;
    实践发现, 由于HttpURLConnection这样的基础类是由BootClassLoader加载的, 目前很难能做到替换, 这不像你的自定义类那样实现热修复替换, 或许以后在这方面会有更好的思路, 我一直在关注alibaba/AndFix, 它在这方面的实现方式是少有限制的, 不知道兼容性上有无风险;

监控自己app的网络请求的需求还是现实的, 如果只是自己的代码, 那么封装一个类库, 比如基于okhttp即可, 但是有很多依赖类库/三方SDK会在内部做网络请求, 你不希望这些外部因素没用好网络的责任推在你的身上吧, 不过理想很美好, 但这不是坦途~
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安卓提供了一些可以用于监听app网络请求的方法。其中一种方法是使用OkHttp拦截器,可以在网络请求的过程中拦截并处理请求及响应。 首先,我们需要在项目中导入OkHttp库。然后,我们可以创建一个拦截器,在拦截器中重写intercept方法,对请求进行处理。 具体步骤如下: 1. 创建一个类,实现OkHttp的Interceptor接口。 ``` public class NetworkInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 在这里可以获取到请求的信息,如URL请求方法等 Request request = chain.request(); // 在发送请求之前可以对请求进行修改 // ... // 执行请求 Response response = chain.proceed(request); // 在这里可以获取到响应的信息,如状态码等 // ... // 对响应进行处理 // ... // 返回处理后的响应 return response; } } ``` 2. 创建OkHttpClient时,将拦截器添加到拦截器列表中。 ``` OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new NetworkInterceptor()) .build(); ``` 3. 此时,当app发送网络请求时,拦截器的intercept方法会被调用,我们可以在这个方法中获取并处理请求和响应的信息。 以上就是一种使用OkHttp拦截器监听app网络请求的方法。当然,还有其他一些方式可以实现类似的功能,如使用HttpURLConnection或使用第三方库等。选择合适的方法取决于具体的需求和项目要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值