Android OKHttp may you never used the interceptor practical [Recommended]

Foreword

In normal development, so you have no trouble following it?

scene one

Obviously server interface data errors, and QA (test) could be the first to find client development you why this error occurred page?

As you develop a client, you may want to come up with a test machine connected to the computer, beat the Log, look in the end what data is returned, causing a page fault.

Or a little advanced QA, play on their own or Log connection packet capture tool to look at specific data returned from the server, then Bug mention to the corresponding person, and most of the company's business tests are only testing business, regardless of skill level of. Most of our QA, belonging to expatriates, usually only test business, every time there is a problem, we go first client.

Scene II

You are now outside the subway, product leadership, or you suddenly give you feedback, piece of business before you do, do not run up the line suddenly, die. You thought, this is definitely a problem server, ah, but how to prove it?

Scene Three

Server on a line, each client needs with overtime, said there are problems, timely help troubleshoot problems.

Recommend a small tool

Having said that, it is the lack of capture gadgets on one end, to see if the data server in question, today's recommendation is based on OKHttp the capture tool. Section below screenshot

 

 

 

 

Support

  • Comes with Class Interface
  • Data capture time-latitude default storage to the phone cache / Android / Data / package name / Cache / capture / under
  • Support Http / Https protocol capture, classification request info / request URL / Request Header / body Request / Response Status / Response Header / Response Body
  • Supporting a key corresponding to the state of replication
  • If a response body JSON, supports automatic formatting
  • Data capture, the default cache one day

Github Address

Managed code has to Github Address: github.com/DingProg/Ne...

Fast access

 

 

allprojects {
	repositories {
	   maven { url 'https://jitpack.io' }
	}
}

dependencies {
    debugImplementation 'com.github.DingProg.NetworkCaptureSelf:library:v1.0.1' releaseImplementation 'com.github.DingProg.NetworkCaptureSelf:library_no_op:v1.0.1' } 复制代码

Add your Interceptor in the global OkHttp

new OkHttpClient.Builder()
        .addInterceptor(new CaptureInfoInterceptor())
        .build();
复制代码

Detailed knowledge of the principles involved and

As an Android developer, comes Interceptor OKHttp certainly familiar. Interceptor then you know how much? You have used Interceptor those OKHttp it?

Let's look at the very recent drops fire A Dream

DoraemonKit

长下面这个样子

 

 

其中关于网络模块OK Http的监听如下

OkHttpClient client = new OkHttpClient().newBuilder()
                //用于模拟弱网的拦截器
                .addNetworkInterceptor(new DoraemonWeakNetworkInterceptor())
                //网络请求监控的拦截器 ,用于网络流量监听等
                .addInterceptor(new DoraemonInterceptor()).build(); 复制代码

这里举例说一下弱网模拟

弱网模拟

看一下他的实现代码

public class DoraemonWeakNetworkInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { if (!WeakNetworkManager.get().isActive()) { Request request = chain.request(); return chain.proceed(request); } final int type = WeakNetworkManager.get().getType(); switch (type) { case WeakNetworkManager.TYPE_TIMEOUT: //超时 final HttpUrl url = chain.request().url(); throw WeakNetworkManager.get().simulateTimeOut(url.host(), url.port()); case WeakNetworkManager.TYPE_SPEED_LIMIT: //限速 return WeakNetworkManager.get().simulateSpeedLimit(chain); default: //断网 throw WeakNetworkManager.get().simulateOffNetwork(chain.request().url().host()); } } } 复制代码

实现一个OkHttp的Intercepter,根据不同的状态来进行延迟,例如如下的模拟超时

/**
     * 模拟超时
     *
     * @param host
     * @param port
     */
    public SocketTimeoutException simulateTimeOut(String host, int port) { SystemClock.sleep(mTimeOutMillis); return new SocketTimeoutException(String.format("failed to connect to %s (port %d) after %dms", host, port, mTimeOutMillis)); } 复制代码

根据Interceptor 可以干很多事情,那么Interceptor到底是什么样的原理呢?

Interceptor原理

先看一下Interceptor的原型

public interface Interceptor {
  Response intercept(Chain chain) throws IOException; } 复制代码

再看一下OkHttp源码,可以知道,我们的请求最终都会被调用到RealCall中,并执行到如下代码

 @Override protected void execute() { boolean signalledCallback = false; try { Response response = getResponseWithInterceptorChain(); } ... } Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); interceptors.addAll(client.interceptors()); interceptors.add(retryAndFollowUpInterceptor); interceptors.add(new BridgeInterceptor(client.cookieJar())); interceptors.add(new CacheInterceptor(client.internalCache())); interceptors.add(new ConnectInterceptor(client)); if (!forWebSocket) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(forWebSocket)); Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); } 复制代码

在getResponseWithInterceptorChain 添加了很多OkHttp自定义的拦截器,其中有重定向,Cache,连接请求,发起请求到服务端等。我们来看一下最后几行 代码,RealInterceptorChain是一个Interceptor.Chain类型,并执行chain.proceed,接着看一下proceed方法

//RealInterceptorChain
 public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException { ... if (index >= interceptors.size()) throw new AssertionError(); calls++; // Call the next interceptor in the chain. RealInterceptorChain next = new RealInterceptorChain( interceptors, streamAllocation, httpCodec, connection, index + 1, request); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); .... return response; } 复制代码

重点看一下Call the next interceptor in the chain 下面几行代码,他把当前的interceptor.intercept()时,传入的是下一个interceptor的包装类,RealInterceptorChain 这样就实现了,链式递归调用了,直到最后一个response返回,才会依次返回到第一个interceptor。

可以用如下图大致描述

 

 

讲了那么多相关的知识点,我们来回到正题,上述推荐小工具的实现步骤介绍

抓包工具实现主要步骤介绍

添加一个抓包入口

在Manifest中注册即可,如下

  <activity
        android:name="com.ding.library.internal.ui.CaptureInfoActivity"
        android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|locale" android:launchMode="singleInstance" android:screenOrientation="portrait" android:theme="@style/AppTheme.NoActionBar" /> <activity-alias android:label="抓包入口" android:name="CaptureInfoActivity" android:targetActivity="com.ding.library.internal.ui.CaptureInfoActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity-alias> 复制代码

暴露Interceptor

public final class CaptureInfoInterceptor implements Interceptor{ @Override public Response intercept(Chain chain) throws IOException { //获取request 所有信息 ... //获取response 所有信息 ... //存储抓包数据 CacheUtils.getInstance().saveCapture(request.url().toString(),captureEntity); } } 复制代码

这里其中有两种方式,添加到OkHttp的Interceptor,一种硬编码,如下

new OkHttpClient.Builder()
   .addInterceptor(new CaptureInfoInterceptor())
   .build();
复制代码

另一种方式 采用字节码注入的形式,关于字节码注入,可以简单参考我的另一篇Gradle学习笔记,自定义 Transform部分。

存储和读取抓包数据 效率问题

When storing, in order not to affect the efficiency of the main network request of APP, IO operations need to be performed in a separate thread, as used herein, single-threaded pools

public class DiskIOThreadExecutor implements Executor { private final Executor mDiskIO; public DiskIOThreadExecutor() { mDiskIO = Executors.newSingleThreadExecutor(); } @Override public void execute(@NonNull Runnable command) { mDiskIO.execute(command); } } 复制代码

storage

   public void saveCapture(final String url, final CaptureEntity value) { Runnable runnable = new Runnable() { @Override public void run() { String saveUrl = url; if (url.contains("?")) { saveUrl = saveUrl.substring(0, saveUrl.indexOf("?")); } String key = urlMd5(saveUrl); sp.edit().putString(key, saveUrl).apply(); checkOrCreateFilePath(key); File file = new File(captureFilePath + "/" + key + "/" + getCurrentTime() + ".txt"); BufferedSink bufferedSink = null; try { file.createNewFile(); bufferedSink = Okio.buffer(Okio.sink(file)); bufferedSink.writeString(JSON.toJSONString(value), StandardCharsets.UTF_8); bufferedSink.flush(); } catch (Exception e) { e.printStackTrace(); } finally { if (bufferedSink != null) { try { bufferedSink.close(); } catch (IOException e) { e.printStackTrace(); } } } } }; diskIOThreadExecutor.execute(runnable); } 复制代码

Read

When reading data capture, not directly read all of the data, only read the current directory capture, data, when clicked, the corresponding data to load

public List<String> getCapture() {
   File file = new File(captureFilePath); return getFileList(file); } public List<String> getCapture(String key) { File file = new File(captureFilePath + "/" + key); return getFileList(file); } 复制代码

Well, on this gadget, it introduces so much, the details of code, you can directly view the code repository Github, github.com/DingProg/Ne...

to sum up

In fact, on the packet capture tool, there are some mature programs.

  • Computer terminals have Fiddler, Charels, Wireshark, etc., but not particularly convenient.
  • APP can grab bag of other tools, such as NetWorkPacketCapture / capture wizard / AndroidHttpCapture, but have some restrictions, or the code is not open source, advertising and more. Or it is only in the WIFI, or Root and other needs or is not very good custom.

In this paper, it is to introduce OkHttp interceptor, and find you can do many things. If there is an error in the text, but also forgot to correct me, thanks.

Finally, thank your thumbs and Github's Star NetworkCaptureSelf


Author: Big Dipper _And
link: https: //juejin.im/post/5ddddd2a6fb9a07161483fb2
Source: Nuggets
copyright reserved by the authors. Commercial reprint please contact the author authorized, non-commercial reprint please indicate the source.

Guess you like

Origin www.cnblogs.com/yizijianxin/p/12000283.html