Joe Moore's blog



Joe MooreJoe Moore
Introducing Android IntelliJ Starter and Android CI
edit Posted by Joe Moore on Tuesday August 09, 2011 at 06:33AM

We have been doing quite a bit of Android development over the last year and a half at Pivotal Labs. Over time we have compiled a set of go-to tools, and libraries, and configuration settings that help make our development process as productive as possible. We are excited to publish two open source projects, each with the goal of helping new Android development projects hit the ground running: Android IntelliJ Starter and Android CI.

Joe MooreJoe Moore
Fast Android Debugging with IntelliJ
edit Posted by Joe Moore on Friday July 15, 2011 at 12:41PM

Sure, you can launch your Android app in IntelliJ's debugger, but that's slow. IntelliJ allows you to dynamically attach the debugger to a running device using the "Attach debugger to Android process" button. That's fast!

Joe MooreJoe Moore
Android Tidbits 6/23/2011: Tabs and Colors
edit Posted by Joe Moore on Thursday June 23, 2011 at 07:19AM

Pivotal Android Tabs

We have published a simple Android project that illustrates how to use tabs in an Android app: TabActivity, TabHost, TabWidget, and android:divider. Thank you Pivot Ryan, the original author, for taking the time to write and open source this. Check it out, fork it, and enjoy -- https://github.com/pivotal/Pivotal-Android-Tabs

Tabs 1

Tabs 2

See Hex'd Colors

IntelliJ trick: in a colors.xml file, place your cursor on a hex value and hold down Shift. You'll see a large preview of the color.

Hex colors in IntelliJ

Colors and States

(Repost from the 6/22/2011 Standup blog): You can use a selector drawable to set Android text color for the various states (focused, selected, etc.) using a drawable xml file. IntelliJ will complain and say this is invalid syntax but the application will use the file as you would expect. This only seems to work for the android:textColor attribute in TextViews.

Joe MooreJoe Moore
Android Tidbits 6/22/2011: Hiding Header Views
edit Posted by Joe Moore on Wednesday June 22, 2011 at 08:01AM

Android ListView#addHeaderView and ListView#addFooterView methods are strange: you have to add the header and footer Views before you set the ListView's adapter so the ListView can take the headers and footers into consideration -- you get an exception otherwise. Here we add a ProgressBar (spinner) as the headerView:

// spinner is a ProgressBar
listView.addHeaderView(spinner);

We'd like to be able to show and hide that spinner at will, but removing it outright is dangerous because we'd never be able to add it again without destroying the ListView -- remember, we can't addHeaderView after we've it's adapter:

listView.removeHeaderView(spinner); //dangerous!

So let's hide it! Turns out that's hard, too. Just hiding the spinner view itself results in an empty, but still visible, header area.

Joe MooreJoe Moore
Android Tidbits 6/21/2011: Unregister? Nah!
edit Posted by Joe Moore on Tuesday June 21, 2011 at 09:51AM

C2DM Unregister Issues

It turns out when you follow the client-side C2DM unregistration process, this does not guarantee that those registration tokens are permanently unregistered for that device.

If we unregister as specified above and then send a push notification to that registration_id, the server receives an Error=NotRegistered as expected.

But, unexpectedly, when that device re-register with C2DM (and getting a new registration_id), the old registration_id is reactivated as well and can receive push notifications and does not result in a server-side Error=NotRegistered.

The end result: we implemented our server-side API to take both the new and old registration_ids when the Android client successfully registers with C2DM, allowing us to manually delete the old registration_id.

Drawable XML Files

Prefixing the name of a drawable xml file with "active_" seems to prevent android from using that drawable at all.

Joe MooreJoe Moore
Syncing IntelliJ Android .apk Files Using Dropbox
edit Posted by Joe Moore on Thursday June 16, 2011 at 01:26PM

During a typical day of Android development we compile Android applications (.apk files) dozens of times, deploying to emulators and devices simply by pressing the Run button in IntelliJ. This is great for our in-office developers, but it's more difficult for our remote-pairing developers to install those same .apks on their own emulators and phones. As a remote developer, I wanted seamless, instant access to all .apks we build during development. Using Dropbox and some IntelliJ configuration changes I now have all .apks we build available for me to install on my local emulators and phones just seconds after we build them on our development machines, 2500 miles away.

Joe MooreJoe Moore
Android Tidbits 6/13/2011: Great Expectations
edit Posted by Joe Moore on Tuesday June 14, 2011 at 07:29AM

Great Expectations

Most of our Android projects are using great-expectations, which brings Jasmine-style test assertions. Thanks, Xian, for writing this!

Robolectric Enhancements -- Stay Tuned

We have a bunch of Robolectric enhancements, including the ability to wire up BroadcastReceivers by just declaring them in AndroidManifest.xml. We'll have to put some pull-requests together soon.

Roboguice uses Robolectric!

We use Roboguice on most of our Android projects for dependency injection. We discovered that Roboguice is using Robolectric for unit testing. Awesome!

Roboguice using Robolectric

Joe MooreJoe Moore
Android Tidbits 6/9/2011: CD2M Resources
edit Posted by Joe Moore on Friday June 10, 2011 at 07:16AM

C2DM

One of our projects just started implementing the Android Cloud to Device Messaging (C2DM) framework. We'll keep you posted as we progress through the many pieces of this implementation. Various resources include:

  • Official Google code page: Google Projects for Android: C2DM
  • Sign up for the service -- you'll need a Google account, like GMail or a hosted Google account.
  • There is no official Android client library for handling these messages. There is a de-facto standard set of classes, as used in JumpNote and Google Chrome to Phone Extension. Most blog and forum posts say something like "Download those classes and tweak as needed."
  • Wei Huang from Google posted an article about implementing C2DM.
  • Now for the Ruby part -- wait, Ruby? Yes, there is a big server-side component to C2DM. Your message-pushing server must not obtain an authorization token from Google to communicate with the service, but also keep track of the authorization tokens from each device that needs to receive push notifications. We are implementing a server-side API for our devices to register their C2DM tokens. Also, the awesome folks at GroupMe have open sourced a c2dm gem for Ruby servers to both authorize with Google and post notifications.

Joe MooreJoe Moore
Android Tidbits 6/8/2011: Warning! Warning!
edit Posted by Joe Moore on Thursday June 09, 2011 at 10:00AM

Un-shadowed Method Warnings!

In response to yesterday's question about Un-shadowed Method Warnings, Pivot Tyler points out that you can turn these on by calling Robolectric.logMissingInvokedShadowMethods(). Thanks!

Bad cached-robolectric-classes.jar

On two workstations every unit test was failing with the following error:

// …many levels of stack trace, finally:
Caused by: com.xtremelabs.robolectric.bytecode.IgnorableClassNotFoundException: msg because of javassist.NotFoundException: android.content.DialogInterface$OnShowListener
at com.xtremelabs.robolectric.bytecode.AndroidTranslator.onLoad(AndroidTranslator.java:80)
at javassist.Loader.findClass(Loader.java:340)

Cause: there was an old tmp/cached-robolectric-classes.jar that was causing these errors and our tests ran successfully after deleting it. That's two answers from Pivot Tyler!

Don't DDOS Yourself With Your Own App

The Bump Android team wrote an article about a good idea gone wrong. Moral of the story: not all devices behave the same, and this might cripple your servers rather than the devices.

Robolectric Google Group

Join it, contribute, and learn about unit testing your Android apps.

Joe MooreJoe Moore
Pivotal Android Tidbits 06/07/2011
edit Posted by Joe Moore on Wednesday June 08, 2011 at 06:53AM

We're trying an experiment: since we currently have several Android projects at Pivotal Labs, and Android development and testing is hard, we are going to post to the blog the tips, tricks, gotchas, and conundrums we find.

Emulator and Orientation

Android will destroy and recreate activities upon screen orientation change. One way to prevent this is to set android:configChanges="orientation" in your AndroidManifest.xml (article here):

<activity android:name=".activities.MyActivity"
          android:configChanges="orientation"/>

This prevents android from calling onPause() => onDestroy() => onCreate() on a device, but not within the emulator; annoyingly, the Activity is still recreated within the emulator.

Un-shadowed Method Warnings?

Once again we spent about 15 minutes debugging a failing unit test only to find that there was no Robolectric implementation/shadow for one of the Android methods under test (ArrayAdapter#insert in our case). I would be nice to have a "warning mode" where Robolectric would log warning for all un-shadowed methods. I wish we knew the guys who wrote Robolectric…

Other articles: