package com.huxq17.example.http;
import android.annotation.TargetApi;
import android.os.Build;
import android.text.TextUtils;
import com.andbase.tractor.listener.LoadListener;
import com.andbase.tractor.task.Task;
import com.andbase.tractor.task.TaskPool;
import com.andbase.tractor.utils.LogUtils;
import com.huxq17.example.http.body.FileBody;
import com.huxq17.example.http.request.CountingRequestBody;
import com.huxq17.example.http.request.HttpHeader;
import com.huxq17.example.http.request.HttpMethod;
import com.huxq17.example.http.request.HttpRequest;
import com.huxq17.example.http.request.RequestParams;
import com.huxq17.example.http.response.HttpResponse;
import com.huxq17.example.http.response.ResponseType;
import java.io.File;
import java.io.IOException;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created by xiaoqian.hu on 2015/10/15.
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class OKHttp implements HttpBase {
private static final OkHttpClient mOkHttpClient = new OkHttpClient();
private NetWorkTask netWorkTask;
static {
mOkHttpClient.setRetryOnConnectionFailure(true);
mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(15, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(15, TimeUnit.SECONDS);
// mOkHttpClient.networkInterceptors().add(new RedirectInterceptor());
int versionCode = Build.VERSION.SDK_INT;
if (versionCode >= 9) {
mOkHttpClient.setCookieHandler(new CookieManager(null,
CookiePolicy.ACCEPT_ORIGINAL_SERVER));
// StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
// StrictMode.setThreadPolicy(policy);
}
}
public void prepareTask() {
netWorkTask = new NetWorkTask();
}
@Override
public HttpResponse get(HttpRequest request, LoadListener listener, Object... tag) {
prepareTask();
String url = request.getUrl();
RequestParams requestParams = request.getRequestParams();
HttpHeader header = request.getHeader();
boolean synchron = request.isSynchron();
String params = requestParams.toString();
if (!TextUtils.isEmpty(params)) {
url += "?" + params;
}
LogUtils.d("get url=" + url);
Request.Builder builder = getBuilder().url(url);
addHeader(builder, header);
addTag(builder, tag);
ResponseType responseType = request.responseType();
return execute(responseType, builder.build(), synchron, listener, getTag(tag));
}
@Override
public HttpResponse post(HttpRequest request, LoadListener listener, Object... tag) {
prepareTask();
String url = request.getUrl();
LogUtils.d("post url=" + url);
RequestParams requestParams = request.getRequestParams();
HttpHeader header = request.getHeader();
boolean synchron = request.isSynchron();
RequestBody requestBody = buildRequestBody(requestParams);
if (requestBody == null) {
throw new RuntimeException("requestBody==null");
}
Request.Builder builder = getBuilder().url(url).post(requestBody);
addHeader(builder, header);
addTag(builder, tag);
ResponseType responseType = request.responseType();
return execute(responseType, builder.build(), synchron, listener, getTag(tag));
}
@Override
public HttpResponse request(HttpRequest request, LoadListener listener, Object... tag) {
prepareTask();
String url = request.getUrl();
RequestParams requestParams = request.getRequestParams();
HttpHeader header = request.getHeader();
boolean synchron = request.isSynchron();
HttpMethod method = request.getMethod();
LogUtils.d(method.toString() + " url=" + url);
Request.Builder builder = getBuilder().url(url);
String contentType = requestParams.getContentType();
String charset = requestParams.getCharSet();
if (TextUtils.isEmpty(contentType) || TextUtils.isEmpty(charset)) {
throw new RuntimeException("contentType is empty || charset is empty");
}
addHeader(builder, header);
if (HttpMethod.permitsRequestBody(method)) {
if (HttpMethod.requiresRequestBody(method)) {
if (requestParams.isEmpty()) {
throw new RuntimeException("method:" + method.toString() + "must have params");
}
}
if (!requestParams.isEmpty()) {
builder.method(method.toString(), buildRequestBody(requestParams));
} else {
builder.method(method.toString(), null);
}
} else {
builder.method(method.toString(), null);
}
addTag(builder, tag);
ResponseType responseType = request.responseType();
return execute(responseType, builder.build(), synchron, listener, getTag(tag));
}
private RequestBody buildRequestBody(RequestParams requestParams) {
List<FileBody> files = requestParams.getFiles();
String contentType = requestParams.getContentType();
String charset = requestParams.getCharSet();
String params = requestParams.toString();
LinkedHashMap<String, Object> paramsHashmap = requestParams.getmParams();
if (params == null || TextUtils.isEmpty(contentType) || TextUtils.isEmpty(charset)) {
throw new RuntimeException("params is null");
}
if (files != null && files.size() > 0) {
LogUtils.d("upload file.size=" + files.size());
// MultipartBuilder builder = new MultipartBuilder()
// .type(MultipartBuilder.FORM);
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (FileBody body : files) {
String paramName = body.getParameterName();
File file = body.getFile();
contentType = body.getContentType();
RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), file);
builder.addPart(Headers.of("Content-Disposition",
"form-data; name=\"" + paramName + "\"; filename=\"" + file.getName() + "\""),
fileBody);
LogUtils.d("upload paramName=" + paramName + ";filename=" + file.getName());
}
for (LinkedHashMap.Entry set : paramsHashmap.entrySet()) {
Object value = set.getValue();
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + set.getKey() + "\""),
RequestBody.create(null, value.toString()));
}
RequestBody requestBody = new CountingRequestBody(builder.build(), netWorkTask);
return requestBody;
// return builder.build();
} else {
LogUtils.i("params=" + params + ";mediaType=" + contentType + "; charset=" + charset);
return RequestBody.create(MediaType.parse(contentType + "; charset=" + charset), params);
}
}
private void addHeader(Request.Builder builder, HttpHeader header) {
HashMap<String, String> headers = header.getHeaders();
if (headers != null && headers.size() > 0) {
for (HashMap.Entry<String, String> map :
headers.entrySet()) {
builder.addHeader(map.getKey(), map.getValue());
}
}
}
public void addTag(Request.Builder builder, Object... tag) {
if (tag != null && tag.length == 1) {
builder.tag(tag[0]);
}
}
private Object getTag(Object... tag) {
if (tag != null && tag.length == 1) {
return tag[0];
}
return null;
}
public void cancel(Object... tag) {
if (tag != null && tag.length == 1) {
for (int i = 0; i < tag.length; i++) {
mOkHttpClient.cancel(tag[i]);
}
}
}
private Request.Builder getBuilder() {
return new Request.Builder();
}
private HttpResponse execute(ResponseType type, Request request, boolean synchron, LoadListener listener, Object tag) {
final Call call = mOkHttpClient.newCall(request);
HttpResponse httpResponse = null;
if (synchron) {
try {
httpResponse = new HttpResponse();
httpResponse.setResponseType(type);
Response response = call.execute();
String string = null;
switch (type) {
case String:
try {
string = response.body().string();
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
httpResponse.setString(string);
// LogUtils.d("okresult: " + string);
break;
case InputStream:
httpResponse.setInputStream(response.body().byteStream());
break;
}
httpResponse.setContentLength(response.body().contentLength());
} catch (Exception e) {
e.printStackTrace();
}
} else {
netWorkTask.setCall(type, call, tag, listener);
TaskPool.getInstance().execute(netWorkTask);
}
return httpResponse;
}
public class NetWorkTask extends Task {
private Call mCall;
private ResponseType mType;
public void setCall(ResponseType type, Call call, Object tag, LoadListener listener) {
mCall = call;
setTag(tag);
setListener(listener);
mType = type;
}
@Override
public void onRun() {
execute();
// enqueue();
}
private void execute() {
try {
Response response = mCall.execute();
HttpResponse httpResponse = new HttpResponse();
String string = null;
httpResponse.setContentLength(response.body().contentLength());
httpResponse.setResponseType(mType);
switch (mType) {
case String:
try {
string = response.body().string();
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
httpResponse.setString(string);
LogUtils.d("okresult: " + string + ";contentLength=" + response.body().contentLength());
break;
case InputStream:
httpResponse.setInputStream(response.body().byteStream());
break;
}
notifySuccess(httpResponse);
} catch (Exception e) {
if (e.toString().toLowerCase().contains("canceled")
|| e.toString().toLowerCase().contains("closed")) {
notifyCancel(e);
} else {
notifyFail(e);
}
e.printStackTrace();
}
}
private void enqueue() {
mCall.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
synchronized (NetWorkTask.this) {
NetWorkTask.this.notifyFail(e);
NetWorkTask.this.notify();
}
}
@Override
public void onResponse(Response response) throws IOException {
synchronized (NetWorkTask.this) {
HttpResponse httpResponse = new HttpResponse();
String string = null;
switch (mType) {
case String:
try {
string = response.body().string();
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
}
httpResponse.setString(string);
LogUtils.d("okresult: " + string);
break;
case InputStream:
httpResponse.setInputStream(response.body().byteStream());
break;
}
httpResponse.setString(string);
httpResponse.setContentLength(response.body().contentLength());
NetWorkTask.this.notifySuccess(httpResponse);
NetWorkTask.this.notify();
}
}
});
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void cancelTask() {
mCall.cancel();
}
}
}