Shantanu Paul
Shantanu Paul

Reputation: 705

How can I split the logic of HttpUrlConnection into multiple methods?

I have multiple Activities each of which gets different data from different URLs and different HTTP methods like POST, GET, PUT, DELETE, etc. Some requests have header data while some have Body, some may have both. I am using a single AsyncTask class with multiple constructors to pass data from the Activities such that I can add them to the HttpUrlConnection instance.

I tried this tutorial: http://cyriltata.blogspot.in/2013/10/android-re-using-asynctask-class-across.html.

But the above tutorial uses HttpClient and NameValuePair. I replaced NameValuePair with Pair. But I am finding it difficult to implement the same logic using HttpUrlConnection as I need to add multiple POST data and headers to my request.

But the String returned is empty. How do I implement this scenario properly?

Full code:

public class APIAccessTask extends AsyncTask<String,Void,String> {
URL requestUrl;
Context context;
HttpURLConnection urlConnection;
List<Pair<String,String>> postData, headerData;
String method;
int responseCode = HttpURLConnection.HTTP_NOT_FOUND;


APIAccessTask(Context context, String requestUrl, String method){
    this.context = context;
    this.method = method;
    try {
        this.requestUrl = new URL(requestUrl);
    }
    catch(Exception ex){
        ex.printStackTrace();
    }
 }


APIAccessTask(Context context, String requestUrl, String method,    List<Pair<String,String>> postData,){
    this(context, requestUrl, method);
    this.postData = postData;
}

APIAccessTask(Context context, String requestUrl, String method, List<Pair<String,String>> postData,
              List<Pair<String,String>> headerData){
    this(context, requestUrl,method,postData);
    this.headerData = headerData;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
}

@Override
protected String doInBackground(String... params) {

    setupConnection();

    if(method.equals("POST"))
    {
        return httpPost();
    }

    if(method.equals("GET"))
    {
        return httpGet();
    }

    if(method.equals("PUT"))
    {
        return httpPut();
    }

    if(method.equals("DELETE"))
    {
        return httpDelete();
    }
    if(method.equals("PATCH"))
    {
        return httpPatch();
    }

    return null;
}

@Override
protected void onPostExecute(String result) {
    Toast.makeText(context,result,Toast.LENGTH_LONG).show();
    super.onPostExecute(result);
}

void setupConnection(){
    try {
        urlConnection = (HttpURLConnection) requestUrl.openConnection();
        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.setChunkedStreamingMode(0);
        if(headerData != null){
            for (Pair pair: headerData)
            {
                urlConnection.setRequestProperty(pair.first.toString(), Base64.encodeToString(pair.second.toString().getBytes(),Base64.DEFAULT));
            }
        }
    }
    catch(Exception ex) {
        ex.printStackTrace();
    }

}

private String httpPost(){
    try{
        urlConnection.setRequestMethod("POST");
    }
    catch (Exception ex){
        ex.printStackTrace();

    return stringifyResponse();
}

String httpGet(){

    try{
        urlConnection.setRequestMethod("GET");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();
}

String httpPut(){

    try{
        urlConnection.setRequestMethod("PUT");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();
}

String httpDelete(){
    try{
        urlConnection.setRequestMethod("DELETE");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();

}

String httpPatch(){
    try{
        urlConnection.setRequestMethod("PATCH");
    }
    catch (Exception ex){
        ex.printStackTrace();
    }
    return stringifyResponse();

}

String stringifyResponse() {

    StringBuilder sb = new StringBuilder();
    try {
        OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
        writer.write(getQuery(postData));
        writer.flush();
        writer.close();
        out.close();

        urlConnection.connect();
        responseCode = urlConnection.getResponseCode();
        if (responseCode == 200) {
            InputStream in = new BufferedInputStream(urlConnection.getInputStream());
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String line = null;

            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        }

    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return sb.toString();
}


private String getQuery(List<Pair<String,String>> params) throws UnsupportedEncodingException{
    Uri.Builder builder = null;
    for (Pair pair : params)
    {
         builder = new Uri.Builder()
                .appendQueryParameter(pair.first.toString(), pair.second.toString());
                }
    return builder.build().getEncodedQuery();
}
}

Upvotes: 5

Views: 1870

Answers (2)

abidfs
abidfs

Reputation: 49

Lets apply some oops concepts here
Have a class HttpCommunication with will purely take care of sending the request and getting the response back from server. Sample code for which is as follows

package com.example.sample;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

public class HttpCommunication {
    public String makeHttpRequest( String url, HttpMethods method, ArrayList< NameValuePair > requestParams, ArrayList< NameValuePair > postData ) throws Exception {

        InputStream inputStream = null;
        String response = "";
        HttpParams httpParameters = new BasicHttpParams( );

        /**
         * Set the timeout in milliseconds until a connection is established. The default value is
         * zero, that means the timeout is not used.
         */
        int timeoutConnection = 15000;
        HttpConnectionParams.setConnectionTimeout( httpParameters, timeoutConnection );

        /**
         * Set the default socket timeout (SO_TIMEOUT) in milliseconds which is the timeout for
         * waiting for data.
         */
        int timeoutSocket = 15000;
        HttpConnectionParams.setSoTimeout( httpParameters, timeoutSocket );

        DefaultHttpClient httpClient = new DefaultHttpClient( httpParameters );

        /**
         * Check for request method
         */
        if ( method == HttpMethods.POST ) {
            HttpPost httpPost = new HttpPost( url );

            if ( requestParams != null && requestParams.size( ) > 0 ) {
                httpPost.setEntity( new UrlEncodedFormEntity( requestParams ) );
            }

            HttpResponse httpResponse = httpClient.execute( httpPost );
            HttpEntity httpEntity = httpResponse.getEntity( );
            inputStream = httpEntity.getContent( );

        } else if ( method == HttpMethods.GET ) {
            if ( requestParams != null && requestParams.size( ) > 0 ) {
                String paramString = URLEncodedUtils.format( requestParams, "utf-8" );
                url += "?" + paramString;
            }

            HttpGet httpGet = new HttpGet( url );

            HttpResponse httpResponse = httpClient.execute( httpGet );
            HttpEntity httpEntity = httpResponse.getEntity( );
            inputStream = httpEntity.getContent( );
        }

        BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream, "UTF-8" ) );
        StringBuilder sb = new StringBuilder( );
        String line = null;
        while ( ( line = reader.readLine( ) ) != null ) {
            sb.append( line + "\n" );
        }
        inputStream.close( );
        response = sb.toString( );

        return response;
    }
}

Have an abstract base class which will act as a template for all underlying webservices in your application. This class will use above HttpCommunication class to send the request. The requests will be sent from AsyncTask hence it is completely asynchronous. The class will provide abstract methods which derived classes must override and provide definitions for;
1. getUrl() - The well formatted request url
2. getHttpMethod() - One of the HTTP method from GET, POST, PUT, DELETE, PATCH
3. getRequestParams() - The request params (headers) if any.
4. getPostParams() - The post params if any.
5. parseResponse(String) - The derived classes must give definition of this method to parse the received response.
6. notifyError(int) - The derived classes must give definition of this method to process the error that might be received in communication.

package com.example.sample;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import android.os.AsyncTask;
/**
 * This class is an abstract base class for all web services.
 */
public abstract class BaseService {
    protected abstract String getUrl();
    protected abstract HttpMethods getHttpMethod();
    protected abstract ArrayList< NameValuePair > getRequestParams();
    protected abstract ArrayList< NameValuePair > getPostParams();
    protected abstract void parseResponse( String response );
    protected abstract void notifyError( int errorCode );

    public void send() {
        SendRequestTask sendRequestTask = new SendRequestTask( );
        sendRequestTask.execute( );
    }

    private class SendRequestTask extends AsyncTask< Void, Void, Integer > {
        @Override
        protected Integer doInBackground( Void... params ) {
            try {
                String url = getUrl( );
                HttpMethods method = getHttpMethod( );
                ArrayList< NameValuePair > httpParams = getRequestParams( );
                ArrayList< NameValuePair > postParams = getPostParams( );

                HttpCommunication httpCommunication = new HttpCommunication( );
                String response = httpCommunication.makeHttpRequest( url, method, httpParams, postParams );

                parseResponse( response );
            } catch ( Exception ex ) {
                ex.printStackTrace( );
                notifyError( CommunicationError.ERROR_COMMUNICATION );
            }
            return 0;
        }
    }
}

Here is the code for sample webservice class which is derived from above class;

package com.example.sample;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
/**
 * This is a web service class to login.
 */
public class SignIn extends BaseService {
    private final String _emailId;
    private final String _password;
    private final String _signinUrl = "http://www.example.com/login.php";

    public SignIn( String userName, String password ) {
        _emailId = userName;
        _password = null;
    }

    @Override
    protected String getUrl() {
        return _signinUrl;
    }

    @Override
    protected ArrayList< NameValuePair > getRequestParams() {
        ArrayList< NameValuePair > params = new ArrayList< NameValuePair >( );
        params.add( new BasicNameValuePair( "header1", "header1" ) );
        params.add( new BasicNameValuePair( "header2", "header2" ) );
        return params;
    }

    @Override
    protected ArrayList< NameValuePair > getPostParams() {
        ArrayList< NameValuePair > params = new ArrayList< NameValuePair >( );
        params.add( new BasicNameValuePair( "email", _emailId ) );
        params.add( new BasicNameValuePair( "password", _password ) );
        return params;
    }

    @Override
    protected HttpMethods getHttpMethod() {
        return HttpMethods.POST;
    }

    @Override
    protected void parseResponse( String response ) {
        // Parse the response here
    }

    @Override
    protected void notifyError( int errorCode ) {
        // Notify error to application
    }
}

Here is how you can use the SignIn webservice;

SignIn signIn = new SignIn("[email protected]", "abc123");
signIn.send();

Please modify your HttpCommunication class as follows.

package com.example.sample;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import org.apache.http.NameValuePair;

public class HttpCommunication {
    private final int CONNECTION_TIMEOUT = 10 * 1000;

    /**
     * Default Constructor
     */
    public HttpCommunication() {

    }

    public String makeHttpRequest( String strUrl, HttpMethods method, ArrayList< NameValuePair > requestParams, ArrayList< NameValuePair > postData ) throws Exception {

        HttpURLConnection connection = null;
        InputStream inputStream = null;
        URL url = null;
        String response = null;
        try {
            url = new URL( strUrl );
            connection = (HttpURLConnection) url.openConnection( );
            connection.setConnectTimeout( CONNECTION_TIMEOUT );
            connection.setReadTimeout( CONNECTION_TIMEOUT );

            if ( requestParams != null && requestParams.size( ) > 0 ) {
                for ( NameValuePair pair : requestParams ) {
                    connection.setRequestProperty( pair.getName( ), pair.getValue( ) );
                }
            }

            connection.setDoInput( true );
            connection.connect( );
            if ( method == HttpMethods.POST ) {
                OutputStream os = connection.getOutputStream( );
                // Convert post data to string and then write it to outputstream.
                String postDataStr = "test";
                os.write( postDataStr.getBytes( ) );
                os.close( );
            }

            inputStream = connection.getInputStream( );

            if ( inputStream != null ) {
                BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream, "UTF-8" ) );
                StringBuilder sb = new StringBuilder( );
                String line = null;
                while ( ( line = reader.readLine( ) ) != null ) {
                    sb.append( line + "\n" );
                }
                response = sb.toString( );
                inputStream.close( );
            }
            connection.disconnect( );
        } catch ( Exception e ) {
            if ( connection != null ) {
                connection.disconnect( );
            }
        }

        return response;
    }
}

Upvotes: 1

BNK
BNK

Reputation: 24114

IMO, you can refer to my following sample code:

   /**         
     * HTTP request using HttpURLConnection
     *
     * @param method
     * @param address
     * @param header
     * @param mimeType
     * @param requestBody
     * @return
     * @throws Exception
     */
    public static URLConnection makeURLConnection(String method, String address, String header, String mimeType, String requestBody) throws Exception {
        URL url = new URL(address);

        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(!method.equals(HTTP_METHOD_GET));
        urlConnection.setRequestMethod(method);

        if (isValid(header)) {   // let's assume only one header here             
            urlConnection.setRequestProperty(KEYWORD_HEADER_1, header);
        }

        if (isValid(requestBody) && isValid(mimeType) && !method.equals(HTTP_METHOD_GET)) {
            urlConnection.setRequestProperty(KEYWORD_CONTENT_TYPE, mimeType);
            OutputStream outputStream = new BufferedOutputStream(urlConnection.getOutputStream());
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8");
            writer.write(requestBody);
            writer.flush();
            writer.close();
            outputStream.close();
        }

        urlConnection.connect();

        return urlConnection;
    }

the requestBody is made by using the following method:

    public static String buildRequestBody(Object content) {
        String output = null;
        if ((content instanceof String) ||
                (content instanceof JSONObject) ||
                (content instanceof JSONArray)) {
            output = content.toString();
        } else if (content instanceof Map) {
            Uri.Builder builder = new Uri.Builder();
            HashMap hashMap = (HashMap) content;
            if (isValid(hashMap)) {
                Iterator entries = hashMap.entrySet().iterator();
                while (entries.hasNext()) {
                    Map.Entry entry = (Map.Entry) entries.next();
                    builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString());
                    entries.remove(); // avoids a ConcurrentModificationException
                }
                output = builder.build().getEncodedQuery();
            }
        } else if (content instanceof byte[]) {
            try {
                output = new String((byte[]) content, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        return output;
    }
}

Then, in your AsyncTask class, you can call:

       String url = "http://.......";
       HttpURLConnection urlConnection;
       Map<String, String> stringMap = new HashMap<>();           
       stringMap.put(KEYWORD_USERNAME, "bnk");
       stringMap.put(KEYWORD_PASSWORD, "bnk123");
       String requestBody = buildRequestBody(stringMap);
       try {
           urlConnection = (HttpURLConnection) Utils.makeURLConnection(HTTP_METHOD_POST, url, null, MIME_FORM_URLENCODED, requestBody);               
           if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
               // do something...
           } else {
               // do something...
           }
           ...
       } catch (Exception e) {
           e.printStackTrace();
       }

or

       String url = "http://.......";
       HttpURLConnection urlConnection;
       JSONObject jsonBody;                      
       String requestBody;
       try {
           jsonBody = new JSONObject();
           jsonBody.put("Title", "Android Demo");
           jsonBody.put("Author", "BNK");
           requestBody = Utils.buildRequestBody(jsonBody);
           urlConnection = (HttpURLConnection) Utils.makeURLConnection(HTTP_METHOD_POST, url, null, MIME_JSON, requestBody);               
           if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
               // do something...
           } else {
               // do something...
           }
           ...
       } catch (Exception e) {
           e.printStackTrace();
       }

Upvotes: 1

Related Questions