Java tutorial
/** * Copyright (c) 2012-2013, Michael Yang ?? (www.yangfuhai.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mygame.cloudcontact.http; import java.io.File; import java.io.IOException; import java.net.UnknownHostException; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.HttpResponseException; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.protocol.HttpContext; import android.os.AsyncTask; import android.os.SystemClock; import com.mygame.cloudcontact.http.entityhandler.EntityCallBack; import com.mygame.cloudcontact.http.entityhandler.FileEntityHandler; import com.mygame.cloudcontact.http.entityhandler.StringEntityHandler; public class HttpHandler<T> extends AsyncTask<Object, Object, Object> implements EntityCallBack { private final AbstractHttpClient client; private final HttpContext context; private final StringEntityHandler mStrEntityHandler = new StringEntityHandler(); private final FileEntityHandler mFileEntityHandler = new FileEntityHandler(); private final AjaxCallBack<T> callback; private int executionCount = 0; private String targetUrl = null; // private boolean isResume = false; // ? private String charset; // ?? private CheckResponseInterface mCheckResponse; public void setCheckResponse(CheckResponseInterface checkResponse) { this.mCheckResponse = checkResponse; } public HttpHandler(AbstractHttpClient client, HttpContext context, AjaxCallBack<T> callback, String charset) { this.client = client; this.context = context; this.callback = callback; this.charset = charset; } private void makeRequestWithRetries(HttpUriRequest request) throws IOException { if (isResume && targetUrl != null) { File downloadFile = new File(targetUrl); long fileLen = 0; if (downloadFile.isFile() && downloadFile.exists()) { fileLen = downloadFile.length(); } if (fileLen > 0) request.setHeader("RANGE", "bytes=" + fileLen + "-"); } boolean retry = true; IOException cause = null; HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler(); while (retry) { try { if (!isCancelled()) { HttpResponse response = client.execute(request, context); if (!isCancelled()) { handleResponse(request, response); } } return; } catch (UnknownHostException e) { publishProgress(UPDATE_FAILURE, e, 0, "unknownHostExceptioncan't resolve host"); return; } catch (IOException e) { cause = e; retry = retryHandler.retryRequest(cause, ++executionCount, context); } catch (NullPointerException e) { // HttpClient 4.0.x ?bug // http://code.google.com/p/android/issues/detail?id=5255 cause = new IOException("NPE in HttpClient" + e.getMessage()); retry = retryHandler.retryRequest(cause, ++executionCount, context); } catch (Exception e) { cause = new IOException("Exception" + e.getMessage()); retry = retryHandler.retryRequest(cause, ++executionCount, context); } } if (cause != null) throw cause; else throw new IOException(""); } @Override protected Object doInBackground(Object... params) { if (params != null && params.length == 3) { targetUrl = String.valueOf(params[1]); isResume = (Boolean) params[2]; } try { publishProgress(UPDATE_START); // makeRequestWithRetries((HttpUriRequest) params[0]); } catch (IOException e) { publishProgress(UPDATE_FAILURE, e, 0, e.getMessage()); // ? } return null; } private final static int UPDATE_START = 1; private final static int UPDATE_LOADING = 2; private final static int UPDATE_FAILURE = 3; private final static int UPDATE_SUCCESS = 4; @SuppressWarnings("unchecked") @Override protected void onProgressUpdate(Object... values) { int update = Integer.valueOf(String.valueOf(values[0])); switch (update) { case UPDATE_START: if (callback != null) callback.onStart(); break; case UPDATE_LOADING: if (callback != null) callback.onLoading(Long.valueOf(String.valueOf(values[1])), Long.valueOf(String.valueOf(values[2]))); break; case UPDATE_FAILURE: if (callback != null) { Throwable error = (Throwable) values[1]; int errorNo = (Integer) values[2]; String errorMsg = (String) values[3]; // if (error instanceof IOException) { errorMsg = ""; } else if (error instanceof HttpResponseException) { errorMsg = "???"; } callback.onFailure(error, errorNo, errorMsg); } break; case UPDATE_SUCCESS: if (callback != null) { callback.onSuccess((T) values[1]); callback.onSuccess((T) values[1], (HttpUriRequest) values[2], (HttpResponse) values[3]); } break; default: break; } super.onProgressUpdate(values); } public boolean isStop() { return mFileEntityHandler.isStop(); } /** * @param stop * ? */ public void stop() { mFileEntityHandler.setStop(true); } private void handleResponse(HttpUriRequest request, HttpResponse response) { StatusLine status = response.getStatusLine(); if (status.getStatusCode() >= 300) { String errorMsg = "response status error code:" + status.getStatusCode(); if (status.getStatusCode() == 416 && isResume) { errorMsg += " \n maybe you have download complete."; } publishProgress(UPDATE_FAILURE, new HttpResponseException(status.getStatusCode(), status.getReasonPhrase()), status.getStatusCode(), errorMsg); } else { try { // ?? if (mCheckResponse != null) { // if (mCheckResponse.checkResponse(request, response)) return; } // ? HttpEntity entity = response.getEntity(); Object responseBody = null; if (entity != null) { time = SystemClock.uptimeMillis(); if (targetUrl != null) { responseBody = mFileEntityHandler.handleEntity(entity, this, targetUrl, isResume); } else { responseBody = mStrEntityHandler.handleEntity(entity, this, charset); } } publishProgress(UPDATE_SUCCESS, responseBody, request, response); } catch (IOException e) { publishProgress(UPDATE_FAILURE, e, 0, e.getMessage()); } catch (SeverRequestException e) { publishProgress(UPDATE_FAILURE, e, 0, e.getMessage()); } } } private long time; @Override public void callBack(long count, long current, boolean mustNoticeUI) { if (callback != null && callback.isProgress()) { if (mustNoticeUI) { publishProgress(UPDATE_LOADING, count, current); } else { long thisTime = SystemClock.uptimeMillis(); if (thisTime - time >= callback.getRate()) { time = thisTime; publishProgress(UPDATE_LOADING, count, current); } } } } }