Consuming JSON services in Android apps

Unless you are writing a Hello World Android application, chances are your application would need to connect to the outside world to fetch some data, such as live currency exchange rates, weather information, records from databases, etc. One of the easiest ways for your application to connect to the outside world is to use web services.

For the past few years, XML web services have dominated the arena for web services, as XML was touted as the ubiquitous medium for data exchange. However, using XML as the medium for your data payload suffers from the following problems:

1. XML representation is inherently heavy. The use of opening and closing tags add a lot of unnecessary weight to the payload. In the world of mobile applications, shaving a few bytes off the payload will dramatically improve the performance of applications, not to mention the reduction of data transferred over the expensive 3G and LTE wireless networks. This translates into cost savings for both application developers (who need to subscribe to expensive networks for their web servers) and users (who has limited amount of bandwidth to use per subscription).
2. XML representation is difficult to parse. While on the desktop, the DOM (Document Object Model) and SAX (Simple APIs for XML) are the two commonly used method for parsing XML Documents; on the mobile platform using DOM and SAX are very expensive, both computationally and in terms of memory requirements.

In recent years, another data interchange format has been gaining in popularity – JSON, or JavaScript Object Notation. Like XML, JSON is a text-based open standard for representing data, and it uses characters such as brackets “[{]}”, colon “:” and comma “,”, to represent data. Data are represented using simple key/value pairs, and more complex data are represented as associative arrays.

In this article, I will walk you through on how to consume a JSON service in your Android application.

Creating the Project

For this project, I will be using Eclipse with the Android 4.1 SDK. To start off, create an Android application project and name it as shown in Figure 1.


Figure 1: Create Android application project

In the res/layout folder, add in the following statements to the activity_main.xml file:

This will create the UI as shown in Figure 2. As you can see, there are actually two parts to the UI:

1. The first part allows the user to enter a pair of latitude and longitude information. Click on the Get Weather button and you will be able to get information about the weather information for that particular location.
2. The second part allows the user to enter a postal code. Clicking the Get Places button will search for all the towns and cities in the world with this postal code.

In both cases, the data would be retrieved from web services hosted by GeoNames Web Services (http://www.geonames.org/export/web-services.html).


Figure 2: Create the UI

Creating the Helper Method

To connect to a web service, your application needs to first of all connect to the server using HTTP. You need to also determine if you will be using HTTP GET or HTTP POST. Once that is determined, you will fetch the data from the server and get ready for the next step, which is parsing. For this article, the GeoNames Web Services that you will be using uses HTTP GET, and hence, you will first of all create the helper method readJSONFeed() in the MainActivity.java file:

The readJSONFeed() method takes in a string representing the URL of the web service and then connects to the server using HTTP GET. You make use of the HttpClient class to connect to the server, the HttpGet class to specify the URL of the server, and the HttpResponse class to get the connection status from the server. Once the connection is established successfully, you all use the BufferedReader and InputStreamReader classes to download the result (which is a JSON string in this example) from the server. The readJSONFeed() method then returns the JSON string.

As you need Internet access for this project to work, remember to add the INTERNET permission in the AndroidManifest.xml file:

Getting Weather Information

Now that you can connect to the server to download the JSON result, it is now time to connect to the GeoNames Web Services to get weather information. In particular, to get the weather information of a particular location, you will use the following URL (replace the <lat> and <lng> with the actual latitude and longitude):

http://ws.geonames.org/findNearByWeatherJSON?lat=<lat&gt&lng=<lng>

A sample result from the server looks like this:

If you observe, you have a primary key – weatherObservation. Its value is a collection of key/value pairs, such as clouds, weatherCondition, etc.

In order to use the readJSONFeed() method, you need to call it asynchronously as beginning with Android 3.0 you can no longer call network operations from within your UI thread (such as within an activity). The easiest way to do this is to wrap it using an AsyncTask class. Hence, add the following statements to the MainActivity class:

In the ReadWeatherJSONFeedTask class, you have two methods:

1. The doInBackGround() method is executed asynchronously. Here, you call the readJSONFeed() method to get the weather information. When the result is obtained, it is returned to the onPostExecute() method.
2. The onPostExecute() method takes the JSON result and parses it.
a. First, the JSON string is passed as the argument to the constructor of the JSONObject class. This creates a new JSONObject object (jsonObject) with key/value mappings from the JSON string.
b. You then get the value of the weatherObservation key by using the getString() method of jsonObject. The values are then passed as the constructor of the JSONObject class, creating another JSONObject – weatherObservationItems.
c. Finally, you extract the value of the clouds and stationName keys by calling the getString() method of weatherObservationItems.

To wire up the event handler for the Get Weather button in your UI, add the btnGetWeather() method to MainActivity.java:

You can now test the application on an Android emulator. Figure 3 shows the result.


Figure 3: Test in Emulator

Getting Places using Postal Code

Now that you have managed to consume the first JSON service, let’s take a look at the second example. This time, you will consume a service that returns a list of city names using a given postal code. You can get the result from the following URL (replace the <postal_code> with the actual postal code):

http://api.geonames.org/postalCodeSearchJSON?postalcode=<postal_code>&maxRows=10&username=demo

A sample result from the server looks like this:

If you observe, you have a primary key – postalCodes. Its value is an array of objects, with each object containing a collection of key/value pairs, such as adminCode1, lat, lng, etc.

Like the previous example, you will add a ReadPlacesFeedTask class to connect to the server asynchronously:

As in the previous example, the result is first converted into a JSONObject. The values of the postalCode key is then converted into a JSONArray object – postalCodesItems, which contains an array of JSONObject objects. You then iterate through the array and extracted each object and print out the values of the postalCode, placeName, and countryCode keys.

Finally, wire the event handler for the Get Places button with the btnGetPlaces() method in the MainActivity.java file:

Figure 4 shows the sample result.


Figure 4: Voilà – the result

Summary

In this article, you have seen how to consume a JSON service from within your Android application. You have seen two examples on how to parse a JSON string using the JSONObject and JSONArray classes available in the org.json package.

Exclusive tips, how-tos, news and comment

Receive monthly updates on the world of mobile dev.

Other Products

Market leading device intelligence for the web, app and MNO ecosystems
DeviceAtlas - Device Intelligence

Real-time identification of fraudulent and misrepresented traffic
DeviceAssure - Device Verification

A free tool for developers, designers and marketers to test website performance
mobiReady - Evaluate your websites’ mobile readiness

© 2024 DeviceAtlas Limited. All rights reserved.

This is a website of DeviceAtlas Limited, a private company limited by shares, incorporated and registered in the Republic of Ireland with registered number 398040 and registered office at 6th Floor, 2 Grand Canal Square, Dublin 2, Ireland