OWADVL
OWADVL

Reputation: 11134

Custom Async Http Client in Android

I use https://github.com/loopj/android-async-http but I think this can be applied to an Async Task (native one)

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {

    @Override
    public void onStart() {
        // called before request is started
       //Some debugging code here
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // called when response HTTP status is "200 OK"
        //here is the interesting part
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
         //Some debugging code here, show retry dialog, feedback etc. 
    }

    @Override
    public void onRetry(int retryNo) {
         //Some debugging code here-------

    }
});

I use it alot in lots of separate classes. The onStart, onFailure and onRetry are the same everywhere, just copy-paste, just the onSuccess is different.

I want to keep my code as clean as possible and to reuse what I've already written, so my question is, how do I make this custom, in a separate "file", and just reuse it. I need just the "OnSuccess" function. Thank you

---------------------------------------

SOLUTION for GET & POST (Thanks to furkan3ayraktar)

1st file RequestListener

package com.classicharmony.krakenmessages.utils.AsyncHttp;
import org.apache.http.Header;
public interface RequestListener {
    public void onSuccess(int statusCode, Header[] headers, byte[] response);
}

2nd file RequestHandler

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.util.Log;


import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import org.apache.http.Header;
import org.apache.http.entity.StringEntity;

import java.io.UnsupportedEncodingException;

public class RequestHandler {

    private static RequestHandler instance;

    private AsyncHttpClient client;
    private static final boolean SHOW_DEBUG_ALERT_DIALOG = true;

    private RequestHandler() {
        client = new AsyncHttpClient();

    }

    public static RequestHandler getInstance() {
        if (instance == null) {
            instance = new RequestHandler();
        }
        return instance;
    }


    public void make_get_Request(final Context context, final String url, final RequestListener listener) {
        client.get(url, new AsyncHttpResponseHandler() {

            @Override
            public void onStart() {
                Log.v("▒▒▒▒▒▒▒ GET ", url);
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] response) {
                listener.onSuccess(statusCode, headers, response);
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
                Log.e("▒▒▒▒▒▒▒ GET FAILED ", url);
                Log.e("▒▒▒▒▒▒▒ GET FAILED ", e.getLocalizedMessage());

                if (DUtils.isDebuggable(context) && SHOW_DEBUG_ALERT_DIALOG) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
                    builder.setTitle("▒▒▒▒▒ ERROR ▒▒▒▒▒");
                    String error_msg;
                    if (errorResponse != null) {
                        try {
                            error_msg = String.valueOf(new String(errorResponse, "UTF-8"));
                        } catch (UnsupportedEncodingException e1) {
                            error_msg = e.getLocalizedMessage();
                        }
                    } else {
                        error_msg = e.getLocalizedMessage();
                    }

                    builder.setMessage(context.getClass().getSimpleName() + " -> " + error_msg)
                            .setCancelable(true)
                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    dialog.dismiss();
                                }
                            });
                    AlertDialog alert = builder.create();
                    alert.show();
                }
            }

            @Override
            public void onRetry(int retryNo) {
                Log.e("▒▒▒▒▒▒▒ RETRYING ", "....." + String.valueOf(retryNo));

            }
        });
    }

    public void make_post_Request(final Context context, final StringEntity entity, final String url, final RequestListener listener) {
        client.post(context, url, entity, "application/json", new AsyncHttpResponseHandler() {

            @Override
            public void onStart() {
                Log.v("▒▒▒▒▒▒▒ POST ", url);
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] response) {
                listener.onSuccess(statusCode, headers, response);
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
                Log.e("▒▒▒▒▒▒▒ POST FAILED ", url);
                Log.e("▒▒▒▒▒▒▒ POST FAILED ", context.getClass().getSimpleName() + " -> " + e.getLocalizedMessage());


                if (DUtils.isDebuggable(context) && SHOW_DEBUG_ALERT_DIALOG) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
                    builder.setTitle("▒▒▒▒▒ ERROR ▒▒▒▒▒");
                    String error_msg;
                    if (errorResponse != null) {
                        try {
                            error_msg = String.valueOf(new String(errorResponse, "UTF-8"));
                        } catch (UnsupportedEncodingException e1) {
                            error_msg = e.getLocalizedMessage();
                        }
                    } else {
                        error_msg = e.getLocalizedMessage();
                    }

                    builder.setMessage(context.getClass().getSimpleName() + " -> " + error_msg)
                            .setCancelable(true)
                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    dialog.dismiss();
                                }
                            });
                    AlertDialog alert = builder.create();
                    alert.show();
                }

            }

            @Override
            public void onRetry(int retryNo) {
                Log.e("▒▒▒▒▒▒▒ RETRYING ", "....." + String.valueOf(retryNo));
            }
        });
    }

}

3rd "utility" to show the dialog or not.

public static boolean isDebuggable(Context ctx) {
    boolean debuggable = false;
    X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US");
    try {
        PackageInfo pinfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNATURES);
        Signature signatures[] = pinfo.signatures;

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        for (int i = 0; i < signatures.length; i++) {
            ByteArrayInputStream stream = new ByteArrayInputStream(signatures[i].toByteArray());
            X509Certificate cert = (X509Certificate) cf.generateCertificate(stream);
            debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN);
            if (debuggable)
                break;
        }
    } catch (PackageManager.NameNotFoundException e) {
        //debuggable variable will remain false
    } catch (CertificateException e) {
        //debuggable variable will remain false
    }
    return debuggable;
}

Example how to call it for POST:

JSONObject jsonParams = new JSONObject();
        StringEntity entity;


        try {
            jsonParams.put("from_user_id", "dan");
            jsonParams.put("to_user_id", "vili");
            jsonParams.put("message", "hello world");
            entity = new StringEntity(jsonParams.toString());
        } catch (JSONException e) {
            e.printStackTrace();
            return;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return;
        }

        RequestHandler handler = RequestHandler.getInstance();
        handler.make_post_Request(getActivity(), entity, "http://your_server/api/etc", new RequestListener() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] response) {
                try {
                    String server_response = String.valueOf(new String(response, "UTF-8"));
                    Log.v("Server response",server_response);
                } catch (UnsupportedEncodingException e1) {

                }
            }
        });

Upvotes: 3

Views: 11160

Answers (3)

Rob Meeuwisse
Rob Meeuwisse

Reputation: 2937

First you make an abstract base class that implements the behavior that is common. Something like this:

public abstract class AsyncHttpResponesHandlerBase implements AsyncHttpResponseHandler {
    @Override
    public void onStart() {
        // called before request is started
        // Some debugging code here
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
        //Some debugging code here, show retry dialog, feedback etc. 
    }

    @Override
    public void onRetry(int retryNo) {
        //Some debugging code here-------
    }
}

Then per url you inherited from the base class and implement the onSuccess() method to handle the response.

public class GoogleGetHandler extends AsyncHttpResponesHandlerBase {
    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // called when response HTTP status is "200 OK"
        // do the Google specific handling
    }
}

And you make the HTTP request as follows:

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new GoogleGetHandler());

So if you want to make calls to more urls, just keep making new subclasses based off of the base class so you inherit the common failure handling.

Upvotes: 2

furkan3ayraktar
furkan3ayraktar

Reputation: 543

Create common request handler and listener. You can also create different request methods like makeRequest for each request you want, and also create different listeners. Here is a simple pattern I mostly use,

public class RequestHandler{

    private static RequestHandler instance;

    private AsyncHttpClient client;

    private RequestHandler(){
        client = new AsyncHttpClient();
    }

    public static RequestHandler getInstance(){
        if(instance == null){
            instance = new RequestHandler();
        }
        return instance;
    }

    // You can add more parameters if you need here.
    public void makeRequest(String url, RequestListener listener){
        client.get(url, new AsyncHttpResponseHandler() {

            @Override
            public void onStart() {
                // called before request is started
                //Some debugging code here
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] response) {
                listener.onSuccess(statusCode, headers, response);
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
                // called when response HTTP status is "4XX" (eg. 401, 403, 404)
                //Some debugging code here, show retry dialog, feedback etc. 
            }

            @Override
            public void onRetry(int retryNo) {
                 //Some debugging code here-------

            }
        });
    }
}

public interface RequestListener{
    public void onSuccess(int statusCode, Header[] headers, byte[] response);
}

Then use as following in anywhere you want.

RequestHandler handler = RequestHandler.getInstance();
handler.makeRequest("http://www.google.com", new RequestListener(){
    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // do whatever you want here.       
    }
});

Upvotes: 1

You could create your own, empty version of AsyncHttpResponseHandler, which doesn't implement the onSuccess method.

public abstract class OWADVLHttpResponseHandler extends AsyncHttpResponseHandler {

    @Override
    public void onStart() {}

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {}

    @Override
    public void onRetry(int retryNo) {}
}

Your code would then look like:

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new OWADVLHttpResponseHandler() {
     @Override
     public void onSuccess(int statusCode, Header[] headers, byte[] response) {
      ....
    }
});

Obviously, you can fill in some contents in the non-overrided methods in the base class.

Upvotes: 2

Related Questions