Skip to content

Instantly share code, notes, and snippets.

@tyvsmith
Created May 24, 2011 22:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tyvsmith/989952 to your computer and use it in GitHub Desktop.
Save tyvsmith/989952 to your computer and use it in GitHub Desktop.
RESTclient-Android Blog entries
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ui.Main" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".receiver.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.WebReceiver" />
<service android:name=".service.WebService" />
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
public class Main extends ListActivity {
private Main activity;
private WebService webService;
ProgressDialog dialog;
ArrayList<String> data;
public final static String PREFS_NAME = "tylersmith.webservice";
public final static String PREFS_DATA = "data";
private final int MENU_REFRESH = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
activity = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bindService();
bindList();
}
@Override
protected void onResume() {
super.onResume();
}
private void bindService() {
Intent service = new Intent(this, WebService.class);
service.putExtra("fromApplication", true);
// need to use this instead of startService();
WakefulIntentService.sendWakefulWork(getApplicationContext(), service);
// Binding ..this block can also start service if not started already
Intent bindIntent = new Intent(this, WebService.class);
bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
// Register Broadcast Receiver
IntentFilter filter = new IntentFilter(WebService.WEB_INTENT_FILTER);
registerReceiver(myReceiver, filter);
}
private void bindList() {
try {
loadData();
} catch (Exception e) {
e.printStackTrace();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, data);
adapter.setNotifyOnChange(true);
setListAdapter(adapter);
}
// Using JSON since it serializes so nicely
// Could also create a custom adapter extended from BaseAdapter but thats
// outside the scope of this tutorial.
private void loadData() throws Exception {
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(this);
JSONArray jData = new JSONArray(sp.getString(PREFS_DATA, "[]"));
data = new ArrayList<String>();
for (int index = 0; index < jData.length(); index++) {
data.add(jData.getJSONObject(index).getString("from_user")
+ jData.getJSONObject(index).getString("text"));
}
}
private void refreshData() {
if (dialog == null || !dialog.isShowing())
dialog = ProgressDialog.show(Main.this, "",
"Loading. Please wait...", true);
new Thread(webService).start();
}
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
boolean success = extras.getBoolean(WebService.EXTRAS_SUCCESS,
false);
String message = extras
.getString(WebService.EXTRAS_RESPONSE_MESSAGE);
if (message == null)
message = "There was a connection problem, please try again later";
if (success) {
try {
loadData();
} catch (Exception e) {
e.printStackTrace();
}
} else {
//Using a reference to the activity instead of getApplicationContext() to prevent breaking
//This may keep a reference to the original and cause a memory leak
//TODO: investigate further
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(message)
.setCancelable(false)
.setNeutralButton("Ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int id) {
dialog.cancel();
}
});
final AlertDialog alert = builder.create();
}
if (dialog != null && dialog.isShowing())
dialog.dismiss();
}
};
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
webService = ((WebService.WebBinder) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
webService = null;
}
};
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
menu.add(0, MENU_REFRESH, 0, "Refresh").setIcon(
android.R.drawable.ic_menu_rotate);
return true;
};
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_REFRESH: {
refreshData();
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDestroy() {
super.onDestroy();
// Unregister the Broadcast receiver and unbind service
unregisterReceiver(myReceiver);
unbindService(serviceConnection);
}
}
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
AlarmManager mgr = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent service = new Intent(context, WebReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, service, 0);
//Updates once every two hours
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), 1000*60*60*2, pi);
}
}
public class WebReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
WakefulIntentService.sendWakefulWork(context, WebService.class);
}
}
public class RestClient {
private boolean authentication;
private ArrayList<NameValuePair> headers;
private String jsonBody;
private String message;
private ArrayList<NameValuePair> params;
private String response;
private int responseCode;
private String url;
// HTTP Basic Authentication
private String username;
private String password;
protected Context context;
public RestClient(String url) {
this.url = url;
params = new ArrayList<NameValuePair>();
headers = new ArrayList<NameValuePair>();
}
//Be warned that this is sent in clear text, don't use basic auth unless you have to.
public void addBasicAuthentication(String user, String pass) {
authentication = true;
username = user;
password = pass;
}
public void addHeader(String name, String value) {
headers.add(new BasicNameValuePair(name, value));
}
public void addParam(String name, String value) {
params.add(new BasicNameValuePair(name, value));
}
public void execute(RequestMethod method) throws Exception {
switch (method) {
case GET: {
HttpGet request = new HttpGet(url + addGetParams());
request = (HttpGet) addHeaderParams(request);
executeRequest(request, url);
break;
}
case POST: {
HttpPost request = new HttpPost(url);
request = (HttpPost) addHeaderParams(request);
request = (HttpPost) addBodyParams(request);
executeRequest(request, url);
break;
}
case PUT: {
HttpPut request = new HttpPut(url);
request = (HttpPut) addHeaderParams(request);
request = (HttpPut) addBodyParams(request);
executeRequest(request, url);
break;
}
case DELETE: {
HttpDelete request = new HttpDelete(url);
request = (HttpDelete) addHeaderParams(request);
executeRequest(request, url);
}
}
}
private HttpUriRequest addHeaderParams(HttpUriRequest request)
throws Exception {
for (NameValuePair h : headers) {
request.addHeader(h.getName(), h.getValue());
}
if (authentication) {
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(
username, password);
request.addHeader(new BasicScheme().authenticate(creds, request));
}
return request;
}
private HttpUriRequest addBodyParams(HttpUriRequest request)
throws Exception {
if (jsonBody != null) {
request.addHeader("Content-Type", "application/json");
if (request instanceof HttpPost)
((HttpPost) request).setEntity(new StringEntity(jsonBody,
"UTF-8"));
else if (request instanceof HttpPut)
((HttpPut) request).setEntity(new StringEntity(jsonBody,
"UTF-8"));
} else if (!params.isEmpty()) {
if (request instanceof HttpPost)
((HttpPost) request).setEntity(new UrlEncodedFormEntity(params,
HTTP.UTF_8));
else if (request instanceof HttpPut)
((HttpPut) request).setEntity(new UrlEncodedFormEntity(params,
HTTP.UTF_8));
}
return request;
}
private String addGetParams() throws Exception {
//Using StringBuffer append for better performance.
StringBuffer combinedParams = new StringBuffer();
if (!params.isEmpty()) {
combinedParams.append("?");
for (NameValuePair p : params) {
combinedParams.append((combinedParams.length() > 1 ? "&" : "")
+ p.getName() + "="
+ URLEncoder.encode(p.getValue(), "UTF-8"));
}
}
return combinedParams.toString();
}
public String getErrorMessage() {
return message;
}
public String getResponse() {
return response;
}
public int getResponseCode() {
return responseCode;
}
public void setContext(Context ctx) {
context = ctx;
}
public void setJSONString(String data) {
jsonBody = data;
}
private void executeRequest(HttpUriRequest request, String url) {
DefaultHttpClient client = new DefaultHttpClient();
HttpParams params = client.getParams();
// Setting 30 second timeouts
HttpConnectionParams.setConnectionTimeout(params, 30 * 1000);
HttpConnectionParams.setSoTimeout(params, 30 * 1000);
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();
}
RestClient client = new RestClient(webServiceUrl);
client.addBasicAuthentication(username, password);
try {
client.execute(RequestMethod.GET);
if (client.getResponseCode() != 200) {
//return server error
return client.getErrorMessage();
}
//return valid data
JSONObject jObj = new JSONObject(client.getResponse());
return jObj.toString();
} catch(Exception e) {
return e.toString();
}
public class WebService extends WakefulIntentService implements Runnable {
public static final String EXTRAS_RESPONSE_MESSAGE = "tylersmith.webservice.response_message";
public static final String EXTRAS_SUCCESS = "tylersmith.webservice.success";
public static final String WEB_INTENT_FILTER = "tylersmith.webservice.intent.filter";
private final IBinder binder = new WebBinder();
private Handler handler = new Handler();
protected Context context;
public WebService() {
super("UpdateService");
}
@Override
protected void doWakefulWork(Intent intent) {
context = getApplicationContext();
//preventing this from running unless specifically called from within the activity or through the alarm manager
if(!intent.getBooleanExtra("fromApplication", false))
new Thread(this).start();
}
@Override
public void run() {
String twitterUrl = "http://search.twitter.com/search.json";
RestClient client = new RestClient(twitterUrl);
client.addParam("q", "android");
try {
client.execute(RequestMethod.GET);
if(client.getResponseCode() == 200) {
//Successfully connected
JSONObject jObj = new JSONObject(client.getResponse());
JSONArray jResults = jObj.getJSONArray("results");
SharedPreferences.Editor editPrefs =
PreferenceManager.getDefaultSharedPreferences(context).edit();
editPrefs.putString(Main.PREFS_DATA, jResults.toString());
editPrefs.commit();
broadCast(true, "Success");
} else {
//error connecting to server, lets just return an error
broadCast(false, "Error Connecting");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void broadCast(boolean success, String message) {
Intent intent = new Intent();
intent.putExtra(EXTRAS_SUCCESS, success);
intent.putExtra(EXTRAS_RESPONSE_MESSAGE, message);
intent.setAction(WEB_INTENT_FILTER);
sendBroadcast(intent);
}
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public class WebBinder extends Binder {
public WebService getService() {
return WebService.this;
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment