Java tutorial
/* * Copyright (C) 2013 www.418log.org * * 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.ab.http; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.zip.GZIPInputStream; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.HttpVersion; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.protocol.ClientContext; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.params.ConnPerRouteBean; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultRedirectHandler; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.SyncBasicHttpContext; import android.content.Context; import android.util.Log; import com.ab.task.AbTaskPool; // TODO: Auto-generated Javadoc /** * The AsyncHttpClient can be used to make asynchronous GET, POST, PUT and * DELETE HTTP requests in your Android applications. Requests can be made * with additional parameters by passing a {@link RequestParams} instance, * and responses can be handled by passing an anonymously overridden * {@link AsyncHttpResponseHandler} instance. * <p> </p> * For example: * <p> </p> * <pre> * AsyncHttpClient client = new AsyncHttpClient(); * client.get("http://www.google.com", new AsyncHttpResponseHandler() { * @Override * public void onSuccess(String response) { * System.out.println(response); * } * }); * </pre> */ public class AsyncHttpClient { /** The Constant VERSION. */ private static final String VERSION = "1.4.4"; /** The Constant DEFAULT_MAX_CONNECTIONS. */ private static final int DEFAULT_MAX_CONNECTIONS = 10; /** The Constant DEFAULT_SOCKET_TIMEOUT. */ private static final int DEFAULT_SOCKET_TIMEOUT = 10 * 1000; /** The Constant DEFAULT_MAX_RETRIES. */ private static final int DEFAULT_MAX_RETRIES = 5; /** The Constant DEFAULT_RETRY_SLEEP_TIME_MILLIS. */ private static final int DEFAULT_RETRY_SLEEP_TIME_MILLIS = 1500; /** The Constant DEFAULT_SOCKET_BUFFER_SIZE. */ private static final int DEFAULT_SOCKET_BUFFER_SIZE = 8192; /** The Constant HEADER_ACCEPT_ENCODING. */ private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; /** The Constant ENCODING_GZIP. */ private static final String ENCODING_GZIP = "gzip"; /** The Constant LOG_TAG. */ private static final String LOG_TAG = "AsyncHttpClient"; /** The max connections. */ private int maxConnections = DEFAULT_MAX_CONNECTIONS; /** The timeout. */ private int timeout = DEFAULT_SOCKET_TIMEOUT; /** The http client. */ private final DefaultHttpClient httpClient; /** The http context. */ private final HttpContext httpContext; /** The thread pool. */ private static ExecutorService threadPool = null; /** The request map. */ private final Map<Context, List<WeakReference<Future<?>>>> requestMap; /** The client header map. */ private final Map<String, String> clientHeaderMap; /** The is url encoding enabled. */ private boolean isUrlEncodingEnabled = true; /** * Creates a new AsyncHttpClient with default constructor arguments values. */ public AsyncHttpClient() { this(false, 80, 443); } /** * Creates a new AsyncHttpClient. * * @param httpPort non-standard HTTP-only port */ public AsyncHttpClient(int httpPort) { this(false, httpPort, 443); } /** * Creates a new AsyncHttpClient. * * @param httpPort non-standard HTTP-only port * @param httpsPort non-standard HTTPS-only port */ public AsyncHttpClient(int httpPort, int httpsPort) { this(false, httpPort, httpsPort); } /** * Creates new AsyncHttpClient using given params. * * @param fixNoHttpResponseException Whether to fix or not issue, by ommiting SSL verification * @param httpPort HTTP port to be used, must be greater than 0 * @param httpsPort HTTPS port to be used, must be greater than 0 */ public AsyncHttpClient(boolean fixNoHttpResponseException, int httpPort, int httpsPort) { this(getDefaultSchemeRegistry(fixNoHttpResponseException, httpPort, httpsPort)); } /** * Returns default instance of SchemeRegistry. * * @param fixNoHttpResponseException Whether to fix or not issue, by ommiting SSL verification * @param httpPort HTTP port to be used, must be greater than 0 * @param httpsPort HTTPS port to be used, must be greater than 0 * @return the default scheme registry */ private static SchemeRegistry getDefaultSchemeRegistry(boolean fixNoHttpResponseException, int httpPort, int httpsPort) { if (fixNoHttpResponseException) { Log.d(LOG_TAG, "Beware! Using the fix is insecure, as it doesn't verify SSL certificates."); } if (httpPort < 1) { httpPort = 80; Log.d(LOG_TAG, "Invalid HTTP port number specified, defaulting to 80"); } if (httpsPort < 1) { httpsPort = 443; Log.d(LOG_TAG, "Invalid HTTPS port number specified, defaulting to 443"); } // Fix to SSL flaw in API < ICS // See https://code.google.com/p/android/issues/detail?id=13117 SSLSocketFactory sslSocketFactory; if (fixNoHttpResponseException) sslSocketFactory = MySSLSocketFactory.getFixedSocketFactory(); else sslSocketFactory = SSLSocketFactory.getSocketFactory(); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), httpPort)); schemeRegistry.register(new Scheme("https", sslSocketFactory, httpsPort)); return schemeRegistry; } /** * Creates a new AsyncHttpClient. * * @param schemeRegistry SchemeRegistry to be used */ public AsyncHttpClient(SchemeRegistry schemeRegistry) { BasicHttpParams httpParams = new BasicHttpParams(); ConnManagerParams.setTimeout(httpParams, timeout); ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections)); ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS); HttpConnectionParams.setSoTimeout(httpParams, timeout); HttpConnectionParams.setConnectionTimeout(httpParams, timeout); HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setUserAgent(httpParams, String.format("android-async-http/%s (http://loopj.com/android-async-http)", VERSION)); ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry); threadPool = AbTaskPool.getExecutorService(); requestMap = new WeakHashMap<Context, List<WeakReference<Future<?>>>>(); clientHeaderMap = new HashMap<String, String>(); httpContext = new SyncBasicHttpContext(new BasicHttpContext()); httpClient = new DefaultHttpClient(cm, httpParams); httpClient.addRequestInterceptor(new HttpRequestInterceptor() { @Override public void process(HttpRequest request, HttpContext context) { if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) { request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); } for (String header : clientHeaderMap.keySet()) { request.addHeader(header, clientHeaderMap.get(header)); } } }); httpClient.addResponseInterceptor(new HttpResponseInterceptor() { @Override public void process(HttpResponse response, HttpContext context) { final HttpEntity entity = response.getEntity(); if (entity == null) { return; } final Header encoding = entity.getContentEncoding(); if (encoding != null) { for (HeaderElement element : encoding.getElements()) { if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) { response.setEntity(new InflatingEntity(entity)); break; } } } } }); httpClient .setHttpRequestRetryHandler(new RetryHandler(DEFAULT_MAX_RETRIES, DEFAULT_RETRY_SLEEP_TIME_MILLIS)); } /** * Get the underlying HttpClient instance. This is useful for setting * additional fine-grained settings for requests by accessing the * client's ConnectionManager, HttpParams and SchemeRegistry. * * @return underlying HttpClient instance */ public HttpClient getHttpClient() { return this.httpClient; } /** * Get the underlying HttpContext instance. This is useful for getting * and setting fine-grained settings for requests by accessing the * context's attributes such as the CookieStore. * * @return underlying HttpContext instance */ public HttpContext getHttpContext() { return this.httpContext; } /** * Sets an optional CookieStore to use when making requests. * * @param cookieStore The CookieStore implementation to use, usually an instance of {@link PersistentCookieStore} */ public void setCookieStore(CookieStore cookieStore) { httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); } /** * Overrides the threadpool implementation used when queuing/pooling * requests. By default, Executors.newCachedThreadPool() is used. * * @param threadPool an instance of {@link ThreadPoolExecutor} to use for queuing/pooling requests. */ public void setThreadPool(ThreadPoolExecutor threadPool) { this.threadPool = threadPool; } /** * Simple interface method, to enable or disable redirects. * If you set manually RedirectHandler on underlying HttpClient, effects of this method will be canceled. * * @param enableRedirects boolean */ public void setEnableRedirects(final boolean enableRedirects) { httpClient.setRedirectHandler(new DefaultRedirectHandler() { @Override public boolean isRedirectRequested(HttpResponse response, HttpContext context) { return enableRedirects; } }); } /** * Sets the User-Agent header to be sent with each request. By default, * "Android Asynchronous Http Client/VERSION (http://loopj.com/android-async-http/)" is used. * * @param userAgent the string to use in the User-Agent header. */ public void setUserAgent(String userAgent) { HttpProtocolParams.setUserAgent(this.httpClient.getParams(), userAgent); } /** * Returns current limit of parallel connections. * * @return maximum limit of parallel connections, default is 10 */ public int getMaxConnections() { return maxConnections; } /** * Sets maximum limit of parallel connections. * * @param maxConnections maximum parallel connections, must be at least 1 */ public void setMaxConnections(int maxConnections) { if (maxConnections < 1) maxConnections = DEFAULT_MAX_CONNECTIONS; this.maxConnections = maxConnections; final HttpParams httpParams = this.httpClient.getParams(); ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(this.maxConnections)); } /** * Returns current socket timeout limit (milliseconds), default is 10000 (10sec). * * @return Socket Timeout limit in milliseconds */ public int getTimeout() { return timeout; } /** * Set the connection and socket timeout. By default, 10 seconds. * * @param timeout the connect/socket timeout in milliseconds, at least 1 second */ public void setTimeout(int timeout) { if (timeout < 1000) timeout = DEFAULT_SOCKET_TIMEOUT; this.timeout = timeout; final HttpParams httpParams = this.httpClient.getParams(); ConnManagerParams.setTimeout(httpParams, this.timeout); HttpConnectionParams.setSoTimeout(httpParams, this.timeout); HttpConnectionParams.setConnectionTimeout(httpParams, this.timeout); } /** * Sets the Proxy by it's hostname and port. * * @param hostname the hostname (IP or DNS name) * @param port the port number. -1 indicates the scheme default port. */ public void setProxy(String hostname, int port) { final HttpHost proxy = new HttpHost(hostname, port); final HttpParams httpParams = this.httpClient.getParams(); httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } /** * Sets the Proxy by it's hostname,port,username and password. * * @param hostname the hostname (IP or DNS name) * @param port the port number. -1 indicates the scheme default port. * @param username the username * @param password the password */ public void setProxy(String hostname, int port, String username, String password) { httpClient.getCredentialsProvider().setCredentials(new AuthScope(hostname, port), new UsernamePasswordCredentials(username, password)); final HttpHost proxy = new HttpHost(hostname, port); final HttpParams httpParams = this.httpClient.getParams(); httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } /** * Sets the SSLSocketFactory to user when making requests. By default, * a new, default SSLSocketFactory is used. * * @param sslSocketFactory the socket factory to use for https requests. */ public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { this.httpClient.getConnectionManager().getSchemeRegistry() .register(new Scheme("https", sslSocketFactory, 443)); } /** * Sets the maximum number of retries and timeout for a particular Request. * * @param retries maximum number of retries per request * @param timeout the timeout */ public void setMaxRetriesAndTimeout(int retries, int timeout) { this.httpClient.setHttpRequestRetryHandler(new RetryHandler(retries, timeout)); } /** * Sets headers that will be added to all requests this client makes (before sending). * * @param header the name of the header * @param value the contents of the header */ public void addHeader(String header, String value) { clientHeaderMap.put(header, value); } /** * Remove header from all requests this client makes (before sending). * * @param header the name of the header */ public void removeHeader(String header) { clientHeaderMap.remove(header); } /** * Sets basic authentication for the request. Uses AuthScope.ANY. This is the same as * setBasicAuth('username','password',AuthScope.ANY) * * @param username Basic Auth username * @param password Basic Auth password */ public void setBasicAuth(String username, String password) { AuthScope scope = AuthScope.ANY; setBasicAuth(username, password, scope); } /** * Sets basic authentication for the request. You should pass in your AuthScope for security. It should be like this * setBasicAuth("username","password", new AuthScope("host",port,AuthScope.ANY_REALM)) * * @param username Basic Auth username * @param password Basic Auth password * @param scope - an AuthScope object */ public void setBasicAuth(String username, String password, AuthScope scope) { UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password); this.httpClient.getCredentialsProvider().setCredentials(scope, credentials); } /** * Removes set basic auth credentials. */ public void clearBasicAuth() { this.httpClient.getCredentialsProvider().clear(); } /** * Cancels any pending (or potentially active) requests associated with the * passed Context. * <p> </p> * <b>Note:</b> This will only affect requests which were created with a non-null * android Context. This method is intended to be used in the onDestroy * method of your android activities to destroy all requests which are no * longer required. * * @param context the android Context instance associated to the request. * @param mayInterruptIfRunning specifies if active requests should be cancelled along with pending requests. */ public void cancelRequests(Context context, boolean mayInterruptIfRunning) { List<WeakReference<Future<?>>> requestList = requestMap.get(context); if (requestList != null) { for (WeakReference<Future<?>> requestRef : requestList) { Future<?> request = requestRef.get(); if (request != null) { request.cancel(mayInterruptIfRunning); } } } requestMap.remove(context); } // // HTTP HEAD Requests // /** * Perform a HTTP HEAD request, without any parameters. * * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle head(String url, AsyncHttpResponseHandler responseHandler) { return head(null, url, null, responseHandler); } /** * Perform a HTTP HEAD request with parameters. * * @param url the URL to send the request to. * @param params additional HEAD parameters to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle head(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return head(null, url, params, responseHandler); } /** * Perform a HTTP HEAD request without any parameters and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle head(Context context, String url, AsyncHttpResponseHandler responseHandler) { return head(context, url, null, responseHandler); } /** * Perform a HTTP HEAD request and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param params additional HEAD parameters to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle head(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return sendRequest(httpClient, httpContext, new HttpHead(getUrlWithQueryString(isUrlEncodingEnabled, url, params)), null, responseHandler, context); } /** * Perform a HTTP HEAD request and track the Android Context which initiated * the request with customized headers. * * @param context Context to execute request against * @param url the URL to send the request to. * @param headers set headers only for this request * @param params additional HEAD parameters to send with the request. * @param responseHandler the response handler instance that should handle * the response. * @return the request handle */ public RequestHandle head(Context context, String url, Header[] headers, RequestParams params, AsyncHttpResponseHandler responseHandler) { HttpUriRequest request = new HttpHead(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); if (headers != null) request.setHeaders(headers); return sendRequest(httpClient, httpContext, request, null, responseHandler, context); } // // HTTP GET Requests // /** * Perform a HTTP GET request, without any parameters. * * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle get(String url, AsyncHttpResponseHandler responseHandler) { return get(null, url, null, responseHandler); } /** * Perform a HTTP GET request with parameters. * * @param url the URL to send the request to. * @param params additional GET parameters to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return get(null, url, params, responseHandler); } /** * Perform a HTTP GET request without any parameters and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle get(Context context, String url, AsyncHttpResponseHandler responseHandler) { return get(context, url, null, responseHandler); } /** * Perform a HTTP GET request and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param params additional GET parameters to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle get(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return sendRequest(httpClient, httpContext, new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params)), null, responseHandler, context); } /** * Perform a HTTP GET request and track the Android Context which initiated * the request with customized headers. * * @param context Context to execute request against * @param url the URL to send the request to. * @param headers set headers only for this request * @param params additional GET parameters to send with the request. * @param responseHandler the response handler instance that should handle * the response. * @return the request handle */ public RequestHandle get(Context context, String url, Header[] headers, RequestParams params, AsyncHttpResponseHandler responseHandler) { HttpUriRequest request = new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); if (headers != null) request.setHeaders(headers); return sendRequest(httpClient, httpContext, request, null, responseHandler, context); } // // HTTP POST Requests // /** * Perform a HTTP POST request, without any parameters. * * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle post(String url, AsyncHttpResponseHandler responseHandler) { return post(null, url, null, responseHandler); } /** * Perform a HTTP POST request with parameters. * * @param url the URL to send the request to. * @param params additional POST parameters or files to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return post(null, url, params, responseHandler); } /** * Perform a HTTP POST request and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param params additional POST parameters or files to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle post(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return post(context, url, paramsToEntity(params, responseHandler), null, responseHandler); } /** * Perform a HTTP POST request and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param entity a raw {@link org.apache.http.HttpEntity} to send with the request, for example, use this to send string/json/xml payloads to a server by passing a {@link org.apache.http.entity.StringEntity}. * @param contentType the content type of the payload you are sending, for example application/json if sending a json payload. * @param responseHandler the response ha ndler instance that should handle the response. * @return the request handle */ public RequestHandle post(Context context, String url, HttpEntity entity, String contentType, AsyncHttpResponseHandler responseHandler) { return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPost(url), entity), contentType, responseHandler, context); } /** * Perform a HTTP POST request and track the Android Context which initiated * the request. Set headers only for this request * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param headers set headers only for this request * @param params additional POST parameters to send with the request. * @param contentType the content type of the payload you are sending, for * example application/json if sending a json payload. * @param responseHandler the response handler instance that should handle * the response. * @return the request handle */ public RequestHandle post(Context context, String url, Header[] headers, RequestParams params, String contentType, AsyncHttpResponseHandler responseHandler) { HttpEntityEnclosingRequestBase request = new HttpPost(url); if (params != null) request.setEntity(paramsToEntity(params, responseHandler)); if (headers != null) request.setHeaders(headers); return sendRequest(httpClient, httpContext, request, contentType, responseHandler, context); } /** * Perform a HTTP POST request and track the Android Context which initiated * the request. Set headers only for this request * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param headers set headers only for this request * @param entity a raw {@link HttpEntity} to send with the request, for * example, use this to send string/json/xml payloads to a server by * passing a {@link org.apache.http.entity.StringEntity}. * @param contentType the content type of the payload you are sending, for * example application/json if sending a json payload. * @param responseHandler the response handler instance that should handle * the response. * @return the request handle */ public RequestHandle post(Context context, String url, Header[] headers, HttpEntity entity, String contentType, AsyncHttpResponseHandler responseHandler) { HttpEntityEnclosingRequestBase request = addEntityToRequestBase(new HttpPost(url), entity); if (headers != null) request.setHeaders(headers); return sendRequest(httpClient, httpContext, request, contentType, responseHandler, context); } // // HTTP PUT Requests // /** * Perform a HTTP PUT request, without any parameters. * * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle put(String url, AsyncHttpResponseHandler responseHandler) { return put(null, url, null, responseHandler); } /** * Perform a HTTP PUT request with parameters. * * @param url the URL to send the request to. * @param params additional PUT parameters or files to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle put(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return put(null, url, params, responseHandler); } /** * Perform a HTTP PUT request and track the Android Context which initiated the request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param params additional PUT parameters or files to send with the request. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle put(Context context, String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { return put(context, url, paramsToEntity(params, responseHandler), null, responseHandler); } /** * Perform a HTTP PUT request and track the Android Context which initiated the request. * And set one-time headers for the request * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param entity a raw {@link HttpEntity} to send with the request, for example, use this to send string/json/xml payloads to a server by passing a {@link org.apache.http.entity.StringEntity}. * @param contentType the content type of the payload you are sending, for example application/json if sending a json payload. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle put(Context context, String url, HttpEntity entity, String contentType, AsyncHttpResponseHandler responseHandler) { return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPut(url), entity), contentType, responseHandler, context); } /** * Perform a HTTP PUT request and track the Android Context which initiated the request. * And set one-time headers for the request * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param headers set one-time headers for this request * @param entity a raw {@link HttpEntity} to send with the request, for example, use this to send string/json/xml payloads to a server by passing a {@link org.apache.http.entity.StringEntity}. * @param contentType the content type of the payload you are sending, for example application/json if sending a json payload. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle put(Context context, String url, Header[] headers, HttpEntity entity, String contentType, AsyncHttpResponseHandler responseHandler) { HttpEntityEnclosingRequestBase request = addEntityToRequestBase(new HttpPut(url), entity); if (headers != null) request.setHeaders(headers); return sendRequest(httpClient, httpContext, request, contentType, responseHandler, context); } // // HTTP DELETE Requests // /** * Perform a HTTP DELETE request. * * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle delete(String url, AsyncHttpResponseHandler responseHandler) { return delete(null, url, responseHandler); } /** * Perform a HTTP DELETE request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle delete(Context context, String url, AsyncHttpResponseHandler responseHandler) { final HttpDelete delete = new HttpDelete(url); return sendRequest(httpClient, httpContext, delete, null, responseHandler, context); } /** * Perform a HTTP DELETE request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param headers set one-time headers for this request * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle delete(Context context, String url, Header[] headers, AsyncHttpResponseHandler responseHandler) { final HttpDelete delete = new HttpDelete(url); if (headers != null) delete.setHeaders(headers); return sendRequest(httpClient, httpContext, delete, null, responseHandler, context); } /** * Perform a HTTP DELETE request. * * @param context the Android Context which initiated the request. * @param url the URL to send the request to. * @param headers set one-time headers for this request * @param params additional DELETE parameters or files to send along with request * @param responseHandler the response handler instance that should handle the response. * @return the request handle */ public RequestHandle delete(Context context, String url, Header[] headers, RequestParams params, AsyncHttpResponseHandler responseHandler) { HttpDelete httpDelete = new HttpDelete(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); if (headers != null) httpDelete.setHeaders(headers); return sendRequest(httpClient, httpContext, httpDelete, null, responseHandler, context); } /** * Puts a new request in queue as a new thread in pool to be executed. * * @param client HttpClient to be used for request, can differ in single requests * @param httpContext HttpContext in which the request will be executed * @param uriRequest instance of HttpUriRequest, which means it must be of HttpDelete, HttpPost, HttpGet, HttpPut, etc. * @param contentType MIME body type, for POST and PUT requests, may be null * @param responseHandler ResponseHandler or its subclass to put the response into * @param context Context of Android application, to hold the reference of request * @return the request handle */ protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, AsyncHttpResponseHandler responseHandler, Context context) { if (contentType != null) { uriRequest.addHeader("Content-Type", contentType); } Future<?> request = threadPool .submit(new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler)); if (context != null) { // Add request to request map List<WeakReference<Future<?>>> requestList = requestMap.get(context); if (requestList == null) { requestList = new LinkedList<WeakReference<Future<?>>>(); requestMap.put(context, requestList); } requestList.add(new WeakReference<Future<?>>(request)); // TODO: Remove dead weakrefs from requestLists? } return new RequestHandle(request); } /** * Sets state of URL encoding feature, see bug #227, this method * allows you to turn off and on this auto-magic feature on-demand. * * @param enabled desired state of feature */ public void setURLEncodingEnabled(boolean enabled) { this.isUrlEncodingEnabled = enabled; } /** * Will encode url, if not disabled, and adds params on the end of it. * * @param isUrlEncodingEnabled the is url encoding enabled * @param url String with URL, should be valid URL without params * @param params RequestParams to be appended on the end of URL * @return the url with query string */ public static String getUrlWithQueryString(boolean isUrlEncodingEnabled, String url, RequestParams params) { if (isUrlEncodingEnabled) url = url.replace(" ", "%20"); if (params != null) { String paramString = params.getParamString(); if (!url.contains("?")) { url += "?" + paramString; } else { url += "&" + paramString; } } return url; } /** * Returns HttpEntity containing data from RequestParams included with request declaration. * Allows also passing progress from upload via provided ResponseHandler * * @param params additional request params * @param responseHandler AsyncHttpResponseHandler or its subclass to be notified on progress * @return the http entity */ private HttpEntity paramsToEntity(RequestParams params, AsyncHttpResponseHandler responseHandler) { HttpEntity entity = null; try { if (params != null) { entity = params.getEntity(responseHandler); } } catch (Throwable t) { if (responseHandler != null) responseHandler.sendFailureMessage(0, null, null, t); else t.printStackTrace(); } return entity; } /** * Checks if is url encoding enabled. * * @return true, if is url encoding enabled */ public boolean isUrlEncodingEnabled() { return isUrlEncodingEnabled; } /** * Applicable only to HttpRequest methods extending HttpEntityEnclosingRequestBase, which is for example not DELETE. * * @param requestBase HttpRequest instance, must not be null * @param entity entity to be included within the request * @return the http entity enclosing request base */ private HttpEntityEnclosingRequestBase addEntityToRequestBase(HttpEntityEnclosingRequestBase requestBase, HttpEntity entity) { if (entity != null) { requestBase.setEntity(entity); } return requestBase; } /** * Enclosing entity to hold stream of gzip decoded data for accessing HttpEntity contents. */ private static class InflatingEntity extends HttpEntityWrapper { /** * Instantiates a new inflating entity. * * @param wrapped the wrapped */ public InflatingEntity(HttpEntity wrapped) { super(wrapped); } /** * ??TODO * @see org.apache.http.entity.HttpEntityWrapper#getContent() * @author: zhaoqp * @date2013-10-22 ?4:23:15 * @version v1.0 */ @Override public InputStream getContent() throws IOException { return new GZIPInputStream(wrappedEntity.getContent()); } /** * ??TODO * @see org.apache.http.entity.HttpEntityWrapper#getContentLength() * @author: zhaoqp * @date2013-10-22 ?4:23:15 * @version v1.0 */ @Override public long getContentLength() { return -1; } } }