Codepath

Using CodePath Async Http Client

Overview

CodePath built a simple lightweight library to make it easy to send and parse network requests. The goal of this library is to have an API that clearly and cleanly supports the following features:

  • Asynchronous network requests without any need for manual thread handling
  • Response onSuccess callbacks run on the mainthread (by default)
  • Easy way to catch all errors and failures and handle them
  • Easy pluggable Text, JSON, and Bitmap response handlers to parse the response

This client tries to follow a similar API inspired by this older now deprecated android-async-http library.

Setup

To use this library, add the following dependency into our app/build.gradle file:

dependencies {
  implementation 'com.codepath.libraries:asynchttpclient:2.2.0'
}

Sending a Network Request

Now, we just create an AsyncHttpClient, and then execute a request specifying an anonymous class as a callback:

import com.codepath.asynchttpclient.AsyncHttpClient;

AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("limit", "5");
params.put("page", "0");
client.get("https://api.thecatapi.com/v1/images/search", params, new TextHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Headers headers, String response) {
            // called when response HTTP status is "200 OK"
        }

        @Override
        public void onFailure(int statusCode, Headers headers, String errorResponse, Throwable t) {
            // called when response HTTP status is "4XX" (eg. 401, 403, 404)
        }	
    }
);
val client = AsyncHttpClient()
val params = RequestParams()
params["limit"] = "5"
params["page"] = "0"
client["https://api.thecatapi.com/v1/images/search", params, object :
    TextHttpResponseHandler() {
    override fun onSuccess(statusCode: Int, headers: Headers, response: String) {
        // called when response HTTP status is "200 OK"
    }

    override fun onFailure(
        statusCode: Int,
        headers: Headers?,
        errorResponse: String,
        t: Throwable?
    ) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
    }
}]

This will automatically execute the request asynchronously and fire the onSuccess when the response returns a success code and onFailure if the response does not.

Sending a JSON Request

Similar to sending a regular HTTP request, this library can also be used for sending JSON API requests:

RequestParams params = new RequestParams();
params.put("limit", "5");
params.put("page", "0");

client.get("https://api.thecatapi.com/v1/images/search", params, new JsonHttpResponseHandler() {
   @Override
   public void onSuccess(int statusCode, Headers headers, JSON json) {
         // Access a JSON array response with `json.jsonArray` 
         Log.d("DEBUG ARRAY", json.jsonArray.toString());
         // Access a JSON object response with `json.jsonObject` 
         Log.d("DEBUG OBJECT", json.jsonObject.toString());
   }

   @Override
   public void onFailure(int statusCode, Headers headers, String response, Throwable throwable) {

   }
});
val params = RequestParams()
params["limit"] = "5"
params["page"] = "0"

client["https://api.thecatapi.com/v1/images/search", params, object :
    JsonHttpResponseHandler() {
    override fun onSuccess(statusCode: Int, headers: Headers, json: JSON) {
        // Access a JSON array response with `json.jsonArray` 
        Log.d("DEBUG ARRAY", json.jsonArray.toString())
        // Access a JSON object response with `json.jsonObject` 
        Log.d("DEBUG OBJECT", json.jsonObject.toString())
    }

    override fun onFailure(
        statusCode: Int,
        headers: Headers?,
        response: String,
        throwable: Throwable?
    ) {
    }
}]

Assuming the callback uses JsonHttpResponseHandler, the request will be sent out with the appropriate parameters passed in the query string and then the response can be parsed as JSON and made available within onSuccess.

The JSON returned can be either an Array or an Object, and you can access them with .jsonArray and .jsonObject respectively depending on the root JSON content of the response. Check the Converting JSON to Models guide for more details on parsing a JSON response manually.

Sending an Authenticated API Request

API requests tend to be JSON or XML responses that are sent to a server and then the result needs to be parsed and processed as data models on the client. In addition, many API requests require authentication in order to identify the user making the request. This is typically done with a standard OAuth process for authentication.

Fortunately, there are several OAuth libraries out there to simplify the process of authentication such as scribe and signpost. You can explore several examples of using scribe or signpost to authenticate.

We have also created a meta-library to make this process as simple as possible called android-oauth-handler and a skeleton app to act as a template for a simple rest client called android-rest-client-template. You can see the details of these libraries by checking out their respective READMEs.

Using these wrappers, you can then send an API request and properly process the response using code like this:

// SomeActivity.java
RestClient client = RestClientApp.getRestClient();
RequestParams params = new RequestParams();
params.put("key", "value");
params.put("more", "data");
client.getHomeTimeline(1, new JsonHttpResponseHandler() {
    public void onSuccess(int statusCode, Headers headers, JSON json) {
        // Response is automatically parsed into a JSONArray
        // json.jsonObject.getLong("id");
        // Here we want to process the json data into Java models.
    }
 

   public void onFailure(int statusCode, Headers headers, String responseString, Throwable t)  {
    // Handle the failure and alert the user to retry
    Log.e("ERROR", responseString);
  }
});
client.getHomeTimeline(1, object : JsonHttpResponseHandler() {
    override fun onSuccess(statusCode: Int, headers: Headers, json: JSON) {
        // Response is automatically parsed into a JSONArray
        // json.jsonObject.getLong("id");
        // Here we want to process the json data into Java models.
    }

    override fun onFailure(
        statusCode: Int,
        headers: Headers?,
        responseString: String,
        t: Throwable?
    ) {
        // Handle the failure and alert the user to retry
        Log.e("ERROR", responseString)
    }
})

Advanced Usage

This library also exposes the ability to send multipart forms and receive images by the examples shown here.

Fork me on GitHub