*
*
* 1 支持没网缓存,和保质期(多少秒之内不请求后台,而是读缓存)
*
* 2 支持强制读取缓存
*
* 3 支持删除整个缓存和某个接口缓存
*
* 4 支持大文件下载
*
* 5 支持单个接口配置缓存,保质期,连接时间
*
* 6 支持Gzip压缩,解决了Gzip缓存乱码bug
*
* 1 支持没网缓存,和保质期(多少秒之内不请求后台,而是读缓存)
*
* 2 支持强制读取缓存
*
* 3 支持删除整个缓存和某个接口缓存
*
* 4 支持大文件下载
*
* 5 支持单个接口配置缓存,保质期,连接时间
*
* 6 支持Gzip压缩,解决了Gzip缓存乱码bug
* 7 支持分批读取json数组,不会oom
* 8 支持文件上传,和下载
需要 okhttp-3.4.1 jar包及以上
最新okhttp jar包链接:http://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp/3.6.0
最新 ok.io jar包链接:http://mvnrepository.com/artifact/com.squareup.okio/okio/1.11.0
使用方法:
// 测试缓存
public static void testCache(ObserverCallBack back) {
String url = "http://118.25.43.50:8089/sv/operation/operation/main.do";
HashMap<String, Object> config = new HashMap<String, Object>();
config.put(HttpConfig.MAX_AGE, 60 * 5);// 5分钟之内不走网络走缓存
config.put(HttpConfig.MAX_STALE, 60 * 60 * 24 * 2);// 没网时数据缓存两天
// config.put(HttpConfig.CONNECT_TIME, 30);//超时时间30秒
OkHttpUtil.get(url, back, -1, null, config);
}
// 测试读取缓存
public static void readCache() {
String url = "http://118.25.43.50:8089/sv/operation/operation/main.do";
// 为null说明没数据
String response = OkHttpUtil.getCacheResponse(url);
System.out.println("读取本地缓存:" + response);
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;
import okhttp3.Cache;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.FormBody.Builder;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.Util;
import okio.BufferedSink;
import okio.GzipSink;
import okio.Okio;
/**
* okhttp访问封装
* <p>
* 1 支持没网缓存,和保质期
* <p>
* 2 支持强制读取缓存
* <p>
* 3 支持删除整个缓存和当个接口缓存
* <p>
* 4 支持大文件下载
* <p>
* 5 支持单个接口配置缓存,保质期,连接时间
* <p>
* 6 支持gzip压缩
* <p>
* 7 支持分批读取json数组,不会oom
*
* @version 2017年2月21日
*
*/
public class OkHttpUtil {
// 官方格式,文件为内容
private static final String FILE_FLAG_CONTENT = ".1";
// 官方格式,文件为响应头
private static final String FILE_FLAG_HTTPHEAD = ".0";
// 文件缓存的名字
private static final String CACHE_NAME = "http_cache";
private static final OkHttpClient mOkHttpClient;
private static final okhttp3.OkHttpClient.Builder clientBuilder;
private static final Context context = GlobalApplication.mContext;
// 文件缓存
private static final Cache cache;
static {
clientBuilder = new OkHttpClient.Builder();
clientBuilder.connectTimeout(14, TimeUnit.SECONDS);// 设置连接超时12秒
clientBuilder.writeTimeout(30, TimeUnit.SECONDS);
clientBuilder.readTimeout(30, TimeUnit.SECONDS);
int cachesize = 10 * 1024 * 100;
File dir = context.getDir(CACHE_NAME, Context.MODE_PRIVATE);
cache = new Cache(dir, cachesize);
clientBuilder.cache(cache);
clientBuilder.interceptors().add(new CacheApplicationInterceptor());
// clientBuilder.addNetworkInterceptor(new GzipRequestInterceptor());
mOkHttpClient = clientBuilder.build();
}
public static String get(String url, Map<String, String> parmter, HashMap<String, Object> config)
throws IOException {
String content = "";
Set<String> keySet = parmter.keySet();
int i = 0;
String start = null;
if (url.contains("?"))
start = "&";
else
start = "?";
for (String key : keySet) {
if (i == 0)
content = content + key + "=" + parmter.get(key);
else
content = content + "&" + key + "=" + parmter.get(key);
i++;
}
url = url + start + content;
return get(url, config);
}
public static String get(String url, HashMap<String, Object> config) throws IOException {
okhttp3.Request.Builder build = creatBuilder();
Request request = build.url(url).build();
build.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
Response response = execute(copyClient, request);
if (response.isSuccessful())
return response.body().string();
return null;
}
// 分批加载json数据
public static void getBigJsonData(String url, ObserverBigCallBack back, int method, Object obj) {
BigJsonThread bigJsonThread = new BigJsonThread(url, back, method, obj);
new Thread(bigJsonThread).start();
}
// 堵塞的post请求
private static String postString(String url, Map<String, Object> body, HashMap<String, Object> config) {
Builder type = new FormBody.Builder();
Set<String> keySet = body.keySet();
for (String key : keySet)
type.add(key, (String) body.get(key));
RequestBody requestBody = type.build();
okhttp3.Request.Builder builder = creatBuilder();
builder.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
// "Connection", "close"这个解决报错 不让他长连接
Request request = builder.url(url).post(requestBody).addHeader("Connection", "close").build();
Response execute;
try {
execute = execute(copyClient, request);
keySet = null;
if (execute.isSuccessful())
return execute.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static String post(String url, Map<String, Object> body, HashMap<String, Object> config) {
Set<String> keySet = body.keySet();
boolean isHasFile = false;
for (String value : keySet) {
Object object = body.get(value);
if (object instanceof File) {
isHasFile = true;
break;
}
}
if (!isHasFile)
return postString(url, body, config);
okhttp3.Request.Builder build = creatBuilder();
build.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
// 构造上传请求,类似web表单
okhttp3.MultipartBody.Builder type = new MultipartBody.Builder();
RequestBody fileBody = null;
keySet = body.keySet();
for (String key : keySet) {
Object object = body.get(key);
if (object == null)
continue;
if (object instanceof String) {
type.addFormDataPart(key, (String) object);
Headers of = Headers.of("Content-Disposition", "form-data; name=\"" + key + "\"");
type.addPart(of, RequestBody.create(null, (String) object));
} else if (object instanceof File) {
File file = (File) object;
fileBody = RequestBody.create(MediaType.parse(guessMimeType(file.getName())), file);
String format = "form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\"\r\n";
Headers of = Headers.of("Content-Disposition", format);
type.addPart(of, fileBody);
}
}
RequestBody requestBody = type.build();
Request request = build.url(url).post(requestBody).build();
try {
Response execute = execute(copyClient, request);
boolean successful = execute.isSuccessful();
if (successful)
return execute.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void download(String url, File file, ObserverCallBack back, int method, Object obj,
HashMap<String, Object> config) {
okhttp3.Request.Builder build = creatBuilder();
build.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
Request request = build.url(url).build();
FileOkCallBack fileOkCallBack = new FileOkCallBack(file, back, method, obj);
enqueue(copyClient, request, fileOkCallBack);
}
// 结束所有网络请求
public static void cancelAll() {
mOkHttpClient.dispatcher().cancelAll();
}
public static void get(String url, ObserverCallBack back, int method, Object obj, HashMap<String, Object> config) {
OkCallBack okCallBack = new OkCallBack(back, method, obj);
Request.Builder build = creatBuilder();
build.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
Request request = build.url(url).build();
enqueue(copyClient, request, okCallBack);
}
public static void postFile(String url, File file, ObserverCallBack back, int method, Object obj,
HashMap<String, Object> config) {
RequestBody create = RequestBody.create(MediaType.parse(guessMimeType(file.getName())), file);
okhttp3.Request.Builder build = creatBuilder();
build.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
Request request = build.url(url).post(create).build();
OkCallBack okCallBack = new OkCallBack(back, method, obj);
enqueue(copyClient, request, okCallBack);
}
public static void post(String url, Map<String, Object> body, ObserverCallBack back, int method, Object obj,
HashMap<String, Object> config) {
Set<String> keySet = body.keySet();
boolean isHasFile = false;
for (String value : keySet) {
Object object = body.get(value);
if (object instanceof File) {
isHasFile = true;
break;
}
}
if (!isHasFile) {
postString(url, body, back, method, obj, config);
return;
}
okhttp3.Request.Builder build = creatBuilder();
build.tag(config);
OkHttpClient copyOkHttpClient = connectionParmter(config, mOkHttpClient);
// 构造上传请求,类似web表单
okhttp3.MultipartBody.Builder type = new MultipartBody.Builder();
keySet = body.keySet();
RequestBody fileBody = null;
for (String key : keySet) {
Object object = body.get(key);
if (object == null)
continue;
if (object instanceof String) {
type.addFormDataPart(key, (String) object);
} else if (object instanceof File) {
File file = (File) object;
fileBody = RequestBody.create(MediaType.parse(guessMimeType(file.getName())), file);
String format = "form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\"\r\n";
type.addPart(Headers.of("Content-Disposition", format), fileBody);
}
}
RequestBody requestBody = type.build();
Request request = build.url(url).post(requestBody).build();
OkCallBack okCallBack = new OkCallBack(back, method, obj);
enqueue(copyOkHttpClient, request, okCallBack);
}
private static void postString(String url, Map<String, Object> body, ObserverCallBack back, int method, Object obj,
HashMap<String, Object> config) {
Builder type = new FormBody.Builder();
Set<String> keySet = body.keySet();
for (String key : keySet)
type.add(key, (String) body.get(key));
RequestBody requestBody = type.build();
okhttp3.Request.Builder builder = creatBuilder();
builder.tag(config);
OkHttpClient copyClient = connectionParmter(config, mOkHttpClient);
Request request = builder.url(url).post(requestBody).build();
OkCallBack okCallBack = new OkCallBack(back, method, obj);
enqueue(copyClient, request, okCallBack);
}
// ----------------------------------------
public static Response execute(Request request) throws IOException {
return mOkHttpClient.newCall(request).execute();
}
private static Response execute(OkHttpClient mOkHttpClient, Request request) throws IOException {
return mOkHttpClient.newCall(request).execute();
}
/**
* 开启异步线程访问网络
*
* @param request
* @param responseCallback
*/
private static void enqueue(OkHttpClient mOkHttpClient, Request request, Callback responseCallback) {
mOkHttpClient.newCall(request).enqueue(responseCallback);
}
// 配置连接参数
private static OkHttpClient connectionParmter(HashMap<String, Object> config, OkHttpClient copyClient) {
long connectionTime = HttpConfig.getConnectionTime(config);
long readTime = HttpConfig.getReadTime(config);
if (connectionTime > 0 || readTime > 0) {
long currConnectTimeout = TimeUnit.MILLISECONDS.toSeconds(mOkHttpClient.connectTimeoutMillis());
long currReadTime = TimeUnit.MILLISECONDS.toSeconds(mOkHttpClient.readTimeoutMillis());
if (connectionTime < 1)
connectionTime = currConnectTimeout;
if (readTime < 1)
readTime = currReadTime;
// Copy to customize OkHttp for this request.
copyClient = mOkHttpClient.newBuilder().connectTimeout(connectionTime, TimeUnit.SECONDS)
.writeTimeout(mOkHttpClient.writeTimeoutMillis(), TimeUnit.SECONDS)
.readTimeout(readTime, TimeUnit.SECONDS).build();
}
return copyClient;
}
private static Request.Builder creatBuilder() {
okhttp3.Request.Builder build = new Request.Builder();
return build;
}
// 按照okhttp删除对应的缓存
public static void clearCache(String url) {
okhttp3.Request.Builder builder = creatBuilder();
Request request = builder.url(url).build();
String md5Hex = Util.md5Hex(request.url().toString());
if (cache == null)
return;
File directory = cache.directory();
File fileContent = new File(directory, md5Hex + FILE_FLAG_CONTENT);
File fileHead = new File(directory, md5Hex + FILE_FLAG_HTTPHEAD);
if (fileContent != null)
FileUtil.delete(fileContent);
if (fileHead != null)
FileUtil.delete(fileHead);
}
// 清除缓存.0的文件是header .1的文件是数据
public static void clearCache() {
if (cache == null)
return;
File directory = cache.directory();
if (directory != null)
FileUtil.delete(directory);
}
private static String guessMimeType(String path) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(path);
if (contentTypeFor == null) {
contentTypeFor = "application/octet-stream";
}
return contentTypeFor;
}
/**
* 从磁盘读取网络缓存,不支持gzip
*
* @param request
* @return
*/
private static Response getCacheResponse(Request request) {
Class<? extends Cache> class1 = cache.getClass();
Method method = null;
try {
method = class1.getDeclaredMethod("get", Request.class);
} catch (Exception e) {
e.printStackTrace();
}
method.setAccessible(true);
Response res = null;
try {
res = (Response) method.invoke(cache, request);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return res;
}
// 从磁盘读取缓存
public static String getCacheResponse(String url) {
if (cache == null)
return null;
okhttp3.Request.Builder builder = creatBuilder();
Request request = builder.url(url).build();
String key = Util.md5Hex(request.url().toString());
File directory = cache.directory();
File fileContent = new File(directory, key + FILE_FLAG_CONTENT);
File fileHead = new File(directory, key + FILE_FLAG_HTTPHEAD);
if (fileContent != null && fileContent.exists()) {
Response response = getCacheResponse(request, fileContent, fileHead);
if (response == null)
return null;
try {
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
// 从磁盘读取网络缓存,并且支持gzip
private static Response getCacheResponse(Request request, File fileContent, File fileHead) {
boolean isGzip = isGzip(fileHead);
okhttp3.Response.Builder builder = new Response.Builder();
builder.body(new FileResponseBody(fileContent, isGzip));
builder.request(request);
builder.code(200);
builder.protocol(Protocol.HTTP_1_1);
Response res = builder.build();
return res;
}
private static boolean isGzip(File fileHead) {
boolean isGzip = false;
if (fileHead == null)
return isGzip;
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(fileHead);
br = new BufferedReader(fr);
String line = null;
// 官方存储的格式
String GZIP = "Content-Encoding: gzip";
while ((line = br.readLine()) != null) {
if (TextUtils.equals(line, GZIP)) {
isGzip = true;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭缓冲读入流及文件读入流的连接.
br.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return isGzip;
}
// 实现缓存功能
static class CacheApplicationInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
HashMap<String, Object> config = HttpConfig.getConfig(request.tag());
int maxAge = -1;
int maxStale = -1;
File fileContent = null;
File fileHead = null;
if (config != null) {
maxAge = HttpConfig.getMaxAge(config);
maxStale = HttpConfig.getMaxStale(config);
}
// 处理存活期
if (maxAge > 0) {
String md5Hex = Util.md5Hex(request.url().toString());
File directory = cache.directory();
fileContent = new File(directory, md5Hex + FILE_FLAG_CONTENT);
fileHead = new File(directory, md5Hex + FILE_FLAG_HTTPHEAD);
boolean isUse = false;
if (fileContent != null && fileContent.exists()) {
long lastModified = fileContent.lastModified();
long currentThreadTimeMillis = System.currentTimeMillis();
isUse = currentThreadTimeMillis - lastModified < maxAge * 1000;
}
Response cacheResponse = null;
if (isUse)
cacheResponse = getCacheResponse(request, fileContent, fileHead);
if (cacheResponse != null) {
LogUtil.i("--okhttp--", "数据来自缓存(存活期)");
return cacheResponse;
}
}
// 处理没网缓存
if (!hasConnectedNetwork(context) && maxStale > 0) {
if (fileContent == null) {
String md5Hex = Util.md5Hex(request.url().toString());
File directory = cache.directory();
fileContent = new File(directory, md5Hex + FILE_FLAG_CONTENT);
fileHead = new File(directory, md5Hex + FILE_FLAG_HTTPHEAD);
}
boolean isUse = false;
if (fileContent != null && fileContent.exists()) {
long lastModified = fileContent.lastModified();
long currentThreadTimeMillis = System.currentTimeMillis();
isUse = currentThreadTimeMillis - lastModified < maxStale * 1000;
}
Response cacheResponse = null;
if (isUse)
cacheResponse = getCacheResponse(request, fileContent, fileHead);
if (cacheResponse != null) {
LogUtil.i("--okhttp--", "数据来自缓存");
return cacheResponse;
}
}
return chain.proceed(request);
}
public static boolean hasConnectedNetwork(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null)
return false;
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info == null)
return false;
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
info = null;
return true;
}
}
return false;
}
}
/** 可以选择不用开启 */
static class GzipRequestInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
}
Request compressedRequest = originalRequest.newBuilder().header("Content-Encoding", "gzip")
.method(originalRequest.method(), gzip(originalRequest.body())).build();
return chain.proceed(compressedRequest);
}
private RequestBody gzip(final RequestBody body) {
return new RequestBody() {
@Override
public MediaType contentType() {
return body.contentType();
}
@Override
public long contentLength() {
return -1; // 无法知道压缩后的数据大小
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
body.writeTo(gzipSink);
gzipSink.close();
}
};
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import android.os.Handler;
import android.os.Looper;
import okhttp3.Request;
import okhttp3.Response;
class BigJsonThread implements Runnable {
private static Handler handler = new Handler(Looper.getMainLooper());
private String url;
private ObserverBigCallBack back;
private int method;
private Object obj;
public BigJsonThread(String url, ObserverBigCallBack back, int method, Object obj) {
this.url = url;
this.back = back;
this.method = method;
this.obj = obj;
}
// 在子线程中调主线程的回调方法
private void postHandlerBigData(final ObserverBigCallBack back, final String methodFunction, final String response,
final int method, final Object obj) {
handler.post(new Runnable() {
public void run() {
switch (methodFunction) {
case "badBack":
back.badBack(null, method, obj);
break;
case "startBack":
back.startBack(method, obj);
break;
case "endBack":
back.endBack(method, obj);
break;
case "finallyBack":
back.finallyBack(method, obj);
break;
}
}
});
}
@Override
public void run() {
Request request = new Request.Builder().url(url).build();
BufferedReader read = null;
InputStream byteStream = null;
try {
Response execute = OkHttpUtil.execute(request);
if (execute != null && !execute.isSuccessful()) {
postHandlerBigData(back, "badBack", null, method, obj);
return;
}
byteStream = execute.body().byteStream();
StringBuilder old = new StringBuilder();
read = new BufferedReader(new InputStreamReader(byteStream));// 防止中文乱码
char[] buffer = new char[2048];
int len = -1;
boolean init = true;
while ((len = read.read(buffer)) != -1) {// 分段加载
if (init) {
init = false;
postHandlerBigData(back, "startBack", null, method, obj);
}
old.append(buffer, 0, len);
int indexOfStart = -1;
int indexOfEnd = -1;
while (old != null && old.length() > 1 && (indexOfStart = old.indexOf("{")) >= 0
&& (indexOfEnd = old.indexOf("}", indexOfStart)) >= 0 && indexOfStart < indexOfEnd) {
String item = old.substring(indexOfStart, indexOfEnd + 1);
if (item != null)
back.back(item, method, null);
item = null;
old.delete(0, indexOfEnd + 1);
}
}
buffer = null;
old = null;
postHandlerBigData(back, "endBack", null, method, obj);
} catch (IOException e1) {
postHandlerBigData(back, "badBack", null, method, obj);
} finally {
try {
if (read != null)
read.close();
if (byteStream != null)
byteStream.close();
byteStream = null;
read = null;
} catch (IOException e) {
}
postHandlerBigData(back, "finallyBack", null, method, obj);
}
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Response;
public class FileOkCallBack extends OkCallBack {
protected File file;
public FileOkCallBack(File address, ObserverCallBack back, int mehtod, Object obj) {
super(back, mehtod, obj);
this.file = address;
}
@Override
public void onResponse(Call arg1, Response response){
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
try {
is = response.body().byteStream();
fos = new FileOutputStream(file);
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
// 如果下载文件成功,第一个参数为文件的绝对路径
handler.post(new Runnable() {
public void run() {
if (back != null) {
back.back(file.getAbsolutePath(), method, obj);
}
}
});
} catch (IOException e) {
LogUtil.e(e);
handler.post(new Runnable() {
public void run() {
if (back != null) {
back.badBack(file.getAbsolutePath(), method, obj);
}
}
});
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
}
}
import java.io.File;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.BufferedSource;
import okio.Okio;
/**
* 读取缓存文件的内容
* <p>
*
* @version 2017年2月21日
*/
public class FileResponseBody extends ResponseBody {
private FileSource fileSource;
public FileResponseBody(File file, boolean isGzip) {
fileSource = new FileSource(file, isGzip);
}
@Override
public BufferedSource source() {
return Okio.buffer(fileSource);
}
@Override
public MediaType contentType() {
return null;
}
@Override
public long contentLength() {
return -1;
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import okio.Buffer;
import okio.Source;
import okio.Timeout;
/**
* 读取文件源
* <p>
*
* @version 2017年2月21日
*/
public class FileSource implements Source {
private File file = null;
private FileInputStream fileInputStream;
private boolean isGzip;
private InputStream inputStream;
private int contentLength = 0;
public FileSource(File file, boolean isGzip) {
this.file = file;
this.isGzip = isGzip;
}
public long contentLength() {
return contentLength;
}
@Override
public void close() throws IOException {
if (fileInputStream != null) {
fileInputStream.close();
fileInputStream = null;
}
if (inputStream != null) {
inputStream.close();
inputStream = null;
}
}
// res.body().string()调用会执行read
@Override
public long read(Buffer arg0, long arg1) throws IOException {
if (fileInputStream == null) {
fileInputStream = new FileInputStream(file);
if (isGzip)
inputStream = GzipUtil.convertGzipStream(fileInputStream);
else
inputStream = fileInputStream;
}
byte[] data = new byte[1024];
int read = inputStream.read(data);
if (read >= 0)
arg0.write(data, 0, read);
if (read != -1) {
contentLength += read;
}
data = null;
return read;
}
@Override
public Timeout timeout() {
return null;
}
}
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GzipUtil {
// 压缩
public static String compress(String str) throws IOException {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes());
gzip.close();
out.close();
return out.toString();
}
// 解压缩
public static String uncompress(String str) throws IOException {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes());
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gunzip = new GZIPInputStream(in);
byte[] buffer = new byte[256];
int n;
while ((n = gunzip.read(buffer)) >= 0) {
out.write(buffer, 0, n);
}
in.close();
out.close();
gunzip.close();
// toString()使用平台默认编码,也可以显式的指定如toString("GBK")
return out.toString();
}
// 解压缩
public static GZIPInputStream convertGzipStream(InputStream str) throws IOException {
if (str == null) {
return null;
}
GZIPInputStream gunzip = new GZIPInputStream(str);
return gunzip;
}
}
import java.util.HashMap;
/**
* 网络配置类
*
*
* 2017年2月21日
*/
public class HttpConfig {
public static final String CONNECT_TIME = "con-time";// 可连接时间,单位秒
public static final String READ_TIME_OUT = "read-time";// 可读时间,单位秒
public static final String MAX_AGE = "max-age";// 存活时间,多少秒之内不用走网络,单位秒
public static final String MAX_STALE = "max-stale";// 没获取成功走本地的网络缓存,单位秒
public static boolean isForceCache(HashMap<String, Object> map) {
if (map == null)
return false;
boolean containsKey = map.containsKey(CONNECT_TIME);
if (containsKey) {
Object object = map.get(CONNECT_TIME);
if (object != null && object instanceof Boolean)
return (Boolean) object;
}
return false;
}
@SuppressWarnings("unchecked")
public static HashMap<String, Object> getConfig(Object obj) {
if (obj == null)
return null;
if (obj instanceof HashMap)
return (HashMap<String, Object>) obj;
return null;
}
public static int getConnectionTime(HashMap<String, Object> map) {
if (map == null)
return -1;
boolean containsKey = map.containsKey(CONNECT_TIME);
if (containsKey) {
Object object = map.get(CONNECT_TIME);
if (object != null && object instanceof Integer)
return (int) object;
}
return -1;
}
public static int getReadTime(HashMap<String, Object> map) {
if (map == null)
return -1;
boolean containsKey = map.containsKey(READ_TIME_OUT);
if (containsKey) {
Object object = map.get(READ_TIME_OUT);
if (object != null && object instanceof Integer)
return (int) object;
}
return -1;
}
public static int getMaxAge(HashMap<String, Object> map) {
if (map == null)
return -1;
boolean containsKey = map.containsKey(MAX_AGE);
if (containsKey) {
Object object = map.get(MAX_AGE);
if (object != null && object instanceof Integer)
return (int) object;
}
return -1;
}
public static int getMaxStale(HashMap<String, Object> map) {
if (map == null)
return -1;
boolean containsKey = map.containsKey(MAX_STALE);
if (containsKey) {
Object object = map.get(MAX_STALE);
if (object != null && object instanceof Integer)
return (int) object;
}
return -1;
}
public static HashMap<String, Object> newConfig() {
HashMap<String, Object> config = new HashMap<String, Object>();
return config;
}
public static HashMap<String, Object> newConfig(int maxAge, int maxStale) {
HashMap<String, Object> config = new HashMap<String, Object>();
config.put(MAX_AGE, maxAge);
config.put(MAX_STALE, maxStale);
return config;
}
public static HashMap<String, Object> defaultConfig() {
// 存活2分钟,缓存2天
return newConfig(120, 60 * 60 * 24 * 2);
}
public static HashMap<String, Object> smallConfig() {
// 存活1小时,缓存2天
return newConfig(60 * 60, 60 * 60 * 24 * 2);
}
public static HashMap<String, Object> middleConfig() {
// 存活24小时,缓存5天
return newConfig(60 * 60 * 24, 60 * 60 * 24 * 5);
}
}
/**
* 分批返回
* <p>
*
* @version 2016年4月20日
*/
public interface ObserverBigCallBack extends ObserverCallBack {
public void startBack(int method, Object obj);
public void endBack(int method, Object obj);
public void finallyBack(int method, Object obj);
}
public interface ObserverCallBack {
/**
*
* @param data
* 服务端的信息
* @param encoding
* 响应状态
* @param method
* 请求的接口
* @param obj
* 附带值
*/
public void back(String data, int method, Object obj);
public void badBack(String error, int method, Object obj);
}
import java.io.IOException;
import java.net.URL;
import android.os.Handler;
import android.os.Looper;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Response;
public class OkCallBack implements Callback {
protected static Handler handler = new Handler(Looper.getMainLooper());
protected ObserverCallBack back;
protected int method;
protected Object obj;
protected String response;
public OkCallBack(ObserverCallBack back, int method, Object obj) {
this.back = back;
this.method = method;
this.obj = obj;
}
@Override
public void onFailure(Call arg0, IOException arg1) {
if (arg1 != null && arg0 != null) //需要try catch
response = arg1.toString();
failed();
}
@Override
public void onResponse(Call arg1, Response arg0) {
if (arg0 != null) //需要try catch
response = arg0.body().string();
successful();
}
private void successful() {
if (back == null)
return;
handler.post(new Runnable() {
public void run() {
back.back(response, method, obj);
}
});
}
private void failed() {
if (back == null)
return;
handler.post(new Runnable() {
public void run() {
back.badBack(response, method, obj);
}
});
}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import android.os.Environment;
public class FileUtil {
/**
* 删除文件(包括子文件)
*
* @param file
*/
public static void delete(File file) {
if (file.isDirectory()) {
File[] childs = file.listFiles();
for (File file2 : childs)
delete(file2);
}
file.delete();
}
}
//如果版本是大于3.4.1,的可能找不到Util.md5Hex()方法,源码里面Util.md5Hex变成了Cache.key,如下
// okhttp
public static String md5Hex(HttpUrl url) {
return Cache.key(url);
}