提交 eed2ab30 编写于 作者: J jackjintai

Merge branch 'feature/platform' into feature/newfunction_from_platform

......@@ -6,7 +6,8 @@ import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.BaiduLocationMeth
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.FlagMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.OkHttpNullConsMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.OkHttpOneParamConsMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.PlatformHttpMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.PlatformNullConsHttpMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.PlatformOneParamHttpMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.TencentLocationMethodAdapter;
import com.didichuxing.doraemonkit.plugin.bytecode.method.comm.TencentLocationSingleMethodAdapter;
......@@ -129,11 +130,19 @@ public final class DokitCommClassAdapter extends ClassVisitor {
return mv == null ? null : new OkHttpOneParamConsMethodAdapter(mv, access, methodName, desc);
}
//didi平台端 网络 拦截器字节码替换
if (className.equals("didihttp/DidiHttpClient$Builder") && methodName.equals("<init>")) {
//didi平台端 网络 空构造函数
if (className.equals("didihttp/DidiHttpClient$Builder") && methodName.equals("<init>") && getParamsSize(desc) == 0) {
//创建MethodVisitor代理
log(className, access, methodName, desc, signature);
return mv == null ? null : new PlatformNullConsHttpMethodAdapter(access, desc, mv);
}
//didi平台端 网络 一个参数的构造函数
if (className.equals("didihttp/DidiHttpClient$Builder") && methodName.equals("<init>") && getParamsSize(desc) == 1) {
//创建MethodVisitor代理
log(className, access, methodName, desc, signature);
return mv == null ? null : new PlatformHttpMethodAdapter(access, desc, mv);
return mv == null ? null : new PlatformOneParamHttpMethodAdapter(mv, access, methodName, desc);
}
//app启动hook点 onCreate()函数 兼容MultiDex
// if (!StringUtils.isEmpty(superName) && (superName.equals("android/app/Application") || superName.equals("android/support/multidex/MultiDexApplication")) && methodName.equals("onCreate") && desc.equals("()V")) {
......
......@@ -10,10 +10,10 @@ import org.objectweb.asm.commons.LocalVariablesSorter;
* Only weave okhttp3/OkHttpClient's init method
* Created by Quinn on 09/09/2018.
*/
public final class PlatformHttpMethodAdapter extends LocalVariablesSorter implements Opcodes {
public final class PlatformNullConsHttpMethodAdapter extends LocalVariablesSorter implements Opcodes {
public PlatformHttpMethodAdapter(int access, String desc, MethodVisitor mv) {
public PlatformNullConsHttpMethodAdapter(int access, String desc, MethodVisitor mv) {
super(Opcodes.ASM7, access, desc, mv);
}
......@@ -27,6 +27,14 @@ public final class PlatformHttpMethodAdapter extends LocalVariablesSorter implem
mv.visitFieldInsn(GETSTATIC, "com/didichuxing/foundation/net/rpc/http/PlatformHttpHook", "globalInterceptors", "Ljava/util/List;");
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "addAll", "(Ljava/util/Collection;)Z", true);
mv.visitInsn(POP);
//插入NetworkInterceptor 网络拦截器
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "didihttp/DidiHttpClient$Builder", "networkInterceptors", "Ljava/util/List;");
mv.visitFieldInsn(GETSTATIC, "com/didichuxing/foundation/net/rpc/http/PlatformHttpHook", "globalNetworkInterceptors", "Ljava/util/List;");
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "addAll", "(Ljava/util/Collection;)Z", true);
mv.visitInsn(POP);
}
super.visitInsn(opcode);
}
......
package com.didichuxing.doraemonkit.plugin.bytecode.method.comm;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.AdviceAdapter;
import org.objectweb.asm.commons.LocalVariablesSorter;
/**
* Only weave didihttp/DidiHttpClient's init method
* Created by Quinn on 09/09/2018.
*/
public final class PlatformOneParamHttpMethodAdapter extends AdviceAdapter {
public PlatformOneParamHttpMethodAdapter(MethodVisitor methodVisitor, int access, String methodName, String descriptor) {
super(Opcodes.ASM7, methodVisitor, access, methodName, descriptor);
}
@Override
protected void onMethodExit(int opcode) {
super.onMethodExit(opcode);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKESTATIC, "com/didichuxing/foundation/net/rpc/http/PlatformHttpHook", "performDidiHttpOneParamBuilderInit", "(Ljava/lang/Object;Ljava/lang/Object;)V", false);
}
}
......@@ -55,8 +55,8 @@ public class RpcMockInterceptor implements RpcInterceptor<HttpRpcRequest, HttpRp
String queries = url.query();
String jsonQuery = transformQuery(queries);
String jsonRequestBody = transformRequestBody(oldRequest.getEntity());
LogHelper.i(TAG, "realJsonQuery===>" + jsonQuery);
LogHelper.i(TAG, "realJsonRequestBody===>" + jsonRequestBody);
//LogHelper.i(TAG, "realJsonQuery===>" + jsonQuery);
//LogHelper.i(TAG, "realJsonRequestBody===>" + jsonRequestBody);
String interceptMatchedId = DokitDbManager.getInstance().isMockMatched(path, jsonQuery, jsonRequestBody, DokitDbManager.MOCK_API_INTERCEPT, DokitDbManager.FROM_SDK_DIDI);
String templateMatchedId = DokitDbManager.getInstance().isMockMatched(path, jsonQuery, jsonRequestBody, DokitDbManager.MOCK_API_TEMPLATE, DokitDbManager.FROM_SDK_DIDI);
......
package com.didichuxing.doraemonkit.kit.network.rpc;
import android.os.SystemClock;
import com.didichuxing.doraemonkit.kit.weaknetwork.RpcSpeedLimitRequestBody;
import com.didichuxing.doraemonkit.kit.weaknetwork.RpcSpeedLimitResponseBody;
import com.didichuxing.doraemonkit.kit.weaknetwork.WeakNetworkManager;
import java.io.IOException;
import didihttp.HttpUrl;
import didihttp.Interceptor;
import didihttp.Request;
import didihttp.RequestBody;
import didihttp.Response;
import didihttp.ResponseBody;
/**
* 用于模拟弱网的拦截器
* <p>
* Created by xiandanin on 2019-05-09 16:29
*
* @author didi
*/
public class RpcWeakNetworkInterceptor implements Interceptor {
private static final String TAG = "DoraemonWeakNetworkInterceptor";
@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();
final HttpUrl url = chain.request().url();
switch (type) {
case WeakNetworkManager.TYPE_TIMEOUT:
//超时
return simulateTimeOut(chain);
case WeakNetworkManager.TYPE_SPEED_LIMIT:
//限速
return simulateSpeedLimit(chain);
default:
//断网
return simulateOffNetwork(chain);
}
}
/**
* 模拟断网
*/
public Response simulateOffNetwork(Interceptor.Chain chain) throws IOException {
final Response response = chain.proceed(chain.request());
ResponseBody responseBody = ResponseBody.create(response.body().contentType(), "");
Response newResponse = response.newBuilder()
.code(400)
.message(String.format("Unable to resolve host %s: No address associated with hostname", chain.request().url().host()))
.body(responseBody)
.build();
return newResponse;
}
/**
* 模拟超时
*
* @param chain url
*/
public Response simulateTimeOut(Interceptor.Chain chain) throws IOException {
SystemClock.sleep(WeakNetworkManager.get().getTimeOutMillis());
final Response response = chain.proceed(chain.request());
ResponseBody responseBody = ResponseBody.create(response.body().contentType(), "");
Response newResponse = response.newBuilder()
.code(400)
.message(String.format("failed to connect to %s after %dms", chain.request().url().host(), WeakNetworkManager.get().getTimeOutMillis()))
.body(responseBody)
.build();
return newResponse;
}
/**
* 限速
*/
public Response simulateSpeedLimit(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
final RequestBody body = request.body();
if (body != null) {
//大于0使用限速的body 否则使用原始body
final RequestBody requestBody = WeakNetworkManager.get().getRequestSpeed() > 0 ? new RpcSpeedLimitRequestBody(WeakNetworkManager.get().getRequestSpeed(), body) : body;
request = request.newBuilder().method(request.method(), requestBody).build();
}
final Response response = chain.proceed(request);
//大于0使用限速的body 否则使用原始body
final ResponseBody responseBody = response.body();
final ResponseBody newResponseBody = WeakNetworkManager.get().getResponseSpeed() > 0 ? new RpcSpeedLimitResponseBody(WeakNetworkManager.get().getResponseSpeed(), responseBody) : responseBody;
return response.newBuilder().body(newResponseBody).build();
}
}
package com.didichuxing.doraemonkit.kit.weaknetwork;
import android.os.SystemClock;
import java.io.IOException;
import didihttp.MediaType;
import didihttp.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Sink;
/**
* Created by xiandanin on 2019-05-09 18:35
*/
public class RpcSpeedLimitRequestBody extends RequestBody {
private long mSpeedByte;//b/s
private RequestBody mRequestBody;
private BufferedSink mBufferedSink;
public RpcSpeedLimitRequestBody(long speed, RequestBody source) {
this.mRequestBody = source;
this.mSpeedByte = speed * 1024;//转成字节
}
@Override
public MediaType contentType() {
return mRequestBody.contentType();
}
@Override
public long contentLength() throws IOException {
return mRequestBody.contentLength();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
if (mBufferedSink == null) {
//mBufferedSink = Okio.buffer(sink(sink));
//默认8K 精确到1K
mBufferedSink = new ByteCountBufferedSink(sink(sink), 1024L);
}
mRequestBody.writeTo(mBufferedSink);
mBufferedSink.close();
}
private Sink sink(final BufferedSink sink) {
return new ForwardingSink(sink) {
private long cacheTotalBytesWritten;
private long cacheStartTime;
@Override
public void write(Buffer source, long byteCount) throws IOException {
if (cacheStartTime == 0) {
cacheStartTime = SystemClock.uptimeMillis();
}
super.write(source, byteCount);
cacheTotalBytesWritten += byteCount;
long endTime = SystemClock.uptimeMillis() - cacheStartTime;
//如果在一秒内
if (endTime <= 1000L) {
//大小就超出了限制
if (cacheTotalBytesWritten >= mSpeedByte) {
long sleep = 1000L - endTime;
SystemClock.sleep(sleep);
//重置计算
cacheStartTime = 0L;
cacheTotalBytesWritten = 0L;
}
}
}
};
}
}
package com.didichuxing.doraemonkit.kit.weaknetwork;
import android.os.SystemClock;
import java.io.IOException;
import didihttp.MediaType;
import didihttp.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
/**
* Created by xiandanin on 2019-05-09 18:35
*/
public class RpcSpeedLimitResponseBody extends ResponseBody {
private static String TAG = "SpeedLimitResponseBody";
/**
* 限速字节
*/
private long mSpeedByte;
private ResponseBody mResponseBody;
private BufferedSource mBufferedSource;
public RpcSpeedLimitResponseBody(long speed, ResponseBody source) {
this.mResponseBody = source;
//转成字节
this.mSpeedByte = speed * 1024L;
}
@Override
public MediaType contentType() {
return mResponseBody.contentType();
}
@Override
public long contentLength() {
return mResponseBody.contentLength();
}
@Override
public BufferedSource source() {
if (mBufferedSource == null) {
mBufferedSource = Okio.buffer(source(mResponseBody.source()));
}
return mBufferedSource;
}
private Source source(Source source) {
return new ForwardingSource(source) {
/**
* 如果小于1s 会重置
*/
private long cacheTotalBytesRead;
/**
* 分片读取1024个字节开始时间 小于1s会重置
*/
private long cacheStartTime;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
if (cacheStartTime == 0) {
cacheStartTime = SystemClock.uptimeMillis();
}
//默认8K 精确到1K -1代表已经读取完毕
long bytesRead = super.read(sink.buffer(), 1024L);
if (bytesRead == -1) {
return bytesRead;
}
//一般为1024
cacheTotalBytesRead = cacheTotalBytesRead + bytesRead;
/**
* 判断当前请求累计消耗的时间 即相当于读取1024个字节所需要的时间
*/
long costTime = SystemClock.uptimeMillis() - cacheStartTime;
//如果每次分片读取时间小于ls sleep 延迟时间
if (costTime <= 1000L) {
if (cacheTotalBytesRead >= mSpeedByte) {
long sleep = 1000L - costTime;
SystemClock.sleep(sleep);
//重置计算
cacheStartTime = 0L;
cacheTotalBytesRead = 0L;
}
}
return bytesRead;
}
};
}
}
package com.didichuxing.foundation.net.rpc.http;
import android.util.Log;
import com.blankj.utilcode.util.ReflectUtils;
import com.didichuxing.doraemonkit.kit.network.rpc.RpcMockInterceptor;
import com.didichuxing.doraemonkit.kit.network.rpc.RpcMonitorInterceptor;
import com.didichuxing.doraemonkit.kit.network.rpc.RpcWeakNetworkInterceptor;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import didihttp.DidiHttpClient;
import didihttp.Interceptor;
......@@ -20,6 +26,7 @@ import didihttp.Interceptor;
*/
public class PlatformHttpHook {
public static List<Interceptor> globalInterceptors = new ArrayList<>();
public static List<Interceptor> globalNetworkInterceptors = new ArrayList<>();
private static boolean IS_INSTALL = false;
public static void installInterceptor() {
......@@ -28,13 +35,50 @@ public class PlatformHttpHook {
}
try {
//可能存在用户没有引入滴滴内部网络库的情况
OkHttpRpc.OkHttpRpcInterceptor rpcMockInterceptor = new OkHttpRpc.OkHttpRpcInterceptor((new RpcMockInterceptor()));
OkHttpRpc.OkHttpRpcInterceptor rpcMonitorInterceptor = new OkHttpRpc.OkHttpRpcInterceptor((new RpcMonitorInterceptor()));
OkHttpRpc.OkHttpRpcInterceptor rpcMockInterceptor = new OkHttpRpc.OkHttpRpcInterceptor(new RpcMockInterceptor());
OkHttpRpc.OkHttpRpcInterceptor rpcMonitorInterceptor = new OkHttpRpc.OkHttpRpcInterceptor(new RpcMonitorInterceptor());
globalInterceptors.add(rpcMockInterceptor);
globalInterceptors.add(rpcMonitorInterceptor);
Interceptor weakNetworkInterceptor = new RpcWeakNetworkInterceptor();
globalNetworkInterceptors.add(weakNetworkInterceptor);
IS_INSTALL = true;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param builder 真实的对象为DidiHttpClient.Builder
* @param didiHttpClient 真实的对象为DidiHttpClient
*/
public static void performDidiHttpOneParamBuilderInit(Object builder, Object didiHttpClient) {
try {
if (builder instanceof DidiHttpClient.Builder) {
DidiHttpClient.Builder localBuild = (DidiHttpClient.Builder) builder;
List<Interceptor> interceptors = removeDuplicate(localBuild.interceptors());
List<Interceptor> networkInterceptors = removeDuplicate(localBuild.networkInterceptors());
ReflectUtils.reflect(localBuild).field("interceptors", interceptors);
ReflectUtils.reflect(localBuild).field("networkInterceptors", networkInterceptors);
//Log.i("Doraemon", "====performDidiHttpOneParamBuilderInit===");
}
} catch (Exception e) {
Log.i("Doraemon", "" + e.getMessage());
}
}
/**
* 保证顺序并去重
*
* @param list
* @return
*/
private static List<Interceptor> removeDuplicate(List<Interceptor> list) {
//保证顺序并去重
LinkedHashSet h = new LinkedHashSet<Interceptor>(list);
list.clear();
list.addAll(h);
return list;
}
}
......@@ -9,7 +9,6 @@ import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.LargePictureIn
import com.didichuxing.doraemonkit.kit.network.okhttp.interceptor.MockInterceptor;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
......
package com.didichuxing.doraemonkit.config;
/**
* ================================================
* 作 者:jint(金台)
* 版 本:1.0
* 创建日期:2020/4/26-14:35
* 描 述:Dokit 功能开关配置
* 修订历史:
* ================================================
*/
public class DokitSwitchConfig {
private boolean alignRule;
private boolean largeImg;
private boolean log;
private boolean gps;
private boolean appHealth;
private boolean crash;
}
......@@ -2,7 +2,7 @@ package com.didichuxing.doraemonkit.config;
/**
* Created by jintai on 2019/10/10.
* 将配置信息保存在内存中
* 将配置信息保存在内存中 不需要持久化保存
*/
public class PerformanceMemoryInfoConfig {
......
package com.didichuxing.doraemonkit.config;
import android.content.Context;
import com.didichuxing.doraemonkit.constant.SharedPrefsKey;
import com.didichuxing.doraemonkit.util.SharedPrefsUtil;
......
......@@ -30,7 +30,6 @@ public class DoraemonWeakNetworkInterceptor implements Interceptor {
return chain.proceed(request);
}
final int type = WeakNetworkManager.get().getType();
final HttpUrl url = chain.request().url();
switch (type) {
case WeakNetworkManager.TYPE_TIMEOUT:
//超时
......
......@@ -77,7 +77,7 @@ public class DokitOkGo {
loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
loggingInterceptor.setColorLevel(Level.INFO);
builder.addInterceptor(loggingInterceptor);
builder.retryOnConnectionFailure(true);
//builder.retryOnConnectionFailure(true);
builder.readTimeout(DokitOkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
builder.writeTimeout(DokitOkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
builder.connectTimeout(DokitOkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册