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!


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!


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


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.

(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.
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.

Now try to hide the spinner:
spinner.setVisibility(View.GONE);
Result: header area still visible with an ugly space:

The solution is to put the progress bar in a LinearLayout that wraps it’s content, and hiding the content. That way the wrapping LinearLayout will collapse when its content is hidden, resulting in a headerView that is technically still present, but 0dip high:
<LinearLayout
xmlns:a="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- simplified -->
<ProgressBar
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Then, set the layout as the header:
spinnerLayout = getLayoutInflater().inflate(R.layout.header_view_spinner, null);
listView.addHeaderView(spinnerLayout);
And when we need to hide it, hide the layout’s content, not the layout:
spinnerLayout.findViewById(R.id.spinner).setVisibility(View.GONE);
Now the header disappears from view. No more ugly space at the top!
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!
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!
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.
Join it, contribute, and learn about unit testing your Android apps.
Regular Selenium tests (in Java) might look like:
selenium.open("/login");
selenium.type("id=username", "bob");
selenium.type("id=password", "password");
selenium.click("Login");
selenium.waitForPageToLoad();
selenium.click("My Account");
selenium.waitForPageToLoad();
assertEquals("bob", selenium.getText("//table[2]/tr[3]/td[2]/");
After a few tests, this kind of thing becomes painful to manage. The typical solution is to create a bunch of constants for IDs and Xpaths, but that doesn’t help too much.
Fellow Pivot Mike Grafton came up with a cool pattern for improving on this. The idea is to create a class representing each page of your web app. Each class contains two types of methods: a bunch of action methods (clickMyAccountLink(), typeUsername()), and a bunch of inspection commands (isLoginButtonEnabled(), getLoggedInUsername()).
When an action takes you to a new page, the corresponding action method returns a new class representing that page. When it stays on the same page, the method just returns “this”. This allows methods to be chained to make the tests more readable.
Here’s how that test would look using this new pattern:
MyAccountPage myAccountPage = new LoginPage(selenium)
.typeUsername("bob")
.typePassword("password")
.clickLoginButton()
.clickMyAccountLink();
assertEquals("bob", myAccountPage.getLoggedInUsername());
The constructor of each page class should validate that it’s on the correct page (waiting if necessary, and perhaps asserting on the page title).
For the millionth time, cause I always forget…
Put this in ~/.bashrc:
export JAVA_HOME=/Library/Java/Home
[UPDATE: or this, which according to Mike Swingler, follows the Java version chosen in Java Preferences:
export JAVA_HOME=`/usr/libexec/java_home`
]
Also, run “sudo visudo” and add the line
Defaults env_keep += "JAVA_HOME"
or else commands like “sudo gem install” won’t be able to find Java.
Without the above, I got the following error (which seemed to have been run through a baby-talk filter) when running “sudo gem install rjb”:
extconf.rb:44: JAVA_HOME is not setted. (RuntimeError)
I’m writing Selenium tests again, which means a lot of XPath. Here’s a trick I learned thanks to this article on Push Button Paradise.
The problem is, how do you write XPath that matches one class in a multi-class element like
<div class='foo bar'>
? The standard XPath equality operator matches a full string, so
//div[@class='foo']
won’t work. The solution is arcane but I promise it works:
//div[contains(concat(' ',normalize-space(@class),' '),' foo ')]
Note that there must be spaces on either side of the class name ‘foo’.
Since this is quite a mouthful, I’ve extracted it into a helper method. Here it is in Java:
/**
* Generates a partial xpath expression that matches an element whose 'class' attribute
* contains the given CSS className. So to match <div class='foo bar'> you would
* say "//div[" + containingClass("foo") + "]".
*
* @param className CSS class name
* @return XPath fragment
*/
protected static String containingClass(String className) {
return "contains(concat(' ',normalize-space(@class),' '),' " + className + " ')";
}
After about two years in which the only Java I wrote had a “Script” after it, I’ve recently started working in my old favorite language again. It was clear to me long before I made the leap that somewhere along the line Java took a sharp turn towards Scarytown. (Maybe the writing was on the wall when the “Hello World” program comprised five lines, two declarations, and a static reference, but back in 1995 we were all so excited about getting objects without C++ that our judgement was clouded.)
Anyway, I will always have a place in my heart for the old bird (picture a portly English matron with flower dress and pocketbook and floppy hat), but Stu at Relevance Blog points out why coding in Java now feels like trying to sprint with 30-pound weights strapped to my ankles.
Java is a high-ceremony language. At every turn, Java enforces a high busy-work/real-work ratio. Specifically:
- Java’s checked exceptions bloat code, make components harder to use and maintain, and lead to tons of boilerplate code, each line of which is a bug-in-waiting.
- Java’s new operator/constructors cannot pick a return type. The amount of code that exists only to work around this is staggering. Two entire cottage industries have sprung up to deal with this single issue: factory patterns and dependency injection.
- Java has no metaprogramming features to automate common tasks such as field accessors, standard constructors, and simple delegation.
- Primitives, functions, and classes are not first-class objects, leading to huge code bloat to deal with these types specially.
- Java’s core reflection and interception capabilities are clunky, requiring tons of bolt-on technologies to make them workable, including AOP, annotations, and code generators.
That’s a pretty big stink, but if you are used to it you probably can’t smell it anymore.
(And that’s not even mentioning the prevalent idioms of programming with massive amounts of indirection and wrappers and statics and service locators and and BigLongClassNamesThatIncludeTheirAncestry (I always say, “Do we call it a DogMammalVertebrateAnimal? No, we call it a dog!”) and redundant JavaDoc on every method and…)
I ranted and spoke and even blogged about some of these issues before, but now that I’m a visitor in that world I just feel vaguely amused and sad when I see all the hoops Java programmers still have to jump through. Yeah, control-space completion is nice, but gotapi works pretty well, and at the end of the day, no matter how many curly braces my IDE inserts for me, I’d rather have my code look like this:
parse_args(["--topping", "pepperoni"])
than this:
String[] args = {"--topping", "pepperoni"};
parseArgs(new ArrayList<String>(Arrays.asList(args)))
Wouldn’t you?