I just finished a huge project for school using the Google Android OS. The biggest hurdle I had to jump through we getting android to successfully talk to web services. I have put together a set of classes and procedures to do so that make it easy and reliable. I have taken some code from here and there and adapted my own. It was a while ago so I don’t recall where I found it all. For this example I am going to be using the web service  http://www.sumasoftware.com/alerts/GetAlerts.php to read the alerts.

The first thing you’ll need to download and add to your project is the google GSON library http://code.google.com/p/google-gson/downloads/list

Add the jar file to your android project as an external jar

Download the following WebService.java class in order to interact with the web service and add it to your project

package josecgomez.com.android.dev.webservice;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.google.gson.Gson;

public class WebService{

    DefaultHttpClient httpClient;
    HttpContext localContext;
    private String ret;

    HttpResponse response = null;
    HttpPost httpPost = null;
    HttpGet httpGet = null;
    String webServiceUrl;

    //The serviceName should be the name of the Service you are going to be using. 
    public WebService(String serviceName){
        HttpParams myParams = new BasicHttpParams();

        HttpConnectionParams.setConnectionTimeout(myParams, 10000);
        HttpConnectionParams.setSoTimeout(myParams, 10000);
        httpClient = new DefaultHttpClient(myParams);       
        localContext = new BasicHttpContext();
        webServiceUrl = serviceName;
       
    }

    //Use this method to do a HttpPost\WebInvoke on a Web Service
    public String webInvoke(String methodName, Map<String, Object> params) {
    	
    	JSONObject jsonObject = new JSONObject();

    	for (Map.Entry<String, Object> param : params.entrySet()){
    		try {
    			jsonObject.put(param.getKey(), param.getValue());
			} 
    		catch (JSONException e) {
    			Log.e("Groshie", "JSONException : "+e);
			}
    	}
        return webInvoke(methodName,  jsonObject.toString(), "application/json");
    }

    private String webInvoke(String methodName, String data, String contentType) {
        ret = null;

        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);

        httpPost = new HttpPost(webServiceUrl + methodName);
        response = null;

        StringEntity tmp = null;        

        //httpPost.setHeader("User-Agent", "SET YOUR USER AGENT STRING HERE");
        httpPost.setHeader("Accept", 
"text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");

        if (contentType != null) {
            httpPost.setHeader("Content-Type", contentType);
        } else {
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
        }

        try {
            tmp = new StringEntity(data,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            Log.e("Groshie", "HttpUtils : UnsupportedEncodingException : "+e);
        }

        httpPost.setEntity(tmp);

        Log.d("Groshie", webServiceUrl + "?" + data);

        try {
            response = httpClient.execute(httpPost,localContext);

            if (response != null) {
                ret = EntityUtils.toString(response.getEntity());
            }
        } catch (Exception e) {
            Log.e("Groshie", "HttpUtils: " + e);
        }

        return ret;
    }

    //Use this method to do a HttpGet/WebGet on the web service
    public String webGet(String methodName, Map<String, String> params) {
    	String getUrl = webServiceUrl + methodName;
    	
    	int i = 0;
    	for (Map.Entry<String, String> param : params.entrySet())
    	{
    		if(i == 0){
    			getUrl += "?";
    		}
    		else{
    			getUrl += "&";
    		}
    		
    		try {
				getUrl += param.getKey() + "=" + URLEncoder.encode(param.getValue(),"UTF-8");
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		
    		i++;
    	}
    	
        httpGet = new HttpGet(getUrl);  
        Log.e("WebGetURL: ",getUrl);
        
        try {
            response = httpClient.execute(httpGet);  
        } catch (Exception e) {
            Log.e("Groshie:", e.getMessage());
        }

        // we assume that the response body contains the error message  
        try {
            ret = EntityUtils.toString(response.getEntity());  
        } catch (IOException e) {
            Log.e("Groshie:", e.getMessage());
        }

        return ret;
    }
    
    public static JSONObject Object(Object o){
    	try {
			return new JSONObject(new Gson().toJson(o));
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return null;
    }

    public InputStream getHttpStream(String urlString) throws IOException {
        InputStream in = null;
        int response = -1;

        URL url = new URL(urlString); 
        URLConnection conn = url.openConnection();

        if (!(conn instanceof HttpURLConnection))                     
            throw new IOException("Not an HTTP connection");

        try{
            HttpURLConnection httpConn = (HttpURLConnection) conn;
            httpConn.setAllowUserInteraction(false);
            httpConn.setInstanceFollowRedirects(true);
            httpConn.setRequestMethod("GET");
            httpConn.connect(); 

            response = httpConn.getResponseCode();                 

            if (response == HttpURLConnection.HTTP_OK) {
                in = httpConn.getInputStream();                                 
            }                     
        } catch (Exception e) {
            throw new IOException("Error connecting");            
        } // end try-catch

        return in;     
    }
    
    public void clearCookies() {
        httpClient.getCookieStore().clear();
    }

    public void abort() {
        try {
            if (httpClient != null) {
                System.out.println("Abort.");
                httpPost.abort();
            }
        } catch (Exception e) {
            System.out.println("Your App Name Here" + e);
        }
    }
}

Based on the structure of your JSON file develop a class in your project to support the structure. For example for the above mentioned service I developed this class.

The JSON returned has this structure {“alertid”:”1″,”alerttext”:”This is test”,”alertdate”:”2010-02-11 09:03:40″}

package josecgomez.com.android.dev.webservice.objects;

public class alerts {
	
	public int alertid;
	public String alerttext;
	public String alertdate;
	
	@Override
	public String toString()
	{
		return "Alert ID: "+alertid+ " Alert Text: "+alerttext+ " Alert Date: "+alertdate;
		
	}
}

Once you’ve done this in your android activity you may execute the following code to access the web service

 // Instantiate the Web Service Class with he URL of the web service not that you must pass
        
        WebService webService = new WebService("http://www.sumasoftware.com/alerts/GetAlerts.php");

        //Pass the parameters if needed , if not then pass dummy one as follows
		Map<String, String> params = new HashMap<String, String>();
		params.put("var", "");
		
		//Get JSON response from server the "" are where the method name would normally go if needed example
		// webService.webGet("getMoreAllerts", params);
		String response = webService.webGet("", params);

		try
		{
			//Parse Response into our object
			Type collectionType = new TypeToken<List<alerts>>(){}.getType();
			List<alerts> alrt = new Gson().fromJson(response, collectionType);
		
		}
		catch(Exception e)
		{
			Log.d("Error: ", e.getMessage());
		}

Please note that the above code is for accessing collection of items, if you are attempting to access a single item there should be a slight modification to the code as follows

/* Replace
Type collectionType = new TypeToken<List<alerts>>(){}.getType();
List<alerts> alrt = new Gson().fromJson(response, collectionType);
with
*/
alerts alert = new Gson().fromJson(response, alerts.class);

The above method uses GET if you need to INVOKE POST there should be a slight modification to the above code as follows. I hope this helps.

/* Replace 
String response = webService.webGet("", params);
with
*/
webService.webInvoke("", params);

Be Sociable, Share!

Tags: , , , ,

62 Comments on Android accessing RESTFull Web Services using JSON

  1. Jose C Gomez says:

    I haven’t done Android Dev in a bit, sorry :(

  2. sinchro says:

    any chance u could upload the full source for the project? i’m a student in my 2nd year and i have trouble wrapping my head around your guide.

  3. Jose C Gomez says:

    This is an old post, I don’t have any of the source files. Sorry

  4. Lucas says:

    Thats not a RESTful service. This is WebService with method calls.

  5. Nick Penkov says:

    Very nice article. Unfortunately it will not work straight forward with the latest Android 4.X, as Network operations are not permitted from UI thread. I am planning to create similar article with the latest apis, and some demos for creating and consuming RESTfull web services in Java, if you don’t mind I will put reference to your post.

    Thanks,
    Nick

  6. Jose C Gomez says:

    Sure no problem, I haven’t had time to update anything regarding Android recently, I appreciate that you asked :)

    Thanks!

  7. [...] In other words – our UI class will implement this interface and pass self instance to AsyncThread. When AsyncThread webservice class finishes his work – he will call implementation method response(String) of our UI class to notify about the result. I have to admit here that some of the code for WebService Call – I have copied from Jose C Gomez’s Blog. [...]

  8. hans stam says:

    the thing most people will be missing is in the android manifest. if you add that, the app will run

  9. JOrge says:

    What import do I need for this obnect Type collectionType?

  10. JOrge says:

    I hve an error when a parser my class:
    public class Channel implements Serializable {

    /**
    *
    */
    private static final long serialVersionUID = 1L;
    public String code;
    public String name;
    public int order;
    public String description;
    public boolean enabled;
    public String equipmentCode;
    public double offset;
    public double slope;
    public String unit;
    public int decimals;
    public double minValue;
    public double maxValue;
    public int rawValue;
    public double calculatedValue;
    public String calculatedValueAndUnit;
    public boolean rawValueSupported;
    public double setPointValue;
    public long tsUpdated;
    public long tsProcessed;
    public int lifetime;
    public boolean upToDateNotified;
    public String channelTypeName;
    public int watchCount;
    public String channelTypeCode;
    public String direction;

    @Override
    public String toString() {
    return “Channel “;
    }

    }

    Type collectionType = new TypeToken<List>(){}.getType();
    channels = new Gson().fromJson(response, collectionType);
    Expected BEGIN_ARRAY but Was BEGIN_OBJECT

  11. Ashish says:

    Very nice and detailed post for android developers. Thanks a lot

Leave a Reply