com.octo.android.robospice.motivations.loader.RestLoader Maven / Gradle / Ivy
package com.octo.android.robospice.motivations.loader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
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.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
public class RestLoader extends AsyncTaskLoader< RestLoader.RESTResponse > {
private static final String TAG = RestLoader.class.getName();
// We use this delta to determine if our cached data is
// old or not. The value we have here is 10 minutes;
private static final long STALE_DELTA = 600000;
private long delay;
public enum HTTPVerb {
GET, POST, PUT, DELETE
}
public static class RESTResponse {
private String mData;
private int mCode;
public RESTResponse() {
}
public RESTResponse( String data, int code ) {
mData = data;
mCode = code;
}
public String getData() {
return mData;
}
public int getCode() {
return mCode;
}
}
private HTTPVerb mVerb;
private Uri mAction;
private Bundle mParams;
private RESTResponse mRestResponse;
private long mLastLoad;
public RestLoader( Context context ) {
super( context );
}
public RestLoader( Context context, HTTPVerb verb, Uri action ) {
super( context );
mVerb = verb;
mAction = action;
}
public RestLoader( Context context, HTTPVerb verb, Uri action, Bundle params ) {
super( context );
mVerb = verb;
mAction = action;
mParams = params;
}
public void setDelay( long delay ) {
this.delay = delay;
}
@Override
public RESTResponse loadInBackground() {
if ( delay != 0 ) {
Log.d( "request", "delaying loading from network" );
try {
Thread.sleep( delay );
} catch ( InterruptedException e ) {
Log.e( "request", "Exception while delaying request", e );
}
}
try {
// At the very least we always need an action.
if ( mAction == null ) {
Log.e( TAG, "You did not define an action. REST call canceled." );
return new RESTResponse(); // We send an empty response back. The LoaderCallbacks
// implementation will always need to check the RESTResponse
// and handle error cases like this.
}
// Here we define our base request object which we will
// send to our REST service via HttpClient.
HttpRequestBase request = null;
// Let's build our request based on the HTTP verb we were
// given.
switch ( mVerb ) {
case GET: {
request = new HttpGet();
attachUriWithQuery( request, mAction, mParams );
}
break;
case DELETE: {
request = new HttpDelete();
attachUriWithQuery( request, mAction, mParams );
}
break;
case POST: {
request = new HttpPost();
request.setURI( new URI( mAction.toString() ) );
// Attach form entity if necessary. Note: some REST APIs
// require you to POST JSON. This is easy to do, simply use
// postRequest.setHeader('Content-Type', 'application/json')
// and StringEntity instead. Same thing for the PUT case
// below.
HttpPost postRequest = (HttpPost) request;
if ( mParams != null ) {
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity( paramsToList( mParams ) );
postRequest.setEntity( formEntity );
}
}
break;
case PUT: {
request = new HttpPut();
request.setURI( new URI( mAction.toString() ) );
// Attach form entity if necessary.
HttpPut putRequest = (HttpPut) request;
if ( mParams != null ) {
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity( paramsToList( mParams ) );
putRequest.setEntity( formEntity );
}
}
break;
}
if ( request != null ) {
HttpClient client = new DefaultHttpClient();
// Let's send some useful debug information so we can monitor things
// in LogCat.
Log.d( TAG, "Executing request: " + verbToString( mVerb ) + ": " + mAction.toString() );
// Finally, we send our request using HTTP. This is the synchronous
// long operation that we need to run on this Loader's thread.
HttpResponse response = client.execute( request );
HttpEntity responseEntity = response.getEntity();
StatusLine responseStatus = response.getStatusLine();
int statusCode = responseStatus != null ? responseStatus.getStatusCode() : 0;
// Here we create our response and send it back to the LoaderCallbacks implementation.
RESTResponse restResponse = new RESTResponse( responseEntity != null ? EntityUtils.toString( responseEntity ) : null, statusCode );
return restResponse;
}
// Request was null if we get here, so let's just send our empty RESTResponse like usual.
return new RESTResponse();
} catch ( URISyntaxException e ) {
Log.e( TAG, "URI syntax was incorrect. " + verbToString( mVerb ) + ": " + mAction.toString(), e );
return new RESTResponse();
} catch ( UnsupportedEncodingException e ) {
Log.e( TAG, "A UrlEncodedFormEntity was created with an unsupported encoding.", e );
return new RESTResponse();
} catch ( ClientProtocolException e ) {
Log.e( TAG, "There was a problem when sending the request.", e );
return new RESTResponse();
} catch ( IOException e ) {
Log.e( TAG, "There was a problem when sending the request.", e );
return new RESTResponse();
}
}
@Override
public void deliverResult( RESTResponse data ) {
// Here we cache our response.
mRestResponse = data;
super.deliverResult( data );
}
@Override
protected void onStartLoading() {
if ( mRestResponse != null ) {
// We have a cached result, so we can just
// return right away.
super.deliverResult( mRestResponse );
}
// If our response is null or we have hung onto it for a long time,
// then we perform a force load.
if ( mRestResponse == null || System.currentTimeMillis() - mLastLoad >= STALE_DELTA ) {
forceLoad();
}
mLastLoad = System.currentTimeMillis();
}
@Override
protected void onStopLoading() {
// This prevents the AsyncTask backing this
// loader from completing if it is currently running.
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
// Stop the Loader if it is currently running.
onStopLoading();
// Get rid of our cache if it exists.
mRestResponse = null;
// Reset our stale timer.
mLastLoad = 0;
}
private static void attachUriWithQuery( HttpRequestBase request, Uri uri, Bundle params ) {
try {
if ( params == null ) {
// No params were given or they have already been
// attached to the Uri.
request.setURI( new URI( uri.toString() ) );
} else {
Uri.Builder uriBuilder = uri.buildUpon();
// Loop through our params and append them to the Uri.
for ( BasicNameValuePair param : paramsToList( params ) ) {
uriBuilder.appendQueryParameter( param.getName(), param.getValue() );
}
uri = uriBuilder.build();
request.setURI( new URI( uri.toString() ) );
}
} catch ( URISyntaxException e ) {
Log.e( TAG, "URI syntax was incorrect: " + uri.toString() );
}
}
private static String verbToString( HTTPVerb verb ) {
switch ( verb ) {
case GET:
return "GET";
case POST:
return "POST";
case PUT:
return "PUT";
case DELETE:
return "DELETE";
}
return "";
}
private static List< BasicNameValuePair > paramsToList( Bundle params ) {
ArrayList< BasicNameValuePair > formList = new ArrayList< BasicNameValuePair >( params.size() );
for ( String key : params.keySet() ) {
Object value = params.get( key );
// We can only put Strings in a form entity, so we call the toString()
// method to enforce. We also probably don't need to check for null here
// but we do anyway because Bundle.get() can return null.
if ( value != null ) {
formList.add( new BasicNameValuePair( key, value.toString() ) );
}
}
return formList;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy