Created
May 24, 2011 22:58
-
-
Save tyvsmith/989952 to your computer and use it in GitHub Desktop.
RESTclient-Android Blog entries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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