Android Open Source - NearestRestaurants Http Request






From Project

Back to project page NearestRestaurants.

License

The source code is released under:

Apache License

If you think the Android project NearestRestaurants listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.jiahaoliuliu.nearestrestaurants.session;
//  w  ww  .  jav a2 s.  com
import java.io.ByteArrayOutputStream;
import java.lang.ref.SoftReference;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONObject;

import android.net.Uri;
import android.os.Handler;
import android.util.Log;

import com.jiahaoliuliu.nearestrestaurants.interfaces.RequestDataCallback;
import com.jiahaoliuliu.nearestrestaurants.interfaces.RequestJSONCallback;
import com.jiahaoliuliu.nearestrestaurants.interfaces.RequestStringCallback;
import com.jiahaoliuliu.nearestrestaurants.session.ErrorHandler;
import com.jiahaoliuliu.nearestrestaurants.session.ErrorHandler.RequestStatus;

/**
 * The Request class used to establish REST communication with the server.
 */
public class HttpRequest {

    /**
     * The tag used in logs.
     */
    private static final String LOG_TAG = HttpRequest.class.getSimpleName();

    private static final HashMap<String, String> DEFAULT_HEADER_FIELDS = new HashMap<String, String>();
    private static final HashMap<String, String> DEFAULT_PARAMETERS = null;

    private RequestStatus requestStatus = RequestStatus.REQUEST_OK;

    /**
     * Enumerated data which represents the REST methods used in the Request.
     */
    enum RequestMethod {
        /**
         * Method get.
         */
        RequestMethodGet,
        /**
         * Method post.
         */
        RequestMethodPost,
        /**
         * Method put.
         */
        RequestMethodPut,
        /**
         * Method delete.
         */
        RequestMethodDelete
    }

    /**
     * The uri used to establish the REST communication.
     */
    private Uri uri;

    /**
     * The list of parameters to sent to the server.
     */
    private Map<String, String> parameters;

    private HttpEntity entity;

    /**
     * The request method established.
     */
    private final RequestMethod requestMethod;

    /**
     * The headers used.
     */
    private final Map<String, String> headerFields;

    /**
     * The instance of server Fetcher which is used to communicates with the server.
     */
    private ServerFetcher serverFetcher;

    /**
     * The instance of server Fetcher which is used to communicates with the server.
     */
    private final ExecutorServiceSingleton executorServiceSingleton;


    /**
     * The threadPool which contains all the threads used to communicate with the server.
     */
    private final ExecutorService threadPool;

    /**
     * The handler used to execute all the callbacks in the main thread.
     */
    private final Handler handler;

    /**
     * The main constructor of the class. For other list of parameters, use the method create instead.
     * @param uri           The URI of the server
     * @param parameters    The list of the parameters used
     * @param requestMethod The request method
     */
    private HttpRequest(Uri uri, Map<String, String> headerFields,
          Map<String, String> parameters, HttpEntity entity,
          RequestMethod requestMethod) {

        // If the request method is get, all the parameters is shown in the uri
        this.uri = uri;
        this.parameters = parameters;
        this.entity = entity;
        this.requestMethod = requestMethod;
        // Other data
        this.headerFields = headerFields;

        this.handler = new Handler();
        this.executorServiceSingleton = ExecutorServiceSingleton.instance();
        this.threadPool = executorServiceSingleton.getExecutorService();

    }

    static HttpRequest create(Uri uri, RequestMethod requestMethod) {
      return new HttpRequest(uri, DEFAULT_HEADER_FIELDS, DEFAULT_PARAMETERS, null, requestMethod);
    }
    
    /**
     * The method used to create an instance of HttpRequest
     * @param uri           The URI of the server
     * @param parameters    The list of the parameters used
     * @param requestMethod The request method
     * @return              An instance of HttpRequest
     */
    static HttpRequest create(Uri uri, RequestMethod requestMethod, Map<String, String> parameters) {
      return new HttpRequest(uri, DEFAULT_HEADER_FIELDS, parameters, null, requestMethod);
    }

    /**
     * The method used to create an instance of HttpRequest
     * @param uri           The URI of the server
     * @param headerFields  The header fields created by the called class.
     * @param jsonEntity    The json Entity to send to the server
     * @param requestMethod The request method
     * @return              An instance of HttpRequest
     */
  static HttpRequest create(Uri uri, Map<String, String> headerFields, HttpEntity jsonEntity,
      RequestMethod requestMethod) {
    return new HttpRequest(uri, headerFields, DEFAULT_PARAMETERS, jsonEntity, requestMethod);
  }

  static HttpRequest create(Uri uri, Map<String, String> headerFields, RequestMethod requestMethod) {
    return new HttpRequest(uri, headerFields, DEFAULT_PARAMETERS, null, requestMethod);
  }

  static HttpRequest create(Uri uri, Map<String, String> headerFields, RequestMethod requestMethod, Map<String, String> parameters) {
    return new HttpRequest(uri, headerFields, parameters, null, requestMethod);
  }

    /**
     * Method used to send request to the server, which parse the content returned to a json object.
     * @param jsonHandler The callback to call when the communication finishes.
     */
    protected void performRequestWithJSONHandler(final RequestJSONCallback jsonHandler) {
        /*
         * Add new header
         */
        headerFields.put("Accept", "application/json");

        serverFetcher = new ServerFetcher(requestMethod, uri,
                parameters, entity, headerFields,
                new RequestStringCallback() {

                @Override
                public void done(final String stringObtained, final RequestStatus requestStatus) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            // If there is any data, try to parse it as JSON
                          if (stringObtained != null && !stringObtained.equals("")) {
                              try {
                                  // For latin languages, the codification must be ISO 8859-1(ISO-8859-1)
                                  //http://es.wikipedia.org/wiki/ISO_8859-1
                                  Log.v(HttpRequest.LOG_TAG, stringObtained);
                                  // Parsing json data
                                  // If there is not error, it returns a json object
                                  if (!ErrorHandler.isError(requestStatus)) {
                                    // Check the Result returned by Google
                                    JSONObject jsonObject = new JSONObject(stringObtained);
                                    // Check the status
                                    if (jsonObject.has("status")) {
                                      String resultStatus = jsonObject.getString("status");
                                      
                                      // Check for status code
                                      // If the result status is not ok, then something went wrong
                                      if (!resultStatus.equalsIgnoreCase("OK")) {
                                        Log.e(LOG_TAG, "The result returned is not ok " + resultStatus);
                                        
                                        // Zero results
                                        if (resultStatus.equalsIgnoreCase("ZERO_RESULTS")) {
                                          jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_ZERO_RESULTS);
                                        // Over query limit
                                        } else if (resultStatus.equalsIgnoreCase("OVER_QUERY_LIMIT")) {
                                          jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_OVER_QUERY_LIMIT);
                                        // Request denied
                                        } else if (resultStatus.equalsIgnoreCase("REQUEST_DENIED")) {
                                          jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_REQUEST_DENIED);
                                        // Invalid request
                                        } else if (resultStatus.equalsIgnoreCase("INVALID_REQUEST")) {
                                          // If Request status is REQUEST_OK and the result status is INVALID_REQUEST,
                                          // then the error is because the app is requesting a second page when it is not
                                          // ready. In that case returns a different error
                                            if (requestStatus == RequestStatus.REQUEST_OK) {
                                              jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_DATA_NOT_READY);
                                            } else {
                                              jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_INVALID_REQUEST);
                                            }
                                          // Other errors
                                          } else {  
                                          jsonHandler.done(null, null, RequestStatus.ERROR_SERVER_GENERIC);
                                          }
                                        return;
                                      }
                                      
                                      // if the result is not found, return error
                                      if (!jsonObject.has("results")) {
                                        Log.e(LOG_TAG, "The results does not exist");
                                        jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_DATA_NOT_VALID);
                                        return;
                                      }
                                      
                                      JSONArray jsonArray = new JSONArray(jsonObject.getString("results"));
                                      
                                      // Check for next page token parameter
                                      if (jsonObject.has("next_page_token")) {
                                        String nextPageToken = jsonObject.getString("next_page_token");
                                        jsonHandler.done(jsonArray, nextPageToken, requestStatus);
                                      // If next page token is not found
                                      } else {
                                        jsonHandler.done(jsonArray, null, requestStatus);
                                      }
                                    // if the status does not exists, then there must be some data error
                                    } else {
                                      Log.e(LOG_TAG, "The status does not exist.");
                                      jsonHandler.done(null, null, RequestStatus.ERROR_REQUEST_NOK_DATA_NOT_VALID);
                                    }
                                  } else {
                                    jsonHandler.done(null, null, requestStatus);
                                  }
                              // If there is any problem parsing the server data returned
                              // Return the error about the server data
                              } catch (Exception exception) {
                                  Log.e(LOG_TAG, exception.getLocalizedMessage(), exception);
                                  jsonHandler.done(null, null, RequestStatus.ERROR_SERVER_GENERIC);
                              }
                          } else {
                              jsonHandler.done(null, null, requestStatus);
                          }
                        }
                    });
                }
            });
        threadPool.execute(serverFetcher);
    }

    /**
     * Informs that the request has been finished or not.
     * @return True if the request has been finished.
     *         False otherwise
     */
    protected boolean hasFinished() {
        return (serverFetcher == null || !serverFetcher.isRunning);
    }

    /**
     * Method used to cancel the actual request.
     */
    protected void cancelRequest() {
        if (serverFetcher != null && serverFetcher.isRunning) {
            serverFetcher.stopFetching();
        }

        serverFetcher = null;
    }

    protected Uri getUri() {
        return uri;
    }

    /**
     * The runnable class used to connect with the server.
     */
    private class ServerFetcher implements Runnable {

        /**
         * The tag utilized for the log.
         */
        private static final String LOG_TAG = "ServerFetcher";

        /**
         * The registration time out before it launches the exception.
         */
        private static final int REGISTRATION_TIMEOUT = 3 * 1000;

        /**
         * The wait time out before it launches the exception.
         */
        private static final int WAIT_TIMEOUT = 30 * 1000;

        /**
         * The http client utilized.
         */
        private final HttpClient httpClient = new DefaultHttpClient();

        /**
         * The variable to record the running state (Yes/No).
         */
        private boolean isRunning = false;
        /**
         * The list of parameters of the HTTP client.
         */
        private final HttpParams params = httpClient.getParams();

        /**
         * The http response from the server.
         */
        private HttpResponse response;

        /**
         * The URI to connect.
         */
        private final Uri uri;

        /**
         * The list of parameters that includes in the http request.
         */
        private final Map<String, String> parameters;
        
        private HttpEntity entity;

        /**
         * The headers used.
         */
        private final Map<String, String> headerFields;

        /**
         * The callback to call when the operation finishes.
         */
        private final RequestStringCallback requestStringCallback;


        /**
         *  The final data obtained from the server.
         */
        private String stringObtained;

        /**
         * The main constructor.
         * @param requestMethod The REST method to perform
         * @param uri The Uri of the server to connect
         * @param parameters The list of parameters to be added to the HTTP request
         * @param headerFields The header of the HTTP request
         * @param requestDataCallback The Callback to call when the operation finishes
         */
        ServerFetcher(RequestMethod requestMethod, Uri uri, Map<String,
                String> parameters, HttpEntity entity, Map<String, String> headerFields,
                RequestStringCallback requestStringCallback) {
            this.uri = uri;
            this.parameters = parameters;
            this.entity = entity;
            this.headerFields = headerFields;
            this.requestStringCallback = requestStringCallback;
        }

        /**
         * The method which tells the actual state of the operation.
         * @return True if the server has not returned the response yet
         *         False otherwise
         */
        public boolean isRunning() {
            return isRunning;
        }

        /**
         * This methods stops the communication with the server.
         */
        public void stopFetching() {
            /*
             * TODO Cancel the http request
             */
        }

        @Override
        public void run() {
            Log.v(ServerFetcher.LOG_TAG, ServerFetcher.LOG_TAG + " running");
            isRunning = true;

            try {
                /*
                 * Set the connection parameters
                 */
                HttpConnectionParams.setConnectionTimeout(params, ServerFetcher.REGISTRATION_TIMEOUT);
                HttpConnectionParams.setSoTimeout(params, ServerFetcher.WAIT_TIMEOUT);
                ConnManagerParams.setTimeout(params, ServerFetcher.WAIT_TIMEOUT);

                /*
                 * Create ServerFetcher and prepare the data
                 */
                if (requestMethod == RequestMethod.RequestMethodGet) {
                    HttpGet httpGet = new HttpGet(uri.toString());

                    /*
                     * Add the headers
                     */
                    for (String key : headerFields.keySet()) {
                        httpGet.addHeader(key, headerFields.get(key));
                    }

                    // Check if the entity already exists
                    //Add the values in the parameters
                  String stringUrl = uri.toString();
                    if (parameters != null) {
                      if (!stringUrl.endsWith("?")) {
                        stringUrl += "?";
                      }

                        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                        for (String key : parameters.keySet()) {
                            nameValuePairs.add(new BasicNameValuePair(key, parameters.get(key)));
                        }
                        
                        String paramString = URLEncodedUtils.format(nameValuePairs,"UTF-8");
                        stringUrl += paramString;
                    }
                    httpGet.setURI(new URI(stringUrl));
                    
                    Log.d(LOG_TAG, "HTTPGet. The uri is " + stringUrl);
                    
                    /*
                     * Response from the Http Request
                     */
                    response = httpClient.execute(httpGet);

                } else if (requestMethod == RequestMethod.RequestMethodPost) {
                    HttpPost httpPost = new HttpPost(uri.toString());

                    /*
                     * Add the headers
                     */
                    for (String key : headerFields.keySet()) {
                        httpPost.addHeader(key, headerFields.get(key));
                    }

                    // Check if the entity already exists
                    if (entity != null) {
                      httpPost.setEntity(entity);
                    } else {
                      //Add the values in the parameters
                      if (parameters != null) {
                          List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                          for (String key : parameters.keySet()) {
                              nameValuePairs.add(new BasicNameValuePair(key, parameters.get(key)));
                          }
                          httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
                      }
                    }

                    /*
                     * Response from the Http Request
                     */
                    response = httpClient.execute(httpPost);

                } else if (requestMethod == RequestMethod.RequestMethodPut) {
                  HttpPut httpPut = new HttpPut(uri.toString());
                    /*
                     * Add the headers
                     */
                    for (String key : headerFields.keySet()) {
                      httpPut.addHeader(key, headerFields.get(key));
                    }

                    // Check if the entity already exists
                    if (entity != null) {
                      httpPut.setEntity(entity);
                    } else {
                      //Add the values in the parameters
                      if (parameters != null) {
                          List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                          for (String key : parameters.keySet()) {
                              nameValuePairs.add(new BasicNameValuePair(key, parameters.get(key)));
                          }
                          httpPut.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
                      }
                    }

                    //Send the http put
                    response = httpClient.execute(httpPut);
                } else if (requestMethod == RequestMethod.RequestMethodDelete) {
                  HttpDelete httpDelete = new HttpDelete(uri.toString());
                    /*
                     * Add the headers
                     */
                    for (String key : headerFields.keySet()) {
                      httpDelete.addHeader(key, headerFields.get(key));
                    }

                    // Sending the request to the server
                    response = httpClient.execute(httpDelete);
                }

                StatusLine statusLine = response.getStatusLine();
                Log.v(ServerFetcher.LOG_TAG, "Status code " + statusLine.getStatusCode());

                int responseCode = statusLine.getStatusCode();
                if (responseCode == HttpStatus.SC_OK){
                    // Get the returned data
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    response.getEntity().writeTo(out);
                    out.close();
                    stringObtained = out.toString("UTF8");

                    if (responseCode == HttpStatus.SC_OK) {
                        requestStatus = RequestStatus.REQUEST_OK;
                    // For the rest of the cases, there is an error.
                    } else {
                      requestStatus = RequestStatus.ERROR_REQUEST_NOK;
                    }
                } else {
                    requestStatus = RequestStatus.ERROR_REQUEST_NOK;
                }
            } catch (HttpHostConnectException httpHostConnectException) {
              Log.e(LOG_TAG, httpHostConnectException.getLocalizedMessage(), httpHostConnectException);
              requestStatus = RequestStatus.ERROR_REQUEST_NOK_HTTP_NO_CONNECTION;
            } catch (ConnectTimeoutException connectTimeoutException) {
              Log.e(LOG_TAG, connectTimeoutException.getLocalizedMessage(), connectTimeoutException);
              requestStatus = RequestStatus.ERROR_REQUEST_NOK_HTTP_NO_CONNECTION;
            } catch (UnknownHostException unknownHostException) {
              Log.e(LOG_TAG, unknownHostException.getLocalizedMessage(), unknownHostException);
              requestStatus = RequestStatus.ERROR_REQUEST_NOK_HTTP_NO_CONNECTION;
            } catch (Exception e) {
                Log.e(LOG_TAG, "Error requesting data to the backend. " + uri.toString(), e);
                requestStatus = RequestStatus.ERROR_REQUEST_NOK;
            } finally {
                isRunning = false;
                if (requestStringCallback != null) {
                  requestStringCallback.done(stringObtained, requestStatus);
                }
            }
        }
    }

    /**
     * The class which creates the threadPool as singleton.
     */
    private static final class ExecutorServiceSingleton {

        /**
         * The number of the threads which are running in parallel.
         */
        private static final int MAXIMUM_NUM_RUNNING_THREAD = 4;

        /**
         * A class to hold the singleton.
         */
        private static class SingletonHolder {
            /**
             * The instance of the class.
             */
            private static final ExecutorServiceSingleton INSTANCE = new ExecutorServiceSingleton();
        }

        /**
         * Creates the executor server as soft reference.
         */
        private SoftReference<ExecutorService> executorServiceReference = new SoftReference<ExecutorService>(
                createExecutorService());

        /**
         * The empty constructor of the class.
         */
        private ExecutorServiceSingleton() {
        };

        /**
         * The public method to return the instance.
         * @return A instance of the Singleton holder
         */
        static ExecutorServiceSingleton instance() {
            return SingletonHolder.INSTANCE;
        }

        /**
         * Method used to get the executor service.
         * @return The executor service. Create it if it has not been created before
         */
        ExecutorService getExecutorService() {
            ExecutorService executorService = executorServiceReference.get();

            if (executorService == null) {
                // (the reference was cleared)
                executorService = createExecutorService();
                executorServiceReference = new SoftReference<ExecutorService>(executorService);
            }

            return executorService;
        }

        /**
         * The method which creates a threadPool with limit number of threads.
         * Those threads will be re-utilized and they should exist while the application is running.
         * @return A threadPool with always same number of threads
         */
        private ExecutorService createExecutorService() {
            return Executors.newFixedThreadPool(ExecutorServiceSingleton.MAXIMUM_NUM_RUNNING_THREAD);
        }
    }
}




Java Source Code List

com.jiahaoliuliu.nearestrestaurants.NearestRestaurantsListFragment.java
com.jiahaoliuliu.nearestrestaurants.NearestRestaurantsMapFragment.java
com.jiahaoliuliu.nearestrestaurants.NearestRestaurants.java
com.jiahaoliuliu.nearestrestaurants.RestaurantListAdapter.java
com.jiahaoliuliu.nearestrestaurants.interfaces.Callback.java
com.jiahaoliuliu.nearestrestaurants.interfaces.ErrorCallback.java
com.jiahaoliuliu.nearestrestaurants.interfaces.OnPositionRequestedListener.java
com.jiahaoliuliu.nearestrestaurants.interfaces.OnProgressBarShowRequestListener.java
com.jiahaoliuliu.nearestrestaurants.interfaces.OnRefreshRequestedListener.java
com.jiahaoliuliu.nearestrestaurants.interfaces.OnUpdatePositionListener.java
com.jiahaoliuliu.nearestrestaurants.interfaces.RequestDataCallback.java
com.jiahaoliuliu.nearestrestaurants.interfaces.RequestJSONCallback.java
com.jiahaoliuliu.nearestrestaurants.interfaces.RequestRestaurantsCallback.java
com.jiahaoliuliu.nearestrestaurants.interfaces.RequestStringCallback.java
com.jiahaoliuliu.nearestrestaurants.models.Restaurant.java
com.jiahaoliuliu.nearestrestaurants.session.ErrorHandler.java
com.jiahaoliuliu.nearestrestaurants.session.HttpRequest.java
com.jiahaoliuliu.nearestrestaurants.session.Preferences.java
com.jiahaoliuliu.nearestrestaurants.session.RestaurantDBAdapter.java
com.jiahaoliuliu.nearestrestaurants.session.Service.java
com.jiahaoliuliu.nearestrestaurants.session.Session.java
com.jiahaoliuliu.nearestrestaurants.utils.Connectivity.java
com.jiahaoliuliu.nearestrestaurants.utils.PositionTracker.java