package ren.solid.library.http;
import android.text.TextUtils;
import com.trello.rxlifecycle2.internal.Preconditions;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import ren.solid.library.SolidApplication;
import ren.solid.library.utils.NetworkUtil;
import ren.solid.library.utils.SLog;
/**
* Created by _SOLID
* Date:2016/12/3
* Time:13:44
*/
public class OkHttpProvider {
private final static long DEFAULT_CONNECT_TIMEOUT = 5;
private final static long DEFAULT_WRITE_TIMEOUT = 20;
private final static long DEFAULT_READ_TIMEOUT = 10;
public static OkHttpClient getDefaultOkHttpClient() {
return getOkHttpClient(new CacheControlInterceptor());
}
public static OkHttpClient getOkHttpClient() {
return getOkHttpClient(new FromNetWorkControlInterceptor());
}
private static OkHttpClient getOkHttpClient(Interceptor cacheControl) {
//定制OkHttp
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
//设置超时时间
httpClientBuilder.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS);
httpClientBuilder.writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS);
httpClientBuilder.readTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS);
//设置缓存
File httpCacheDirectory = new File(SolidApplication.getInstance().getCacheDir(), "OkHttpCache");
httpClientBuilder.cache(new Cache(httpCacheDirectory, 100 * 1024 * 1024));
//设置拦截器
httpClientBuilder.addInterceptor(new UserAgentInterceptor("Android Device"));
httpClientBuilder.addInterceptor(new LoggingInterceptor());
httpClientBuilder.addInterceptor(cacheControl);
httpClientBuilder.addNetworkInterceptor(cacheControl);
return httpClientBuilder.build();
}
/**
* 没有网络的情况下就从缓存中取
* 有网络的情况则从网络获取
*/
private static class CacheControlInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!NetworkUtil.isConnected(SolidApplication.getInstance())) {
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
if (NetworkUtil.isConnected(SolidApplication.getInstance())) {
int maxAge = 60;//在有网络连接的情况下,一分钟内不再请求网络
String cacheControl = request.cacheControl().toString();
if (TextUtils.isEmpty(cacheControl)) {
cacheControl = "public, max-age=" + maxAge;
}
response = response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", cacheControl)
.build();
} else {
int maxStale = 60 * 60 * 24 * 30;
response = response.newBuilder()
.removeHeader("Pragma")
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
return response;
}
}
/**
* 强制从网络获取数据
*/
private static class FromNetWorkControlInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
Response response = chain.proceed(request);
return response;
}
}
private static class UserAgentInterceptor implements Interceptor {
private static final String USER_AGENT_HEADER_NAME = "User-Agent";
private final String userAgentHeaderValue;
UserAgentInterceptor(String userAgentHeaderValue) {
this.userAgentHeaderValue = Preconditions.checkNotNull(userAgentHeaderValue, "userAgentHeaderValue = null");
}
@Override
public Response intercept(Chain chain) throws IOException {
final Request originalRequest = chain.request();
final Request requestWithUserAgent = originalRequest.newBuilder()
.removeHeader(USER_AGENT_HEADER_NAME)
.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
.build();
return chain.proceed(requestWithUserAgent);
}
}
private static class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
SLog.i(this, String.format(Locale.CHINA, "Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
SLog.i(this, String.format(Locale.CHINA, "Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}
}