序文
通常の開発では、あなたがそれ以下の支障がありませんか?
シーンワン
もちろん、サーバ・インタフェースのデータエラー、およびQA(テスト)は、このエラーがページを発生した理由最初はクライアント開発あなたを見つけることだろうか?
あなたがクライアントの開発として、あなたがコンピュータに接続された試験機を思い付くしたい場合、ページフォールトを引き起こして、返されたどのデータ末尾でログインし、外観を破りました。
それとも少し高度なQA、対応する人物に、サーバから返された特定のデータを見て、自分のか、ログ接続パケットキャプチャツールに遊び、バグ言及、および同社のビジネス・テストのみにかかわらず、スキルレベルの、ビジネスをテストしているほとんどのA。駐在員、通常は検査事業に属する、私たちのQAのほとんどは、問題があるたびに、我々は最初のクライアントを行きます。
シーンII
あなたは今外の地下鉄、製品のリーダーシップ、またはあなたが、突然ラインを実行しないでください前に、あなたは突然、あなたのフィードバック、業務の一部を与え、ダイです。あなたは、ああ、これは間違いなく問題のサーバーである、と思ったが、それを証明するためにどのように?
シーンスリー
ライン上のサーバーは、残業で各クライアントのニーズは、問題、タイムリーなヘルプのトラブルシューティングの問題があると述べました。
小さなツールをお勧めします
それを言って、それが今日の勧告がOKHttpキャプチャツールに基づいており、問題のデータ・サーバかどうかを確認するために、一方の端にキャプチャガジェットの欠如です。スクリーンショット以下のセクション
サポート
- クラスのインターフェイスが付属しています
- 携帯電話のキャッシュ/アンドロイド/データ/パッケージ名/キャッシュ/キャプチャ/下へのデータ取り込み時間 - 緯度デフォルトのストレージ
- サポートHTTP / HTTPSプロトコル・キャプチャー、分類要求情報/要求URL /リクエストヘッダ/ボディ要求/応答ステータス/レスポンスヘッダー/レスポンスボディ
- レプリケーションの状態に対応するキーをサポート
- レスポンスボディJSONは、自動書式をサポートしている場合
- データキャプチャ、デフォルトのキャッシュ1日
Githubの住所
マネージドコードはGitHubの住所にありますgithub.com/DingProg/Ne ...
高速アクセス
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' } 复制代码
グローバルOkHttpであなたのインターセプタを追加
new OkHttpClient.Builder()
.addInterceptor(new CaptureInfoInterceptor())
.build();
复制代码
関与の原則の詳細な知識と
Androidの開発者として、確かに馴染みのインターセプタOKHttpが来ます。インターセプターあなたはどのくらい知っていますか?あなたはそれらのOKHttpそれインターセプタを使用していますか?
ごく最近の滴の火A夢で見てみましょう
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部分。
存储和读取抓包数据 效率问题
格納する際に、APPの主要ネットワーク要求の効率に影響を及ぼさないようにするために、IOオペレーションは本明細書において使用される、シングルスレッドプールとして、別のスレッドで実行する必要が
public class DiskIOThreadExecutor implements Executor { private final Executor mDiskIO; public DiskIOThreadExecutor() { mDiskIO = Executors.newSingleThreadExecutor(); } @Override public void execute(@NonNull Runnable command) { mDiskIO.execute(command); } } 复制代码
メモリ
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); } 复制代码
読みます
データ・キャプチャーを読み出す場合、負荷に直接データのすべてを読んで、クリックされたときにのみ、カレントディレクトリの取得、データの読み取り、対応するデータではありません
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); } 复制代码
さて、このガジェットに、それはそんなに紹介し、コードの詳細は、次のコードリポジトリGithubに、直接見ることができますgithub.com/DingProg/Neを...
概要
実際には、パケットキャプチャツールで、いくつかの成熟したプログラムがあります。
- コンピュータ端末等フィドラー、Charels、Wiresharkのを、持っているが、特に便利ではありません。
- APPは、このようなNetWorkPacketCapture /キャプチャウィザード/ AndroidHttpCaptureなどの他のツールのバッグをつかむが、いくつかの制限がある、またはコードは、オープンソース、広告、より多くのではないことができます。それともそれだけでWIFI、またはルートおよびその他のニーズにあるか、非常に良い習慣ではありません。
本論文では、OkHttpインターセプタを紹介し、あなたは多くのことを行うことができます見つけることです。そこにテキスト内のエラーですが、場合にも、感謝を私を修正するのを忘れました。
最後に、親指とのGithubのスター感謝NetworkCaptureSelf
著者:北斗七星_Andの
リンクします。https://juejin.im/post/5ddddd2a6fb9a07161483fb2
出典:ナゲッツの
著作権は著者が保有。著者は認可商業転載してください接触、非商用の転載は、ソースを明記してください。