RESTfull app: GAE + Android (II)


Here is the second part of the last article (It has been updated since the last time you read it, so please, check it out). In this second part, we’ll make the Android application that will help us access the data from the server (in my case I uploaded the app to GAE) and display it in a ListView in Android. So, in summary, in this application we’ll have an example of how to use a customized adapter for a ListView and how to parse JSON objects

The first thing we have to do is to create the application and give permissions to access the data that is found on the net. The following line has to be included in the AndroidManifest.xml file

<uses-permission android:name="android.permission.INTERNET" />

To use the list on the main Activity, It must extend ListActivity, and we’ll define the main.xml as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

We’ll show the contacts on the list using the following layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvName"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvEmails"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvNumbers"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

As we can see, there’s nothing special in this. It’s a simple layout with three TextView to display the contents of each contact


Obviously, we have a class representing the contacts, as it did on the server side. Whe should simply copy and simplify it a little bit, as we can see:

package es.jmanzano.json;

import java.util.ArrayList;
import java.util.List;

public class Contact {

	/** User name */
	private String name;

	/** user's image */
	private String urlImage;

	/** List of numbers */
	private List<String> numbers;

	/** List of emails */
	private List<String> emails;

	public Contact() {
		numbers = new ArrayList<String>();
		emails = new ArrayList<String>();
	}

	/**
	 * Getters and setters
	 */
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getUrlImage() {
		return urlImage;
	}

	public void setUrlImage(String urlImage) {
		this.urlImage = urlImage;
	}

	public List<String> getNumbers() {
		return numbers;
	}

	public void setNumbers(List<String> numbers) {
		this.numbers = numbers;
	}

	public List<String> getEmails() {
		return emails;
	}

	public void setEmails(List<String> emails) {
		this.emails = emails;
	}

}

* In this case, we have not included Guava for creating lists to simplify the article, but I hardly recommend to use it.

Finally to finish the tutorial, we only have two more classes to comment: ContactsJSONParser (to parse the JSON Objects) and ExampleJSONActivity (the main activity in which we’ll read the contacts).

package es.jmanzano.json;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ContactsJSONParser {

	/** Array JSON Parser */
	private JSONArray arrayParser;

	public ContactsJSONParser(String json) {
		try {
			JSONObject jsonResponse = new JSONObject(json);
			this.arrayParser = jsonResponse.getJSONArray("contacts");
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Get the i contact json
	 */
	private JSONObject getContactJSON(int i) {
		try {
			return arrayParser.getJSONObject(i);
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Get the i contact
	 */
	private Contact getContact(int i) {
		try {
			JSONObject contactJSON = getContactJSON(i);
			Contact contact = new Contact();

			// Get the name
			String name = contactJSON.getString("name");
			// Get the emails
			List<String> emails = new ArrayList<String>();
			JSONArray emailsJson = contactJSON.getJSONArray("emails");
			for (int n = 0; n < emailsJson.length(); n++) {
				emails.add(emailsJson.getString(n));
			}

			// Get the numbers
			List<String> numbers = new ArrayList<String>();
			JSONArray numbersJson = contactJSON.getJSONArray("numbers");
			for (int n = 0; n < numbersJson.length(); n++) {
				numbers.add(numbersJson.getString(n));
			}
			contactJSON.getJSONArray("numbers");

			// Set the properties
			contact.setName(name);
			contact.setEmails(emails);
			contact.setNumbers(numbers);

			return contact;
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Get all the contacts
	 */
	public List<Contact> getContacts() {
		List<Contact> contacts = new ArrayList<Contact>();
		for (int i = 0; i < arrayParser.length(); i++) {
			contacts.add(getContact(i));
		}
		return contacts;
	}
}

The usage of this class is fairly simple. We must create an instance with the JSON object to parse. After it, how to use it is quite simple: Just call the getContacts() method, and It will return the contacts list that can be found on the server. We can see how the getString() and getJSONArray() methods can obtain the fields that we need.

Finally, we’ll use the ExampleJSONAdapter class to show the JSON data obtained from the server

package es.jmanzano.json;

import java.io.IOException;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class ExampleJSONActivity extends ListActivity {

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		List<Contact> contacts = getContacts();
		ContactsArrayAdapter adapter = new ContactsArrayAdapter(
				getApplicationContext(), R.layout.contact_row, contacts);
		setListAdapter(adapter);
	}

	/**
	 * Get method for the JSON Contacts
	 */
	public List<Contact> getContacts() {
		try {
			// Get the JSON
			HttpClient client = new DefaultHttpClient();
			HttpGet request = new HttpGet(
					"http://domain/resources/api/json");
			HttpResponse response = client.execute(request);
			String jsonString = EntityUtils.toString(response.getEntity());
			// Parse the response
			ContactsJSONParser parser = new ContactsJSONParser(jsonString);

			return parser.getContacts();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Adapter class to show the contacts
	 */
	private class ContactsArrayAdapter extends ArrayAdapter<Contact> {

		/** Contacts list */
		private List<Contact> contacts;

		/** Context */
		private Context context;

		public ContactsArrayAdapter(Context context, int textViewResourceId,
				List<Contact> contacts) {
			super(context, textViewResourceId, contacts);
			this.context = context;
			this.contacts = contacts;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			if (v == null) {
				LayoutInflater li = (LayoutInflater) getContext()
						.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				v = li.inflate(R.layout.contact_row, parent, false);
			}

			Contact contact = contacts.get(position);
			if (contact != null) {
				TextView tvName = (TextView) v.findViewById(R.id.tvName);
				TextView tvEmails = (TextView) v.findViewById(R.id.tvEmails);
				TextView tvNumbers = (TextView) v.findViewById(R.id.tvNumbers);

				tvName.setText(contact.getName());
				tvEmails.setText(contact.getEmails().toString());
				tvNumbers.setText(contact.getNumbers().toString());
			}
			return v;
		}

	}
}

Here we can see both, the ListActivity (the class itself), and the list adapter.

In the getContacts() methods, we can find the most interesting part of ListActivity. This method is used to create the connection with the server and the JSON object is parsed with ContactsJSONParser.

We should note that when making the GET request, you have to write your own domain.

The last thing we have to comment is the ContactsArrayAdapter class: the only interesting thing that it does is to overwrite getView() method, in which we’ll assign the values of the TextView’s. That is possible due to we have called the constructor of the ArrayAdapter class including the contacts list. This way, we’re avoiding to overwrite methods like getCount() or getItem().



 


9 thoughts on RESTfull app: GAE + Android (II)

  1. Jackson is significantly faster than json.org, and IMHO quite a bit easier to use. Check out the performance benchmarks at https://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking for some more information.

    Also, if you use Spring Android’s RestTemplate, you could simplify things a bit more, too. You could elimate all of ContactsJSONParser, ExampleJSONActivity.getContacts() could be just one line:
    restTemplate.getForObject(“http://domain/resources/api/json”, Contacts[].class)
    Plus, it has great functionality around URI variables, which you’d otherwise end up doing yourself, and more likely than not, getting the encodings wrong in hard to debug ways.

    BTW – restTemplate is initialized with:
    RestTemplate restTemplate = new RestTemplate();
    which you probably only want to do once for performance reasons. All you need to do is include the RestTemplate and Spring Android core jars, and perhaps the Jackson jar (RestTemplate will also automatically use org.json too).

    Finally, you’re using HttpClient to do the connection to the server. According to http://android-developers.blogspot.com/2011/09/androids-http-clients.html you should be using HttpUrlConnection instead for a variety of good reasons. If you use RestTemplate, it will even automatically switch between HttpUrlConnection and HttpClient depending on the version of Android, giving you the ideal configuration automatically.

  2. You might have heard about the brand which is best known as Louis Vuitton. Well, we have to ask you that if you have ever experienced any of its products? bolsas louis vuitton It is seriously a good thing if you have but what if the price gets so high that you are unable to afford these items?

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>