I'm quite new to Android. I've been looking for a good example on how to perform a HTTP post request over the web, but I'm hesitating on which to use since I'm only developing for Android 4. I want something asynchronous, fast and simple. An example with JSON result parsing would be much appreciated. Any ideas? Should I use Apache HTTP Client or HttpURLConnection?
For me RestTemplate is one of the easiest ways to consume REST services on Android.
Example for JSON:
RestTemplate template = new RestTemplate();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
//setting timeout
requestFactory.getHttpClient().getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
HTTP_TIMEOUT);
requestFactory.getHttpClient().getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
HTTP_TIMEOUT);
template.setRequestFactory(requestFactory);
//setting converter for JSON
List<HttpMessageConverter<?>> converters = template.getMessageConverters();
converters.add(new MappingJacksonHttpMessageConverter());
template.setMessageConverters(converters);
ResponseEntity<ResponseObject> response = template.postForEntity(URL, requestObject, ResponseObject.class);
ResponseObject result = response.getBody();
To make this works You need RestTemplate and jackson(I think it should be jackson-all) jars in your project. You can find links to those jars in RestTemplate documentation(link above).
To make this asynchronous use AsyncTask from Android SDK.
Related
I am trying to use DELETE method of HttpMethod. The code that I am using for that is
response = restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Response.class);
I am also using JacksonJson for mapping json. The delete functionality returns the json which should be mapped to Response class. But calling the above line doesn't works and gives internal server error with 500 as response code. But, the same API does work with RESTClient in the browser so I guess there is something that I am not doing correctly.
After doing some more research it seems that DELETE method doesn't supports request body. As we had the control over REST API we have changed the request body to be added as parameters. After doing this change the request is working properly.
Hope it helps someone.
A little late to the party I'd like to chime in here as well (document my solution for posterity)
I'm too using spring's rest template, also trying to perform a delete request with a payload AND i'd also like to be able to get the response code from the server side
Disclaimer: I'm on Java 7
My solution is also based on a post here on SO, basically you initially declare a POST request and add a http header to override the request method:
RestTemplate tpl = new RestTemplate();
/*
* http://bugs.java.com/view_bug.do?bug_id=7157360
* As long as we are using java 7 we cannot expect output for delete
* */
HttpHeaders headers = new HttpHeaders();
headers.add("X-HTTP-Method-Override", "DELETE");
HttpEntity<Collection<String>> request = new HttpEntity<Collection<String>>(payload, headers);
ResponseEntity<String> exchange = tpl.exchange(uri, HttpMethod.POST, request, String.class);
I am a beginner on Android app development. I want to confirm if my approach is correct and as per best practices in Android world.
I have an android application that needs textual data (no graphic, video). The data comes from REST based web service as JSON string. I consume this web service using HttpGet object, parse json string using JSONArray and display data.
All this happens in a button click.
My questions are:
Is there a better (or android-style) approach to do the same?
What is the preferred approach to retrieve and post graphic contents to REST based web service?
Any help is most appreciated.
Thanks
Please find my inline commnets,
All this happens in a button click.
My questions are:
Is there a better (or android-style) approach to do the same?
Ideal approach to trigger the Webservice calls in Async task or in a service, so your UI thread will not be blocked till HTTP fires and get the response.
What is the preferred approach to retrieve and post graphic contents to REST based web service?
The graphics content will be usually base64 when you try to retrieve it from the backend.
Refer this example : http://androidtrainningcenter.blogspot.in/2012/03/how-to-convert-string-to-bitmap-and.html
for the posting the graphics to the server
I'm going to assume that you know the path and filename of the image that you want to upload. Add this string to your NameValuePair using image as the key-name.
Sending images can be done using the HttpComponents libraries. Download the latest HttpClient (currently 4.0.1) binary with dependencies package and copy apache-mime4j-0.6.jar and httpmime-4.0.1.jar to your project and add them to your Java build path.
You will need to add the following imports to your class.
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
Now you can create a MultipartEntity to attach an image to your POST request. The following code shows an example of how to do this:
public void post(String url, List nameValuePairs) {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
try {
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
for(int index=0; index < nameValuePairs.size(); index++) {
if(nameValuePairs.get(index).getName().equalsIgnoreCase("image")) {
// If the key equals to "image", we use FileBody to transfer the data
entity.addPart(nameValuePairs.get(index).getName(), new FileBody(new File (nameValuePairs.get(index).getValue())));
} else {
// Normal string data
entity.addPart(nameValuePairs.get(index).getName(), new StringBody(nameValuePairs.get(index).getValue()));
}
}
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost, localContext);
} catch (IOException e) {
e.printStackTrace();
}
}
Hope this helps!
Hey refer this link which will train you better in parsing json data as you required in Android App. Loading the graphic required some lazy loading mechanism which you can refer it from here.
I've been using RestTemplate for a while and have always been satisfied !
But now It sucks.
I used to make my put like this :
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new GsonHttpMessageConverter());
restTemplate.put(URI, object);
Usually my server was accepting format in the URL in a Ruby way : resource.json
But now I'm consuming a server who is not doing so anymore. I need to use Header to deal with format.
Everything is ok, restTemplate set content-type to application/json but don't set the Accept header. So my server is issuing a 406 error because default format is HTML, and he don't render html.
So, does anybody has a workaround for putting both content and accept header to json and adding a json formatted body ?
You can get the headers from the RestTemplate object and add what you need to it (since the headers are nothing more than a map).
Here is the sample code provided by Dam after he got it working:
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new GsonHttpMessageConverter());
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
requestHeaders.setAccept(Arrays.asList(new MediaType[] {MediaType.APPLICATION_JSON}));
HttpEntity<T> requestEntity = new HttpEntity<T>((T) parameter, requestHeaders);
restTemplate.exchange(URI , HttpMethod.PUT, requestEntity, null );
I am using the HttpPut to communicate with server in Android, the response code I am getting is 500.After talking with the server guy he said prepare the string like below and send.
{"key":"value","key":"value"}
now I am completely confused that where should i add this string in my request.
Please help me out .
I recently had to figure out a way to get my android app to communicate with a WCF service and update a particular record. At first this was really giving me a hard time figuring it out, mainly due to me not knowing enough about HTTP protocols, but I was able to create a PUT by using the following:
URL url = new URL("http://(...your service...).svc/(...your table name...)(...ID of record trying to update...)");
//--This code works for updating a record from the feed--
HttpPut httpPut = new HttpPut(url.toString());
JSONStringer json = new JSONStringer()
.object()
.key("your tables column name...").value("...updated value...")
.endObject();
StringEntity entity = new StringEntity(json.toString());
entity.setContentType("application/json;charset=UTF-8");//text/plain;charset=UTF-8
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,"application/json;charset=UTF-8"));
httpPut.setEntity(entity);
// Send request to WCF service
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(httpPut);
HttpEntity entity1 = response.getEntity();
if(entity1 != null&&(response.getStatusLine().getStatusCode()==201||response.getStatusLine().getStatusCode()==200))
{
//--just so that you can view the response, this is optional--
int sc = response.getStatusLine().getStatusCode();
String sl = response.getStatusLine().getReasonPhrase();
}
else
{
int sc = response.getStatusLine().getStatusCode();
String sl = response.getStatusLine().getReasonPhrase();
}
With this being said there is an easier option by using a library that will generate the update methods for you to allow for you to update a record without having to manually write the code like I did above. The 2 libraries that seem to be common are odata4j and restlet. Although I haven't been able to find a clear easy tutorial for odata4j there is one for restlet that is really nice: http://weblogs.asp.net/uruit/archive/2011/09/13/accessing-odata-from-android-using-restlet.aspx?CommentPosted=true#commentmessage
Error 500 is Internal Server error. Not sure if this answers your question but I personally encountered it when trying to send a data URI for an animated gif in a PUT request formatted in JSON but the data URI was too long. You may be sending too much information at once.
I need to upload an image to a remote PHP server which expects the following parameters in HTTPPOST:
*$_POST['title']*
*$_POST['caption']*
*$_FILES['fileatt']*
Most of the internet searches suggested either :
Download the following classes and trying MultiPartEntity to send the request:
apache-mime4j-0.5.jar
httpclient-4.0-beta2.jar
httpcore-4.0-beta3.jar
httpmime-4.0-beta2.jar
OR
Use URLconnection and handle multipart data myself.
Btw, I am keen on using HttpClient class rather than java.net(or is it android.net) classes. Eventually, I downloaded the Multipart classes from the Android source code and used them in my project instead.
Though this can be done by any of the above mentioned methods, I'd like to make sure if these are the only ways to achieve the said objective. I skimmed through the documentation and found a FileEntity class but I could not get it to work.
What is the correct way to get this done in an Android application?
Thanks.
The Android source seems to come with an internal multipart helper library. See this post. At a quick glance, it's better documented than plenty of public APIs (cough cough, SoundPool, cough cough), so it should be a pretty good place to start, or possibly fine to just use a drop-in solution.
Maybe this post on the official Android group helps. The guy is using mime4j.
Another helpful resource could be this example in the Pro Android book.
I do exactly that to interact with an image hosting server (implemented also in php) that expects parameters as if they were posted from an html page.
I build a List<NameValuePair> of my keys and values something like this:
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair(key1, value1));
params.add(new BasicNameValuePair(key2, value2));
and then I pass it to my http helper class that sets the HttpEntity property of my HttpPost request. Here's the method straight out of my helper class:
public static HttpResponse Post(String url, List<NameValuePair> params, Context context)
{
HttpResponse response = null;
try
{
HttpPost request = new HttpPost();
request.setURI(new URI(url));
if(params != null)
request.setEntity(new UrlEncodedFormEntity(params));
HttpClient client = ((ApplicationEx)context.getApplicationContext()).getHttpClient();
response = client.execute(request);
}
catch(Exception ex)
{
// log, etc
}
return response;
}