Thursday 27 October 2011

Android: changing background color or drawable of a custom View when it's pressed or focused

Let's say you've created your own custom view named MyCustomView which extends the FrameLayout class and you've added to it your own xml layout (as defined in layout/mycustomview.xml), something like the following post:

http://adilatwork.blogspot.com/2011/08/android-make-custom-view-class-based-on.html

Now you want MyCustomView to change its background color or drawable when it's pressed or focused. The first thing you'll need to do is define a State List resource. This is done by creating an xml file in the res/drawable folder (let's called it res/drawable/mystatelist.xml) which has contents something like the following:

<?xml version="1.0" encoding="utf-8"?>
<selector
 xmlns:android="http://schemas.android.com/apk/res/android">
 <item
  android:state_pressed="true"
  android:drawable="@color/mypressedcolor" />
 <item
  android:state_focused="true"
  android:drawable="@drawable/myfocusedcolor" />
</selector>
We'll assume mypressedcolor and myfocusedcolor are colors defined in the res/values folder. The values of android:drawable of course needn't necessarily be a color but can alternatively be a drawable with value something like the following:

android:drawable="@drawable/mypresseddrawable"
Next, somewhere in MyCustomView we need to set its background resource to be the State List resource we just defined, and to also set MyCustomView to be focusable and clickable, as follows:

setBackgroundResource(R.drawable.mystatelist);
setClickable(true);
setFocusable(true);
Note that you're setting the properties (background resource, is focusable, is clickable) of MyCustomView itself and not the properties of the outermost node in the mycustomview.xml layout file which is added to MyCustomView (like I did mistakenly!).

That's it. You've defined a custom view and now it changes its background color or drawable when it is pressed or focused.

Tuesday 25 October 2011

Android: taking a picture and then deleting it from external storage

I've been playing with the bulit-in camera app today, launching it from within my app, taking a picture and then returning back to my calling activity (let's call it MyActivity) with an Intent containing a Uri instance pointing to the saved picture. I used the following guide to do this...

http://developer.android.com/guide/topics/media/camera.html#intents

... but with one difference: I didn't specify where to save the file, saving the picture instead in the default picture gallery location. Getting to the point of this post... say the Intent returned in the MyActivity.onActivityResult(int, int, Intent) method is named data and I get the Uri pointing to the picture out from data as follows:

Uri myPictureLocation = data.getData();

... Then, if I want to delete the saved picture once I am done with it, the thing to bear in mind is that myPictureLocation is not a file location but data pointed to by a content provider. So, you don't delete the picture as follows (like I tried!!)...

File myFile = new File(myPictureLocation.getPath());
myFile.delete();

...but instead you would chain the following method calls...

MyActivity.this.getContentResolver().delete(myPictureLocation, null, null);

Friday 14 October 2011

Android: parsing/formatting dates and currencies

I got back a date from an API call in the following format: "2008-03-29T00:00:00Z". To parse this String and get a Date instance, I created a SimpleDateFormat instance as follows...

SimpleDateFormat myDateTimeFormat = new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");

... and then parsed my String representation of a Date as follows...

String myDateString = "2008-03-29T00:00:00Z";
Date myDate = myDateTimeFormat .parse(myDateString);

... To get back the original String value from the Date instance I would call the format(...) method as follows...

myDateString = myDateTimeFormat .format(myDateString);

... In a similar fashion, if I wanted to format a number as a String showing the pounds sterling currency symbol and two decimal places, I could do something like the following...

double myNumber = 25;
DecimalFormat myCurrencyFormat = new DecimalFormat("£#.00");
String myFormattedNumber = myCurrencyFormat.format(myNumber);

... The value of myFormattedNumber in the above example would be "£25.00".

Both dates and currencies can be formatted smarter using pre-defined formats and locale information. The above is intended only as a quick guide to get you started parsing and formatting dates and currencies.

Android: creating an aynchronous task to make a http request

What we'll do to make an aynchronous http request is extend the AsyncTask class (overriding the doInBackground(...) and onPostExecute(...) methods) as follows...

public class MyAsyncTask extends AsyncTask<HttpRequestBase, Void, HttpResponse>
{
 @Override
 protected HttpResponse doInBackground(HttpRequestBase... httpRequests)
 {
  DefaultHttpClient httpClient = new DefaultHttpClient();
  HttpResponse response = httpClient.execute(httpRequests[0]);
  return response;
 }
 @Override
 protected void onPostExecute(HttpResponse httpResponse)
 {
  // handle response
 }
}

... and then instantiate the new MyAsyncTask class and call its execute(...) method passing in a HttpRequestBase instance as a parameter to make a http request. We could make this MyAsyncTask class smarter, constructing it with a DefaultHttpClient instance instead of creating a DefaultHttpClient instance in the doInBackground(...) method, or constructing the MyAsyncTask class additionally with a handler that reports back completion of the http request in the onPostExecute(...) method, or making changes to allow multiple simultaneous http requests to be dispatched. Hopefully though the above serves as a bare bones example to explain the general concept and to get you started.

Tuesday 11 October 2011

Android: how to make a RESTful GET request using Http basic authentication

Let's assume we're sending a request to the url https://mytargetdomain.com/verify to verify a certain username and password combination, and we'll get a 200 status code on success. The code for this is as follows:

DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.getCredentialsProvider().setCredentials(
 new AuthScope(null, -1),
 new UsernamePasswordCredentials("myusername", "mypassword"));
HttpGet httpGet = new HttpGet("https://mytargetdomain.com/verify");
try
{
 HttpResponse response = httpClient.execute(httpGet);
 StatusLine statusLine = response.getStatusLine();
 int statusCode = statusLine.getStatusCode();
 if (statusCode == 200) { /* authorisation successful, do something... */ }
 else { /* authorisation failed, do something... */ }
}
catch (Exception ex) { /* Exception caught, do something... */ }
httpClient.getConnectionManager().shutdown();

Of course, this is a non-asynchronous call, which is not recommended, but hopefully this post serves the purpose of showing how to make a RESTful GET request using Http basic authentication.