I’ve decided recently to branch out from mainly web development into the mobile app space – starting with Google’s Android (because I own a Android phone). One of the first things I wanted to do was start calling webservices, specifically Google Analytics.
Now I am pretty new to Android and Java in general but I feel I’ve come up with a nice simple way to make requests to web services and APIs (and plain html pages if you want). The class uses the org.apache.http library which is included in Android.
This is the code for the class.
public class RestClient {
private ArrayList <NameValuePair> params;
private ArrayList <NameValuePair> headers;
private String url;
private int responseCode;
private String message;
private String response;
public String getResponse() {
return response;
}
public String getErrorMessage() {
return message;
}
public int getResponseCode() {
return responseCode;
}
public RestClient(String url)
{
this.url = url;
params = new ArrayList<NameValuePair>();
headers = new ArrayList<NameValuePair>();
}
public void AddParam(String name, String value)
{
params.add(new BasicNameValuePair(name, value));
}
public void AddHeader(String name, String value)
{
headers.add(new BasicNameValuePair(name, value));
}
public void Execute(RequestMethod method) throws Exception
{
switch(method) {
case GET:
{
//add parameters
String combinedParams = "";
if(!params.isEmpty()){
combinedParams += "?";
for(NameValuePair p : params)
{
String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(),”UTF-8″);
if(combinedParams.length() > 1)
{
combinedParams += "&" + paramString;
}
else
{
combinedParams += paramString;
}
}
}
HttpGet request = new HttpGet(url + combinedParams);
//add headers
for(NameValuePair h : headers)
{
request.addHeader(h.getName(), h.getValue());
}
executeRequest(request, url);
break;
}
case POST:
{
HttpPost request = new HttpPost(url);
//add headers
for(NameValuePair h : headers)
{
request.addHeader(h.getName(), h.getValue());
}
if(!params.isEmpty()){
request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
}
executeRequest(request, url);
break;
}
}
}
private void executeRequest(HttpUriRequest request, String url)
{
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse;
try {
httpResponse = client.execute(request);
responseCode = httpResponse.getStatusLine().getStatusCode();
message = httpResponse.getStatusLine().getReasonPhrase();
HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
response = convertStreamToString(instream);
// Closing the input stream will trigger connection release
instream.close();
}
} catch (ClientProtocolException e) {
client.getConnectionManager().shutdown();
e.printStackTrace();
} catch (IOException e) {
client.getConnectionManager().shutdown();
e.printStackTrace();
}
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
Here is an example of how I use the class to call the Google Analytics API. I use the AddParam methods to add query string / post values and the AddHeader method to add headers to the request. RequestMethod is a simple enum with GET and POST values.
RestClient client = new RestClient(LOGIN_URL);
client.AddParam("accountType", "GOOGLE");
client.AddParam("source", "tboda-widgalytics-0.1");
client.AddParam("Email", _username);
client.AddParam("Passwd", _password);
client.AddParam("service", "analytics");
client.AddHeader("GData-Version", "2");
try {
client.Execute(RequestMethod.POST);
} catch (Exception e) {
e.printStackTrace();
}
String response = client.getResponse();
The class also exposes the Http response code and message which are important when using some Restful APIs. I know could definitely improve/extend on this code and would love to hear from those more experienced in Java and Android than myself.
Hi,
This works fine.But when i create new instance for DefaultHttpClient i did not receive cookies.But i solved this using singleton pattern.when i restart the phone new instance for DefaultHttpClient created.I did not receive any cookies from response.how to solve this?
any suggestions.
@Hiristein,
Please check above my post. There is an example. It will help you a lot.
Try it!!!
@Prashant :
Done… It works
Thanks a lot. it was so helpful
Nice!! It helped me when required
hi,
ur code was helpful for me.i want to know how to give method name which we want to access with the request..
thanks..
Aju
To what class does RequestMethod belong? Using Eclipse for Java (6), I get an error which reads “RequestMethod cannot be resolved to a type”. These are my http imports
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
hi
my web service path is: http://localhost/Survey/SurveyWebService.asmx
method name: SaveData, with string parameter: strData
i made
i used this code
RestClient client = new RestClient(“http://localhost/Survey/SurveyWebService.asmx/SaveData”);
client.AddParam(“strData”, “hi”);
client.AddHeader(“Host”, “localhost”);
client.AddHeader(“Content-Type”, “text/xml; charset=utf-8″);
client.AddHeader(“SOAPAction”, “http://tempuri.org/SaveData”);
client.AddHeader(“Content-Length”, “length”);
client.AddHeader(“GData-Version”, “2″);
try {
client.Execute(RequestMethod.POST);
String response = client.getResponse();
this.feedbackEditText.setText(“response: ” + response);
} catch (Exception e) {
this.feedbackEditText.setText(“err: “);
}
but got: “response: null
help me pls
What about PUT and DELETE?
How can I do that?
Hi, What about passing complex types as parameter to the rest based service using json as the format?
Heya – loving this class to make GET requests, however when making POST requests where should I define the body of the request for a POST request?
Thanks in advance!
Hey. I want to use your RestClient to see how can I access a wcf web service. I don;t have the code for the web service. I have only the webservice url and the name of the method I have to access.
−
−
If you can help me, please.
hey, I think we should reuse HttpClient.
But I find out that after using httpClinet a few times, it just does not work, and donnot know why.
This part is missing in your code:
public enum RequestMethod
{
GET,
POST
}
I am trying to implement this code but regardless of when I check on my response variable it is always null. I can’t seem to make it work. Are there any event listeners or delay I need to consider to wait for the data to come back before I try to make use of it?
Hi Michael,
RequestMethod belongs to the class where you are defining other methods like getResponse(), AddParam(), AddHeader() etc.
Try writing the following code:
public enum RequestMethod
{
GET,
POST
}
Pingback: “What is Web Services, Alex?” « Neil P. Truick
Okay, for those that are getting the “null” returned back. One thing I found after researching is that you need to edit the “permissions” for your application. If you look at the error from the printStackTrack
} catch (IOException e){
client.getConnectionManager().shutdown();
e.printStackTrace();
}
You will see it shows “Permission denied (maybe missing INTERNET permission)”.
We have to give the application permission to each piece of the android it will be accessing. TO do this, you need to update the AndroidManifest.xml file. One way I read was to use Eclipse’s editor (extremely simple) to add the permission..
Here’s one person’s note on it.
http://stackoverflow.com/questions/2990379/permission-denied-maybe-missing-internet-permission-when-calling-web-service
Otherwise, go into Eclipse, then find your Project Explorer tab, open up your project and find AndroidManifest.xml. double click to open it, some tabs in the bottom of that new manifest window will display. Click on the one called Permissions. I’m assuming your permissions are empty, so click the ADD button in that permissions window that comes up, select USES PERMISSION from the popup of new elements. On the window to the right after you select the element, use the “name” drop box and find android.permission.INTERNET .. which is the one you need to give permission to with your app. Save your file again and rerun your app…
That should help.
Pingback: Android – AppEngine – JPA « IDN lab
Hi Luke,
I am using restful webservice.
below is my code for that I am getting exception
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI());
BIInput bi = new BIInput();// Assign
bi.setProductID(BiDataHandle.ProductID + “”);
BIOutput illust = service.path(“services”).path(“calculateBI”)
.accept(MediaType.APPLICATION_XML).post(BIOutput.class,bi);
and this is my BIInput class
package com.XXX.XXX.onlinesale;
//@javax.xml.bind.annotation.XmlRootElement
public class BIInput {
//Values for Premium
private String productID;
public BIInput(){
}
public String getProductID() {
return productID;
}
public void setProductID(String productID) {
this.productID = productID;
}
}
For above code I am getting below exception.
java.lang.ExceptionInInitializerError
09-06 14:59:39.881: ERROR/AndroidRuntime(4462): at com.sun.jersey.core.spi.factory.MessageBodyFactory.getMessageBodyWriterMediaTypes(MessageBodyFactory.java:444)
Please help me Thanx…..
Hi,
I have done One Assignment that is aynchronusly download image in listview. my next task is to use HttpClient to set header and timestamp with this . I don’t know any Idia about this could you tell me how it works with this.
Please reply if you know.
hi..luke , i’m new to android…and i going to my final year project in android..
my question is how to create and consume a web service in android….using Ecilpse IDE..please say in step by step and also show some screen shot….and also suggest some books which covers the web service concept in android using Eclipse IDE….
please luke…
Oh! sorry. Your code give error Bad Request. I’m try to consume Wcfservice.
I tried to run the app, on my local machine, I put both localhost+ port number and my IP + port number, but I got null response, later I uploaded my app into google app engine, it worked.
anyone can tell me what is the problem which i could not get response however google app url runs perfectly in my local machine.
I am trying to use your above code but java cant resolved:
RequestMethod
GET
POST
URLEncoder
Can you please help me
Brilliantly simple. Thank you so much.
Hey when i call your execute method at that time Network on main thread exception is generated .
I don’t know how this happened and i also set the permission in androidmanifest.xml.
HEy its urgent , please tell how to solve this ..
Thnks.
Hey,
Fantastic, exactly what I was after. You should consider putting it onto GitHub so other people
can contribute and help expand it!
Thanks again!
D
Can someone please send me the full source for the RestClient class as the end bit is corrupted from the main post above as you can see./
Thanks for such help.. It works !!
That’s what i was looking for..
Really useful article. Thanks a lot
You may want to pull the creation of of the instance of the http client out of the private instance method.
See this recommendation:
__http://hc.apache.org/httpcomponents-client-ga/tutorial/html/httpagent.html
DefaultHttpClient is thread safe. It is recommended that the same instance of this class is reused for multiple request executions
Also you can look into the AndroidHttpClient.
Great Article