Brain Flush

January 21, 2012

Androitism – bits and bobs for the busy Android coder.

Filed under: Uncategorized — Matthias @ 2:46 pm

I did it. I am moving my blog to Posterous. If you’re interested in all sorts of technical short articles related to Android programming, here’s the link:

http://androitism.posterous.com

If you’re wondering who the hell I am (fair enough): I’m currently employed at Qype where I lead development in Qype’s mobile products team, the A-Team (Apps and API). I am an Android enthusiast and early adopter, with about 4 years of experience in Android programming (yes those days where Android was only–and barely–running on the Nokia i810), and I co-authored the Manning book Android in Practice. Some people may know me from my work on Droid-Fu / ignition, Signpost OAuth, Calculon, gradle-android-plugin and maven-android-plugin, and my tendency to start projects in my spare time and never finish them. There, I said it. Now go blame me for those Droid-Fu samples that I owe you since about 3 years.

October 31, 2011

Our Android book, Android in Practice, is here!

Filed under: Software Development & Programming — Tags: , — Matthias @ 11:34 pm

I just wanted to reach out quickly and mention that our book Android in Practice (AIP) is finally done, it’s available, and most importantly, it’s good–or at least we like to think so! Let the archer speak for himself:

Android in Practice - Book cover

Android in Practice - Book cover

To get the obvious question out of the way: why another book, and what do we think makes this one different from the many others out there? There’s a strikingly simple answer to that: we believed that back when we started, there were very few books, if at all, that covered Android application development in enough depth, with enough inside knowledge, to satisfy those who (want to) develop Android apps for a living. We wanted to go way beyond the standard Hello World thing, and I believe we achieved that with AIP.

How? First of all, Charlie Collins (now working for MOVL, creators of Poker Fun), Michael Galpin (formerly responsible for the Android app at eBay, now working for Bump Technologies) and I (responsible for the Qype Android app, and large parts of the infrastructure behind it) do exactly that: we build Android apps for a living. We have been working with Android ever since it was in alpha status, when there hadn’t even been actual devices to run the platform. We fell in love with it, and we spent three years since then diving into the platform details, finding problems, solving problems, and where we could, share our findings through blog posts or StackOverflow. Since we were hearing the same questions over and over again, we thought it was about time to pour all this into a more handy format, so here it is: Android in Practice is our take on the developer’s cookbook, containing those recipes–or techniques as we like to call them–we think will help most in making delicious apps, including:

  • A close look at the platform itself, why it’s Java, but why it actually isn’t, why it’s Linux, but why it actually isn’t, what it is comprised of from tools and middleware, to framework classes.
  • Okay, we also have a Hello World part. There, I said it.
  • An in-depth explanation of Android’s life-cycle and task model
  • A comprehensive chapter about UI, where we explain how Android renders views, how to write themes and styles (based on a post from my blog here), how to implement state and 9-patch drawables, how to write scalable UIs, etc.
  • We have an entire chapter on services, covering everything from running services in separate processes, communicating via IPC with other services, how to run process-local services and how to leverage Intents.
  • We also found many people struggle with concurrency on Android, so we added a chapter that focuses entirely on threading, tasking, and asynchronous message dispatching. Yes, AsyncTask is covered here.
  • Storing data is fundamental to many apps, so another chapter focuses entirely on that. From simple preference files to Preference activities to SQLite and ContentProviders, it’s all there.
  • Many apps these days fetch their data not from the device, but from the cloud. That’s why we’ve added a chapter that focuses on networking, HTTP, parsing XML and JSON, and along the way also let you in on a few secrets about how to make your network code rock solid.
  • No Android book could be complete without covering location. Hence, we’ve added a separate chapter focusing solely on best practices for writing location aware applications. The demo app for this chapter lets you find beer breweries near you. Selling argument??
  • We know people  love to use their smartphones to listen to music or watch videos, so multimedia was another big topic for us. In that chapter, we let you in on the details of streaming and recording music and videos in your apps, and how to let other applications retrieve that data from your apps.
  • Gaming is becoming huge on Android, so we felt the book would not be complete without adding a chapter on 2D and 3D drawing. Here we cover OpenGL, and how to render arbitrary shapes and text to a canvas.
  • If you think other books cover all those things as well, then we still have a few aces up our sleeves. Yes, we have a chapter on testing, and another one on build automation. We cover not only the basics like running unit and functional tests on a device, we also cover the thing only the cool kidz use, like Robotium and Robolectric, and yes, even the monkey! We also show you how to manage your builds with Maven and its Android plug-in, and to run your builds from a build server to satisfy all your automation needs.
  • Last but not least, the tablet thing did not simply rush past us. We have an entire chapter on tablet development, and how to use the ActionBar, Fragments, and drag and drop.
  • The appendix is also no slouch, since we have an in-depth coverage of SDK tools like ADB, ProGuard, and Monkeyrunner in there, and also touch on various other topics such as StrictMode, alternative languages, and WebView’s Java-to-JavaScript bridging capabilities.
Oh and did I mention we have sample apps for practically all of that? After all, it’s an “in practice” book. We have decided to put QR-codes in the book, so you can simply whip out your Android phone, scan the barcode while reading, and see the code being discussed in action! Just look for something like this:
So, if you feel like catching up on Android development, the book is currently on sale on Amazon! Or alternatively order directly on manning.com and get both the print and ebook editions. Oh right, a Kindle version will be available very soon, too.
And in the event you’ve already bought it, please, review us on Amazon. Good or bad, preferably good, but any feedback is appreciated. You can also drop by the author forum and leave us feedback there. We will consider all feedback for upcoming revisions of the book.
Thanks everyone and we hope you enjoy Android in Practice!

January 27, 2011

Stepping back from Signpost development

Filed under: Software Development & Programming — Tags: — Matthias @ 9:25 am

No post in such a long time, and then it’s even a sad one. I just wanted to reach out quickly and tell everyone who may be using my Signpost library for OAuth that I have ceased development of it. I am now looking for people willing to take over development and maintenance of the project.

Why is that? Well, I develop software not only for my day job, but also for fun. Developing Signpost hasn’t been fun anymore lately, since I was only fixing odd issues related to incompatibilities with all the different OAuth service providers out there. Moreover, I am putting all my effort into evolving the Android tools landscape for build automation and testing now, which I find to be a more challenging and also interesting and fun area. (If you’re interested, make sure to check out Jason Voegele’s Android plugin for Gradle, and also Calculon, an awesome Android test DSL I am developing).

That being said, give me a shout if you’re interested in taking over the Signpost project! I’d find it most disappointing to see it die.

Now have a fun and productive day.

March 21, 2010

Signpost 1.2.1.1 maintenance release

Filed under: Software Development & Programming — Tags: , , , — Matthias @ 11:46 am

Sorry for any inconvenience caused by the Signpost 1.2.1 release last week, which apparently regressed on callback URLs (see issue 34). That’s fixed in 1.2.1.1, along with another bug which prevented custom OAuth authorization headers to not be correctly interpreted before message signing.

Both should work fine now.

Have a nice weekend!

March 13, 2010

Signpost 1.2.1 released: fixes and features inside!

Filed under: Software Development & Programming — Tags: , , — Matthias @ 10:23 pm

I just released Signpost 1.2.1, which is mainly a maintenance release, but also contains a couple new features.

Here is what changed:

  • OAuthProvider has become more flexible. You can now override even more of its default behavior, e.g. for creating customized requests for the token handshake. I’ve also reduced code duplication by pulling code up from concrete provider implementations to the abstract base class, so you now only need to worry about implementing small, self-contained steps when implementing a custom provider, such as creating a custom request object.
  • OAuthProvider now sends token requests using POST, as suggested by the standard. You can change that behavior by overriding createRequest(endpointUrl), but that should hardly be ever required.
  • OAuthProviderListener is a new class that allows you to hook into the token handshake and intercept the flow at certain points (e.g. before and after message signing). This makes it easy for you to customize the request that is being sent, e.g. by setting custom headers or parameters. This deprecates setRequestHeader(), which was formerly used to do that, but which was very limited.
  • During token handshake, OAuth parameters are no longer being sent in a “mixed” way, i.e. they all go in one place now, depending on which SigningStrategy is used by the consumer. In earlier versions, OAuthProvider would always send the oauth_callback and oauth_verifier in the URL.
  • CommonsHttpOAuthProvider can now be configured with a custom HttpClient
  • During token handshake, unsuccessful server replies (e.g. 401 or 400) are not being swallowed anymore, instead the response body can now be retrieved from the exception that is thrown and be interpreted by the client.
  • The debug output has been extended to include the Authorization header and request URL (note that when using java.net.HttpURLConnection, one cannot read the Auth header for security reasons, and it will always print as null)

January 31, 2010

Signpost 1.2 released – now on Maven Central

Filed under: Software Development & Programming — Tags: , , , — Matthias @ 6:47 pm

I am happy to announce that I have released Signpost 1.2 earlier this week and I will briefly go over the changes the library has undergone. Most changes were under the hood, although there are also some minor API changes. I have rewritten much of the core code base, so as to make the library more flexible and easily extensible, something that was often requested by users.

Flexibility, extensibility, and general design improvements

I have flipped quite some bits in signpost-core, and now Signpost is finally more easily extensible and better configurable by developers. AbstractOAuthConsumer now lets subclasses override practically any step in the signing process, or even the entire signing altogether, by following the template method pattern. So if you need special treatment while collecting message parameters for signing, or want to use a different nonce generation algorithm, just override the respective methods in your subclass.

There is also a new class called SigningStrategy. This class defines how a signature is written to an HTTP request. The default behavior is to write OAuth parameters to the HTTP Authorization header (using AuthorizationHeaderSigningStrategy), but you can go ahead and create a custom strategy and configure your OAuthConsumer with it.

Speaking of customization. Should you be implementing your own OAuthConsumer, I have also improved the testability in that case tremendously. Simply inherit from OAuthConsumerTest and implement buildConsumer(). The test will then be executed for your particular consumer configuration.

There are also two API changes by which everyone will be affected. First, I have removed the SignatureMethod enum, since it was not very useful. Instead, every OAuthConsumer uses the HMac-SHA1 signature method by default, since that’s what everyone seems to be using anyway. So constructing a consumer is now simplified to:

OAuthConsumer consumer = new DefaultOAuthConsumer(CONSUMER_KEY,
                                     CONSUMER_SECRET);

If you really want to use a different signer, you can do this:

consumer.setMessageSigner(new PlaintextMessageSigner());

The second API change affects OAuthProvider. In earlier versions, consumer and provider were closely coupled. That led to problems in service oriented environments, where each object should be self-contained when exposed as a service. Thus, the retrieve*Token() methods of OAuthProvider now accept a consumer as the first argument:

String authUrl = provider.retrieveRequestToken(consumer, "http://example.com/callback");
// ...
provider.retrieveAccessToken(consumer, pin);

Android support

Signpost worked well on Android before, however, a bug in Android’s Java implementation (that would be Apache Harmony) prevented it to work correctly with certain service providers (HttpURLConnection is sending lower-case HTTP header names on Android, which breaks some server side OAuth implementations because they don’t recognize the Authorization header; see issue 20). I have therefore implemented a CommonsHttpOAuthProvider, which uses Apache HttpClient to receive tokens instead of HttpURLConnection.

New features

Signpost can now sign URLs. Just pass the consumer a URL string, and it will treat it as an HTTP GET message on the resource identified by the URL and append all necessary OAuth parameters to that URL. This can be very useful if you want to produce clickable links to protected resources:

String signedUrl = consumer.sign("http://example.com");

Another minor but useful feature is Signpost’s new debug mode. If you run your app with the -Ddebug flag, Signpost will now print the signature base string and generated signature for each request it signs to stdout. This is very useful when trying to figure out what went wrong should a server answer with 401 and you believe you did everything right:

[SIGNPOST] SBS: GET&http%3A%2F%2Ftwitter.com%2Foauth%2Frequ...
[SIGNPOST] signature: BVzjTYNjeJJwI4olm5ISHtvZ7Rc=

Bug fixes

Of course this release has seen some bug fixes, too. One of the most important ones is that Signpost does not send a blank oauth_token parameter anymore when retrieving a request token. Although permitted by the standard, and although many providers like Twitter or Google accept this, certain other providers failed when doing so (e.g. Netflix). If you still want to get the old pre-1.2 behavior, call setSendEmptyTokens(true) on your consumer.

Another important fix/enhancement corrects the way Signpost used to write to the Authorization header. Previously, it would just overwrite it with the OAuth parameters it generated, which caused problems when client needed to provide a realm paramter in the Auth header alongside the OAuth params. Signpost now remembers what had been in the Authorization header prior to message signing, appends its own params to it, and writes all of them back to the header. This should get rid of 401s where service providers expect a security realm to be set.

Finally, a problem was corrected where x-www-form-encoded body params were ignored if the content type contained parameters like encodings.

Project reports / API docs

I have also finally uploaded the API docs and other project reports generated by the Maven site plugin to GitHub pages, so you can browse the API docs without linking the JavaDoc JAR. You can find all project reports and other generated information here: http://kaeppler.github.com/signpost/project-reports.html

Maven Central

Last but certainly not least: Signpost 1.2 is now available via Maven Central, which means you do not have to add the signpost-releases repository to your POM anymore. It is available straight away in any Maven powered Java project. Om nom!

January 10, 2010

Introducing Calculon – a Java DSL for Android Activity testing

Filed under: Mobile Devices, Software Development & Programming — Tags: , , — Matthias @ 1:05 pm

I have been working on a new test library for Google Android lately, a project which I’m very excited about, and which I feel has loads of potential: Calculon, an Android testing library which lets you write functional tests for your Activities using a very concise and natural syntax.

I am a big fan of test-driven development, and I think there’s no arguing about the massive benefits you get from backing your software up with an automated test suite. The support for writing tests in Android, however, is lacking at best. Even though there has been a test runner since the 1.0 days, writing unit or functional tests in Android is far from being a pleasant experience. For me, the two most important things about tests are that they must be easy to write, and more importantly, easy to read.

That being said, here is a classic example of why Android testing sucks. Our test story is:

Assert that a click on ‘button’ launches a new BarActivity.

Without Calculon, what you do is this:

public void whatInHeavensNameDoesThisEvenTest() {
    final Button b = (Button) getActivity().findViewById(R.id.button);
    ActivityMonitor monitor = getInstrumentation().addMonitor(
        BarActivity.class.getCanonicalName(), null, false);
    getInstrumentation().runOnMainSync(new Runnable() {
        public void run() {
            b.performClick();
        }
    });
    getInstrumentation().waitForIdleSync();
    assertTrue(getInstrumentation().checkMonitorHit(monitor, 1));
}

So, I first have to retrieve a reference to the button that’s supposed to launch a new BarActivity. Then I have to create what Android calls an ActivityMonitor, that’s simply an object which just sits there and waits until an Activity is being launched that matches the description it was configured with. Then I have to perform the actual button click, but sorry, not allowed on the instrumentation thread, so I have to runOnMainSync(). We’re not yet there though: we have to sit and wait, because launching a new activity could take a while, so we also have to waitForIdleSync(). The assertion that follows also couldn’t be less expressive.

When I first wrote this test, my single thought was: Where the heck is my story? It’s buried under a heap of ugly boilerplate code.

I don’t care that the test runner cannot perform a view event on the instrumentation thread. I don’t care that it needs to sit and wait for the Activity to launch. I don’t care about ActivityMonitor and its crummy API. I just want to look at the test, and understand what it’s doing.

Let’s reiterate our test story:

Assert that a click on ‘button’ launches a new BarActivity.

With Calculon, this test is written as:

assertThat(R.id.button).click().starts(BarActivity.class);

Oh the beauty. Our test story was a single sentence, so is the test. That’s how it should be, really. There’s nothing worse than seeing someone else’s tests failing on the build server and having to dissect them line by line to figure out what it’s actually testing.

So let’s move on and look at some nifty Calculon tests. And remember: “Calculon never does two takes!”

Testing with Calculon

Calculon is in a very early stage of development, and currently it only supports writing functional Activity tests, using Android’s ActivityInstrumentationTestCase2. Here is what a Calculon test looks like:

public class FooTest extends FunctionalTest<FooActivity> {
    public FooTest() {
        super("com.example", FooActivity.class);
    }

    public void testStuff() {
        ...
    }
}

Nothing special here, really. You just inherit from a Calculon FunctionalTest.

Assertions

At the heart of a Calculon test are assertions. To create a new assertion, you use the assertThat() method:

public void testStuff() {
    // testing against activities
    assertThat()...
    assertThat(getActivity())...
    assertThat(someOtherActivity)...

    // testing against views
    assertThat(R.id.some_button)...
    assertThat(someButton)...

    // of course all Junit assertions work as well
    assertEquals(...)
    assertNotNull(...)
    ...
}

For now, there are two basic kinds of assertions: ActivityAssertion and ViewAssertion. There is also a third kind, ActionAssertion, but it takes a somewhat special role and is discussed at the end.

Activity Assertions

An ActivityAssertion is an assertion on the state of an Activity and is used like this:

public void testStuff() {
    // testing for an orientation
    assertThat().inPortraitMode();

    // testing for views
    assertThat().viewExists(R.id.some_button);

    // testing for input actions
    assertThat().keyDown(KeyEvent.KEYCODE_BACK)...

    // testing for custom predicates
    assertThat().satisfies(new Predicate<Activity>() {
        public boolean check(Activity target) {
            return target.isTaskRoot();
        }
    });
}

View Assertions

A ViewAssertion is basically the same, just that it tests the state and behavior of a view:

public void testStuff() {
    // testing for view state
    assertThat(R.id.button).isVisible();
    assertThat(R.id.button).isGone();

    // testing for input actions
    assertThat(R.id.button).keyDown(KeyEvent.KEYCODE_BACK)...
    assertThat(R.id.button).click()...
    assertThat(R.id.button).longClick()...

    // testing for custom predicates
    assertThat(R.id.button).satisfies(new Predicate<View>() {
        public boolean check(View target) {
            return target.getVisibility() == View.VISIBLE;
        }
    });
}

Action Assertions

This is a special kind of assertion. You always use it when you want to assert that some action (e.g. a click or a key press) does something. You can use it on both activity and view assertions, and it also allows you to delegate an assertion to another object:

public void testStuff() {
    // testing for actions that launch a new activity
    assertThat(R.id.b1).click().starts(BarActivity.class);

    // testing for actions that finish an activity
    assertThat(R.id.b2).keyDown(KeyEvent.KEYCODE_Q).finishesActivity();

    // testing for actions that change something
    assertThat(R.id.b3).click().implies(R.id.b2).isGone();
    assertThat(R.id.b4).click().implies(getActivity()).inLandscapeMode();
    assertThat(R.id.b5).click().implies(new Predicate<Model>() {
        public boolean check(Model target) {
            return target.someAttribute() == 5;
        }
    });
}

There’s more to come!

This is only a very early version. I intend to expand this library significantly over time. Of course it’s open source, so contributions are always welcome. You can fork the project on GitHub, add your changes, and send me a pull request.

December 10, 2009

Qype Radar v2.3 now on Android Market! Adds vouchers and location sharing

Filed under: Qype — Tags: , , — Matthias @ 12:48 pm

We’ve just released a new version of Qype Radar for Android, boasting a completely re-designed user interface, vouchers / deals for places, location sharing via Twitter, SMS, etc., a photo gallery and support for Qype Italy.

From the Qype UK blog:

Today sees the latest iteration of the application, launched for Android phones (and coming soon to Apple’s iPhone), which introduces a suite of new features including the availability of special offers, a redesigned interface, reviews from Italy, and real time updating.

Moreover:

Qype vouchers have also been included in this new version of Radar, so you can track down exclusive discounts and special offers while you’re on the move. Plus the whole interface has had a makeover, making the whole thing that bit slicker; and of course we’ve added all the reviews from the recently-launched Qype Italy.

You can download the new version via Android Market in Austria, Denmark, France, Germany, Ireland, Italy, Luxembourg, Netherlands, Norway, Poland, Spain, Sweden, Switzerland and the UK.

November 23, 2009

Droid-Fu, Part 2: WebImageView and WebGalleryAdapter

Filed under: Software Development & Programming — Tags: , — Matthias @ 11:19 pm

This is the second in a series of posts about Droid-Fu, a shiny new shared library for Android application developers. In this post I will introduce two very handy components: WebImageView and WebGalleryAdapter.

WebImageView: Buy one, get two!

Many mobile apps make heavy use of web based content, especially photos, avatars, and other images. The problem with that is: you have to download the images before being able to display them, which has basically three important implications:

  1. the download has to be asynchronous, otherwise your UI will lock up
  2. while the download is processing, you have to keep the user happy by displaying some kind of progress indicator
  3. downloading stuff means you’re sucking away on your user’s quota, hence, you typically want to cache downloaded images.

That sounds like an awful lot of stuff to care about for achieving a rather underwhelming effect: displaying an image. Fortunately, there is a dead simple way to get all this in one handy small package: Droid-Fu’s WebImageView.

Here is an example of what it can look like. The first screenshot shows WebImageView in its loading state, using a grey solid background (of course you can change that) and the stock progress spinner (you can change that, too). The second screenshot shows the fully loaded image.

 

Using WebImageView

If you haven’t already downloaded and linked the Droid-Fu JAR to your project, do that now. Then, in your layout, add this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:droidfu="http://github.com/droidfu/schema"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:background="#FFF"
    >

  <com.github.droidfu.widgets.WebImageView android:id="@+id/webimage"
      android:layout_width="75dip"
      android:layout_height="75dip"
      android:background="#CCC"
      droidfu:autoLoad="true"
      droidfu:imageUrl="http://www.android.com/images/opensourceprojec.gif"
      droidfu:progressDrawable="..."
      />

</LinearLayout>

All arguments are optional, this allows you to define your view first, and then trigger loading the image programatically using WebImageView.loadImage(). Easy, huh?

Caching

WebImageView is backed by ImageLoader, Droid-Fu’s generic way of fetching images from the web. ImageLoader itself is backed by a two-level cache. When you load an image using WebImageView (or ImageLoader), what happens is that the 1st-level (in-memory) cache is queried for the required bitmap. If it’s a hit, it’s served immediately. If it’s a miss, the request drops through to the 2nd-level cache, which is the disk cache. Droid-Fu uses your app’s cache directory, which is managed by Android, so you don’t have to worry about maintenance stuff. If this request also misses, then WebImageView will finally go ahead and download the image from the web.

Be careful not to set the cache size too big. Cache size is currently defined in terms of “number of images” instead of “number of bytes”, so if you know you’re gonna download large high-res images, set this to a small value, otherwise you’ll see OutOfMemory errors. Forget that last paragraph. Meanwhile, I have changed the in-memory cache implementation. It’s now a weak-reference backed hash created by the Google Collections MapMaker, the capacity of which will automatically scale with the available memory. Simply put, if there’s not enough memory left, any cache entry will be garbage collected, unless there is still a strong reference to it (e.g. because it’s currently displayed to the user).

WebGalleryAdapter

So how else can you make use of this? Well, I don’t know, but I know that I already made use of this when implementing WebGalleryAdapter. This class serves as an adapter for Android’s Gallery widget, and it’s completely plug-and-play: Create your gallery, call setAdapter() with a WebGalleryAdapter instance, and pass it a bunch of image URLs. Whenever the user then scrolls/flings through the images in your gallery, the images will be fetched automatically from the web, with all the features such as caching and progress indication as described before.

November 16, 2009

Introducing Droid-Fu for Android: BetterActivity, BetterService and BetterAsyncTask

Filed under: Software Development & Programming — Tags: , — Matthias @ 9:54 pm

This is the first in a series of posts about Droid-Fu, a shiny new shared library for Android application developers. In this post I will introduce some of the ideas behind Droid-Fu, and start by showing off some of its core features.

What is Droid-Fu?

  • Droid-Fu is a general purpose Android application library, deployed as a JAR
  • Droid-Fu’s primary purpose is to make your Android developer life easier
  • Droid-Fu is open source! (fork it, hack it, share it, all on GitHub)
  • ain’t that enough?

Droid-Fu contains utility classes as well as some self-contained, ready to use Android components, all of which I consider useful for typical Android applications. Some of the areas for which Droid-Fu offers support classes include:

  • application life-cycle
  • background tasks
  • HTTP messaging
  • (remote) image handling
  • custom adapters

… and more. The library is still young, so expect to see a lot more stuff forthcoming!

Who uses it?

Droid-Fu contains mostly code which I pulled from Qype Radar, our geo-sensitive mobile application which let’s you find, review, and share all those cool places near you. In other words, Droid-Fu is used in a production quality app, and even though it’s a WIP, we find it to be quite solid. Of course you’re invited to make it even better. Did I mention it’s open source?

The Foundations

One of the strongest (in my opinion) benefits of using Droid-Fu are its application life-cycle helpers. If you are developing an application which performs background work, such as fetching data from the web, you will almost definitely want to Droid-Fu-idize your app. Here’s why.

That Dratted AsyncTask

I’ve written about this two times now. I think with this third approach, which made it into this library, I finally found a decent solution. But, let’s review the biggest problem with Android’s AsyncTask, first. What is AsyncTask? It’s Android’s helper class you’re supposed to use for performing expensive (that means, blocking) operations. If you’re writing an app that talks to a web service, you’ve very likely already used it. (You’re not doing all that work on the UI thread, do you? If you do, chances are your activity will only live for a couple seconds, because Android kills non-responsive activities. ANR, anyone?)

So the basic idea is: launch an AsyncTask making your service call, show a nifty progress dialog while the task thread is running, and have the task’s result be posted back to your activity once it completes. Cool, but what if the user decides to rotate the screen while your task is running? Or a phone call comes in, interrupting your app, and Android decides to kill it? Both these actions will effectively terminateyour activity, and recreate it when resuming (yes, a screen rotation kills your activity, very clever, isn’t it?). Unfortunately, any AsyncTask that was still running now holds a stale reference to your activity, because the restarted activity will be an entirely different object in memory (and it will go through onCreate(), as if the activity had started for the first time). I’m not entirely sure whether AsyncTask will actually post back the data to the old activity object (if it was a weak reference, it may already have been garbage collected), but in any case, your “new” activity will never see it, because it’s a different instance.

Now, one could argue: well, just do all the work again, like, re-send the request or whatever job was running. Yes, you could do that. But that’s wasteful and, really, makes you feel stupid, no? Plus, if the user triggers a web service request, then flips the screen, decides that this wasn’t helpful, and flips it back, then your request is being sent 3 times in parallel. Is that what you want? Probably not.

BetterAsyncTask to the Rescue

Thanks to Droid-Fu, there’s a solution to this: BetterAsyncTask! (I’m a lazy person, and I couldn’t come up with a better name). It behaves exactly like AsyncTask (in fact, it is an AsyncTask), but it does some extra work for you: first and foremost, it keeps track of the active instance of the context that launched it, and if that instance should change, it will post the data back to the new instance. In other words, you can dispatch your task, flip the screen back and forth mentally, and BetterAsyncTask will still post the task’s result back to whatever activity instance is alive at the time it finishes. In other words, the task is only ever run once, regardless whether the context in which it was launched died while it was running or not.

There’s a catch though. Since there is no way for BetterAsyncTask to figure out which one is the current instance of its activity, it relies on a helper: DroidFuApplication. This class derives from Application, and if you want to use BetterAsyncTask, your application has to derive from that class, otherwise it won’t work. That’s because DroidFuApplication keeps a hash of WeakReferences mapping contexts (activites and services) to their active instances, and when a BetterAsyncTask finishes, it will ask your application for the active instance.

This is all you have to do to launch a task showing the standard Android indeterminate progress dialog:

public class MyActivity extends BetterDefaultActivity {

 protected void onResume() {
   super.onResume();

   if (isLaunching()) { // this is explained further down this article
     MyBetterAsyncTask task = new MyBetterAsyncTask(this);
     task.execute(someData);
   }
 }

}

It doesn’t end here though. BetterAsyncTask does other cool stuff, such as automatically opening and closing progress dialogs for you while it’s running, or triggering that little progress spinner in the activity title bar when your activity has enabled that feature. It also allows your task to throw exceptions in its worker method, which are then posted to an error handler you define. Some of that stuff, like spawning dialogs, only works if your activities inherit from BetterActivity, which I will get to now.

BetterActivity and BetterService: Pimp my context!

Droid-Fu provides base classes for your activities and services which provide some simple but very useful helper methods. Currently, there are only BetterDefaultActivity, BetterListActivity and BetterService, but I intend to implement the Better* stuff for all stock Android activity base classes (like MapActivity and all the others).

Here is what you get:

Life-cycle helpers

these methods let you conditionally perform work depending on a context’s life-cycle state.

  • isLaunching() is true if and only if the context just went through onCreate() for the first time (but was not restored, i.e. onRestoreInstanceState() was not called)
  • isRestoring() is true if your context is recovering after being killed by Android
  • isResuming() is true if your context is “soft-resuming” as I call it, i.e. there was no call to onCreate() before going through onResume()
  • isApplicationBroughtToBackground(): sometimes it’s necessary to distinguish between your activity being paused by another activity of your own application, or by an entirely different application. This method yields true if another application’s activity is hiding yours.

Dialog helpers

BetterActivity offers the following helper methods to easily let you spawn dialogs:

  • showInfoDialog(): shows an alert dialog with an info icon
  • showAlertDialog(): shows an alert dialog with a warning icon
  • showErrorDialog(): same as alert dialog, but takes an exception as an argument
  • showListDialog(): shows a dialog with a list of Ts (T is some generic type). When clicking an entry, it will call back to a handler with the T that was selected.

all dialogs are customizable (e.g. message or icon).

There is more to come!

There’s a lot more in Droid-Fu at the moment (will cover that in upcoming posts), and there will be even more in the future, since I’m continually working on this library.

Cool, where can I get it?

The Droid-Fu source code is currently hosted on GitHub, which is the place where the cool kidz hang out these days. It’s a maven project, but the JARs aren’t yet hosted anywhere. Anyway, just check it out using git clone:

git clone git://github.com/kaeppler/droid-fu.git

and run:

mvn install -DcopyTo=path/to/your/apps/lib/dir

(you need to install git and maven2 for all that magic to work).

Happy coding!

Older Posts »

The Shocking Blue Green Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 37 other followers