Sunday, August 11, 2013

Volley - Demo - Part 1

An demonstration of Volley - HTTP library announced by google in I/O 2013.

Why Volley?
Android has provided two HTTP Clients AndroidHttpClient (Extended from apache HTTPClient) and HttpUrlConnection to make a HTTP Request. Both has its own pros and cons. When an application is developed, we write HTTP connection classes which handles all the HTTP requests, creating THREADS to run in background, managing THREAD pool, response parsing, response caching, handling error codes, SSL connections, running requests in parallel and others stuffs around that. Every developer has his own way of implementing these functionalities.Some might use AsycnTask for running network operations in background, or some might use passing handlers created from UI thread to HTTP connection classes which then executes network operation in worker thread and uses the handler to pass back the parsed HTTP response back to the main thread.

But we end up writing same boilerplate codes repeatedly and we try to reinvent the wheel in our application development.

For example, in the below snippet, a HTTP request is made in the AysncTask's doBackground method. When the response is obtained, data is copied from HttpUrlConnection's InputStream to OutputStream and then it tries to convert the string obtained from outputStream to JSONObject which is our final response. On the course, all the necessary try, catch block is handled. All these boilerplate codes are repeated throughout our code.


HttpURLConnection urlConnection = null;
try {
   URL url = new URL("http://www.android.com/");
   urlConnection = (HttpURLConnection) url.openConnection();
   InputStream in = new BufferedInputStream(urlConnection.getInputStream());
   ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
   byte[] buffer = new byte[1024]; // Adjust if you want
   int bytesRead;
   while ((bytesRead = in.read(buffer)) != -1) {
     outputStream.write(buffer, 0, bytesRead);
   }
   JSONObject resultJSON = new JSONObject(outputStream.toString());

}catch (Exception e) {
       e.printStackTrace();
} finally {
     urlConnection.disconnect();
}


Google has come up with Volley interface which helps developers to handle all the network related operations so that developers can concentrate implementing the business logic after the HTTP response is obtained.Also having less code for network calls helps developer reduce number of bugs.

NOTE Volley is not good for larger file download/upload operations as well video streaming operations.

Key features of the Volley are below

* Develop Super fast networked applications for android.
* Schedules all your HTTP requests running them parallely in background threads and manages those threads.
* Gives you flexible ways to run your networking requests concurrently with synchronization.
* Comes with inbuilt JSON parsing the response.
* Set prioirty for requests.
* Retry policy for timeout,certain ERROR codes as Internal Server error.
* Flexible Request cancellations.
* Memory & Disk Caching for images.Batch dispatch to Image Downloads.
* Flexible in giving your own cache implementations.
* You can include your own HTTPStack ( to handle SSL connections, PATCH requests ).
* Effective inbuilt cache - control to handle response caching.
* Request tracing for debugging.
* Excels in the way responses are given back to you.

Integrating Volley to your project.

You can include in two ways
1- Create Volley.jar and include as jar dependency to your project.
2- Include the volley project as Library Dependency in your project.

Clone the Volley project from below git repo. https://android.googlesource.com/platform/frameworks/volley/)

Creating Volley.jar
Import the project into eclipse.
$ cd volley
$ android update project -p . (Generate local.properties file )
$ ant jar
Right click on build.xml file and ‘Run as Ant Task’ , volley.jar would be created in /bin folder.

Library Dependency
Edit the project.properties file and the add the below line
android.library=true
Now right click on your project--> Properties--> Android --> Under Library section, choose ‘Add’ and select ‘Volley’ project as library dependency to your project.

Using Volley involves two main classes RequestQueue and Request.

RequestQueue - Dispatch Queue which takes a Request and executes in a worker thread or if cache found its takes from cache and responds back to the UI main thread.

Request - All network(HTTP) requests are created from this class. It takes main parameters required for a HTTP request like
- METHOD Type - GET, POST, PUT, DELETE
- URL
- Request data (HTTP Body)
- Successful Response Listener
- Error Listener


Volley Provides two specific implementations of Request.

* JsonObjectRequest
* StringRequest

Initialise RequestQueue
mVolleyQueue = Volley.newRequestQueue(this);

You can create a instance of RequestQueue by passing any Object to the static method newRequestQueue of Volley Class. In this case, activity instance this is passed to create the instance. Similarly while cancelling all the requests dispatched in this RequestQueue we should be using activity instance to cancel the requests.

JsonObjectRequest
Creates HTTP request which helps in connecting to JSON based response API's. Takes parameters as
- HTTP METHOD
- A JSON object as request body ( mostly for POST & PUT api's)
- Success & Error Listener.
- Volley parses the HTTP Response to a JSONObject for you. If your server api's are JSON based, you can straightway go ahead and use JsonObjectRequest

The Content-Type for this request is always set to application/json

String url = "";

JsonObjectRequest jsonObjRequest = new JsonObjectRequest(Request.Method.GET,
                            url, null, 
                            new Response.Listener() {
    @Override
    public void onResponse(JSONObject response) {
    }
}, new Response.ErrorListener() {

    @Override
    public void onErrorResponse(VolleyError error) {
    }
});

mVolleyQueue.add(jsonObjRequest);


StringRequest
To obtain the HTTP Response as a String, create HTTP Request using StringRequest Takes parameters as
- HTTP METHOD
- Success & Error Listener.
String url = "";

StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener() {
    @Override
    public void onResponse(String response) {
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
    }
});

mVolleyQueue.add(stringRequest);


GsonRequest
You can customize the Request to make a new type of Request which can give the response in Java Class Object. GSON is a library which is used in converting JSON to Java Class Objects and vice-versa. You write custom request which takes Java Class name as a parameter and return the response in that Class Object.

You should include gson.jar as JAR dependency in your project.
public class GsonRequest extends Request{
private Gson mGson;

public GsonRequest(int method, String url, Class cls, String requestBody, Listener listener,
      ErrorListener errorListener) {
      super(method, url, errorListener);
      mGson = new Gson();        
}

@Override
protected Response parseNetworkResponse(NetworkResponse response) {
     try {
      String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
          T parsedGSON = mGson.fromJson(jsonString, mJavaClass);
      return Response.success(parsedGSON,
        HttpHeaderParser.parseCacheHeaders(response));

      } catch (UnsupportedEncodingException e) {
         return Response.error(new ParseError(e));
      } catch (JsonSyntaxException je) {
         return Response.error(new ParseError(je));
      }
}
}        

Using GsonRequest
Takes FlickrResponsePhotos class as parameter and returns the response as FlickrResponsePhotos Object. Makes life easier for developers if you have the response in your desired Class objects.
gsonObjRequest = new GsonRequest(Request.Method.GET, url,
        FlickrResponsePhotos.class, null, new Response.Listener() {
    @Override
    public void onResponse(FlickrResponsePhotos response) {
    }
}, new Response.ErrorListener() {

    @Override
    public void onErrorResponse(VolleyError error) {
    }
});
mVolleyQueue.add(gsonObjRequest);


Image Download
Most common operation in an application is Image download operation. Volley provides different ways of downloading a image.
ImageRequest
Just like other Request types, ImageRequest takes a URL as paramater and returns Bitmap as response on the main threa.
ImageRequest imgRequest = new ImageRequest(, new Response.Listener() {
        @Override
        public void onResponse(Bitmap response) {
            mImageView.setImageBitmap(response);
        }
    }, 0, 0, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            mImageView.setImageResource(R.drawable.error);
        }
    });
mVolleyQueue.add(imgRequest);

ImageDownloader
Handles loading and caching of images from a URL.Takes URL, ImageView and ImageListener as parameters.Need to initialies the ImageLoader with a cache. Cache can be of two types MemoryCache ( or ) DiskCache. Volley provides a DiskCache implementation DiskBasedCache.You can always use that. If you need to provide your own cache implementation for ImageDownLoader you need to implement the interface ImageCache.
//Initialising ImageDownloader
int max_cache_size = 1000000;
mImageLoader = new ImageLoader(mVolleyQueue, new DiskBitmapCache(getCacheDir(),max_cache_size));

( or )
//Memorycache is always faster than DiskCache. Check it our for yourself.
//mImageLoader = new ImageLoader(mVolleyQueue, new BitmapCache(max_cache_size));

mImageLoader.get(, 
        ImageLoader.getImageListener(mImageView, 
                    R.drawable.flickr, 
                    android.R.drawable.ic_dialog_alert),
                    //You can optional specify width & height of the bitmap to be scaled down when the image is downloaded.
                    50,50);

NetworkImageView
Downloads the image as well as cancels the image request if the ImageView for which it was asked to download is recycled or no longer exists. So reduces the work of developer to manage the ImageRequest life cycle. Takes URL and ImageDownloader
mNetworkImageView.setImageUrl(testUrlToDownloadImage1, mImageLoader);