Inspired by the URL-as-question meme sites http://has the large hadron collider destroyed the world and http://should I use tables for, I present http://how many spaces after a

Audible on Android (and other devices)

I love my new G1, but it doesn't work with Audible yet. Fortunately, I have a workaround. This guide describes how to get audiobooks onto a G1. You'll need a Mac and $40 worth of software.

Download and install Tune4Mac. This app creates a virtual CD burner on your Mac, so when you tell iTunes to burn a CD, you don't actually need a blank CD-R. It's a clever hack, and the software works as promised. There's a Windows version, but I haven't tried it.

Register Tune4Mac. It's $39.95. You'll get the license key to your email immediately, paste that in the app's Registration dialog.

Configure AAC output in Tune4Mac. Tune4Mac automatically encodes audio to either MP3 or AAC. I tried MP3 encoding, and it was flaky, but AAC encoding worked just fine. Save this change by closing the dialog.

Add audiobooks to iTunes. Purchase DRM-protected books from If this is your first time using Audible, choose format #4, a high quality format that works with iTunes.

Create a playlist in iTunes. iTunes burns CDs using playlists, and we're going to be burning a virtual CD. I used a different playlist for each part of my two-part audiobook.

Prepare the fake burn. Click the 'Burn Disc' button in the bottom right corner of the iTunes app. Select Tune4Mac Virtual CDRW, Maximum Possible, Audio CD, none and Include CD Text. Click burn.

Burn fake CDs. Click 'Burn' on the dialog, and then Audio CDs on the dialog that follows. It took an hour for my computer to burn all the virtual CDs for an entire book. During this time, Tune4Mac automatically cycles fake blank CDs so you can go grab a coffee.

Use Finder to transfer the book to your device. I opened the Documents folder, and then the Tune4Mac folder to find my audiobook file. I plugged my device into my Mac, causing an icon for it to show up in the Finder. I dragged the .m4a file to this icon to transfer the book.

Eject the device. In the Finder, click the device's eject icon before detaching it. Otherwise the transfer might not finish properly.

Enjoy! You can now enjoy audiobooks on your device. Unfortunately, some devices don't bookmark audiobooks, so you'll need to remember your place when you stop listening.

Disclaimer: I admit that this process is painful and expensive. Hopefully Audible follows Amazon's lead and makes DRM-free audiobooks available for purchase. That way, Audible's huge library will be available to a larger audience.

Guice punches erasure in the face!

Java 5 Type Erasure is frustrating. I'm coding along, enjoying the glorious type safety of generics. And then I try to do a little more with the Ts, and erasure shows up, "You can't do that!" I can't test an object if it really is a T. I can't inspect T.class using reflection. And I certainly can't new up a T. Yuck.

We're in a unique situation with Guice. Its type literals and injection points have complete generic information. It can follow long chains of type variables throughout an object model. In my app, I've got a Robot<T> that injects a Claw<T>. When I request a Robot<Adamantium>, Guice knows to find an adamantium claw.

And now, this type information is available to application code. I can write a Claw<T> class that actually knows what T is at runtime!

Consider GuardingList<T>, which enforces type safety at runtime:
class GuardingList<T> extends AbstractList<T> {
private final TypeLiteral<T> elementType;
private final ArrayList<T> delegate = new ArrayList<T>();

GuardingList(TypeLiteral<T> elementType) {
this.elementType = elementType;

public boolean add(T t) {
"Cannot add %s which is not of type %s", t, elementType);
return delegate.add(t);

public T get(int i) {
return delegate.get(i);

public int size() {
return delegate.size();
When injected, Guice applies its type knowledge to inject the correct TypeLiteral<T>. The GuardingList blows up when I add an invalid element:
  public static void main(String[] args) {
Injector injector = Guice.createInjector();

List<String> listOfString = injector.getInstance(
new Key<GuardingList<String>>() {});

/* totally unsafe, but this compiles and runs */
List<Object> rawList = (List) listOfString;

/* throws an IllegalArgumentException, since the GuardingList
knows that its elements must be Strings */
Types are the natural currency of Java. Erasure is frustrating 'cause it takes them away from you at runtime. And now Guice can give 'em back.

Reify today.