OkGo是基于Okhttp3的封装,所以只需要增加自定义拦截器就可以实现自定义log。(OkGo有一个默认的log拦截器HttpLoggingInterceptor,如果没有特别需求则无需自定义)
第一步自定义拦截器(参考OkGo中的拦截器实现,自己决定具体的打印格式及控制方式)
public class MyHttpLogInterceptor implements Interceptor {
private static final Charset UTF8 = Charset.forName("UTF-8");
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if(YDLog.showHttpRequest()) {
StringBuilder builder = new StringBuilder("Request[");
builder.append(request.url())
.append("]\nheader=[\n")
.append(request.headers())
.append("\n]body=[\n")
.append(isPlaintext(request.body().contentType()) ? bodyToString(request) : "body: maybe [file part] , too large too print , ignored!")
.append("\n]");
YDLog.v(builder.toString());
}
if(!YDLog.showHttpResponse())
{
return chain.proceed(request);
}
//执行请求,计算请求时间
long startNs = System.nanoTime();
Response response;
try {
response = chain.proceed(request);
} catch (Exception e) {
YDLog.e("["+request.url()+"]<-- HTTP FAILED: " + e);
throw e;
}
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
return logForResponse(response,tookMs);
}
private Response logForResponse(Response response, long tookMs) {
Response.Builder builder = response.newBuilder();
Response clone = builder.build();
ResponseBody responseBody = clone.body();
boolean logBody = true;
try {
String strBody=null;
boolean bInterceptBody = false;
if (logBody && HttpHeaders.hasBody(clone)) {
if (isPlaintext(responseBody.contentType())) {
bInterceptBody = true;
strBody = responseBody.string();
} else {
strBody="body: maybe [file part] , too large too print , ignored!";
}
}
StringBuilder strBuilder = new StringBuilder("Response[");
strBuilder.append(clone.code()).append("][")
.append(clone.message())
.append("][")
.append(clone.request().url())
.append("][")
.append(tookMs)
.append("ms],header=[")
.append(clone.request().headers())
.append("]\n")
.append(strBody);
YDLog.v(strBuilder.toString());
if(bInterceptBody)
{
responseBody = ResponseBody.create(responseBody.contentType(), strBody);
return response.newBuilder().body(responseBody).build();
}
} catch (Exception e) {
YDLog.e(e.getMessage());
}
return response;
}
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
private static boolean isPlaintext(MediaType mediaType) {
if (mediaType == null) return false;
if (mediaType.type() != null && mediaType.type().equals("text")) {
return true;
}
String subtype = mediaType.subtype();
if (subtype != null) {
subtype = subtype.toLowerCase();
if (subtype.contains("x-www-form-urlencoded") ||
subtype.contains("json") ||
subtype.contains("xml") ||
subtype.contains("html")) //
return true;
}
return false;
}
private String bodyToString(Request request) {
try {
final Request copy = request.newBuilder().build();
final Buffer buffer = new Buffer();
copy.body().writeTo(buffer);
Charset charset = UTF8;
MediaType contentType = copy.body().contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
return buffer.readString(charset);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
第二步在自定义Application的onCreate中初始化OkGo并增加拦截器
OkGo.init(this);//必须调用初始化
if (BuildConfig.LogEnable) {
OkHttpClient.Builder builder = OkGo.getInstance().getOkHttpClientBuilder();
MyHttpLogInterceptor interceptor = new MyHttpLogInterceptor();
builder.addInterceptor(interceptor);
}
这样就完成了自定义log功能