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

Erik HansonErik Hanson
Pattern for Functional Testing
edit Posted by Erik Hanson on Friday November 14, 2008 at 05:40PM

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

Alex ChaffeeAlex Chaffee
XPath CSS Class Matching
edit Posted by Alex Chaffee on Tuesday March 25, 2008 at 06:01PM

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 &lt;div class='foo bar'&gt; 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 + " ')";
}

Alex ChaffeeAlex Chaffee
Java Stink
edit Posted by Alex Chaffee on Monday February 11, 2008 at 05:07PM

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:

  1. 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.
  2. 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.
  3. Java has no metaprogramming features to automate common tasks such as field accessors, standard constructors, and simple delegation.
  4. Primitives, functions, and classes are not first-class objects, leading to huge code bloat to deal with these types specially.
  5. 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?