samedi 5 janvier 2013

Populate an Android Spinner with JSON data from a RESTful web API

In the following tutorial I will explain how to populate and Android Spinner (almost equivalent to a java combo box) using JSON data fetched from a REST API. This tutorial DOES NOT explain how to set up and android app or components of an android app; it only explains how to populate an Android spinner. Hoping we are clear with what this does let's begin.

I will use JSON data from the following RESTful API http://www.cmcredit.com/apps/apis/map/

It is a country/region/city database I put together from various sources and you query by sending some NVP parameters. I will also explain how to do this in our android application. Just as a quick example calling the API with the NVP {call: countrylist} will do the get request: http://www.cmcredit.com/apps/apis/map/?call=countrylist and return a country listing. To get regions in a country you could call the api with the NVPs {call: countryregions, country_id: 42}. This API is used for demo purposes ONLY.

We will use data returned from http://www.cmcredit.com/apps/apis/map/?call=countrylist which is of the following format:

First we define some strings that represent the keys of our JSON data (TAG_DATA to TAG_CURRENCY), then we define our API end point MAP_API_URL.

In Android development ,it is recommended not to make http requests on the same thread that displays the user interface (i.e requests are best made asynchronous and not as a blocking operation). This is why I defined a background class called BackGroundTask.java (Code is at the end of this article), that handles all such request. Android provides a class called AsyncTask which enables asynchronous requests so my BackgroundTask class will just be extending this class and overriding some core functions. You can read more about this from the Android documentation.

Define the Spinner countryField as in the layout and finally we define the ArrayList that will hold the list of countries returned from the the API. Each entry in the ArrayList is of type Country (the definition of Country.java class is also given at the end of this article)

The onCreate is called when your activity is started and in it we set the content view and call our buildCountryDropdown() method.

What happens in the buildCountryDropDown() method?

1. Set the parameters to be sent to the API by defining a NameValuePair list.

Initiating our background class, we pass as parameters the API end point, the method to use for the request and the NVP parameters.
3. Get response from the background task

JSONObject countryJSON = bgt.execute().get();

The try..catch block that follows is pretty straight forward.
From the JSON object shown above, you will notice that the necessary data itself is in a JSON array, which is why to get the data, we use

JSONArray countries = countryJSON.getJSONArray(TAG_DATA);

Each item in the countries JSONArray is a JSONObject so to get the entries of each item in the countries Array, we use

JSONObject c = countries.getJSONObject(i);

where i is the current position of the iteration. And finally to get the value of each entry you use the getString() method of the JSONObject class. For example to get the id of a country, you use

String id = c.getString(TAG_ID_COUNTRY);

At the end of the for loop after getting the values of the entries in a country, you add the country to the countryList ArrayList defined in the beginning.

countryList.add(new Country(id, name, iso, currency));

(The code defining the country class is given at the end of this topic.)

The last and final thing that needs to be done to complete our demo is to bind the country list to the spinner. This is done using an ArrayAdapter and because we have a custom type Country we define our own custom adapter called CountryAdapter, that extends the ArrayAdapter class. If the list we wanted to bind to the spinner was a list of Strings, we need not define a custom adapter. we counld directly use the ArrayAdapter.

//get country spinner view from the layout
countryField = (Spinner) findViewById(R.id.countryField);
//define adapter to be used when displaying the country list
CountryAdapter cAdapter = new CountryAdapter(this, android.R.layout.simple_spinner_item, countryList);
//bind the adapter to the spinner
countryField.setAdapter(cAdapter);
//set a listener for selected items in the spinner
countryField.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
Country selectedCountry = countryList.get(position);
showToast(selectedCountry.getName() + " was selected!");
}
});

And that will be it. For detailed explanations on Android Classes used in this tutorial, you can visit the Android Developers site.