Android Color Banding

Many Android programmers encounter severe color banding on devices like the Nexus One. For example, here is a radial gradient in an app I wrote this morning.

Banding on a Nexus One

There is an awful lot of misinformation out there, for example I see many people advocating dithering as a solution. Here is my app with dithering enabled:

Nexus One with Dithering

This is better, but won’t look so hot with many bitmaps. The correct solution is to take note of the format. As shown in the above images, Android’s default format is PixelFormat.OPAQUE. You can change this in a few ways. One way is to create a custom theme and set android:windowBackground to a color.

Another solution is to programmatically call Window.setFormat(PixelFormat.RGBA_8888).

The end result:

Eliminating Color Banding on the Nexus One

Sample code:

 public class MyActivity extends Activity {   @Override   public void onAttachedToWindow() {     super.onAttachedToWindow();     Window window = getWindow();     // Eliminates color banding     window.setFormat(PixelFormat.RGBA_8888);   } } 

HTC EVO Review

The EVO is a great phone with poor software choices.

Like

  • The kickstand on the back
  • HDMI port
  • Front facing secondary camera
  • The huge display
  • Fast processor

Do Not Like

  • Pre-loaded apps on the system partition cannot be removed
    • Footprints, Friend Stream, HTC Mobile Guide, NASCAR Sprint Cup, Peep, Qik, Quickoffice, Sprint Football, Sprint Zone, Sprint Navigation, Sprint TV, and many others
    • Many of these apps are configured to automatically start, so less savvy users will experience reduced battery life and slower performance.
    • Even disabling and removing apps from the home screen leaves the “all applications” list cluttered.
  • The hardware buttons (home,menu,back,search) are easy to mistakenly hit. If you get a chance to try this phone, try tapping the bottom edge of the phone completely outside of the home button’s bounds. Your tap will still register!
  • The dialer is not Android standard. The HTC replacement is cluttered and harder to navigate.
  • The large size is nice, but the corners should be more rounded, like the Nexus One. The boxy shape of the EVO makes it feel even larger than it is.
  • The soft keyboard is not Android standard, and it is cluttered.
  • *** UPDATE: InputMethod full screen mode fails to show a “Next” button, even when android:imeOptions="actionNext" is specified as an EditText attribute. This means when users are entering text in landscape mode, they don’t see the Next button, resulting in a very confusing UI.
  • This phone has no trackball. When editing, you see a bunch of extra soft key arrows on the keyboard for navigation. These arrows add complexity:

HTC EVO Keyboard

Android makes vendor customizations possible and this phone demonstrates just how poorly that can be done.

Interfaces and Implementations

Consider a Java interface and class: Dog and DefaultDog. Which of these two conventions is best?

Option 1 : Dog

Name the interface Dog and call the implementation something like DefaultDog or DogImpl.

Option 2 : IDog

Name the interface IDog and call the implementation Dog, DefaultDog, or whatever else you can come up with.

The Answer

I prefer option 1 for these reasons:

  • A vast majority of your code will utilize the interface, rather than the implementation. Thus, it’s best to keep the interface name clean, and reserve the weird names for the implementation classes, which you hardly ever see.
  • Prefixing names with “I” feels like Hungarian notation. The name redundantly specifies what the interface keyword already specifies. Should we also adopt notations for things that are static, final, abstract, etc? I think not.
  • Many interfaces will have multiple implementations. Thus, each implementation will need a different name. I see no need to also put some name discriminator on the interface.

Regarding names like “Impl” and “Default”, I prefer to avoid those when possible. For example, ArrayList and LinkedList are far better names than DefaultList or ListImpl.

Win 7 Printing to Airport Printer

We have a combination of Mac and Windows machines in our house, and I was unable to get a new Windows 7 64-bit machine to print. The printer is shared using an Airport Extreme Base Station.

I downloaded Bonjour for Windows and it immediately detected the printer. Everything seemed OK, but printing always failed.

This led to many hours of failed searching and troubleshooting. I found many people have the same problem, and many solutions being offered. Nothing worked, until I noticed the “here” link:

64-bit Bonjour

With those highlighted circles, it seems painfully obvious. But the “download” button is more prominent, so I didn’t read the text. Based on the number of people I encountered having the exact same problem, I must not be the only one to miss this.

The real kicker is the fact that 32-bit Bonjour fails to warn you if you install it on a 64-bit PC. It happily finds the printer, leading to a false sense of success.

One last tip — if Bonjour can’t find the driver, first plug the printer directly into your PC. Windows should be able to download the right driver.

T-Mobile Support Session

I just chatted with T-Mobile about the Nexus One phone. Here’s the conversation…

You have been connected to _Kristi J.

_Kristi J: Hi Eric, welcome to T-Mobile live Chat. I’m _Kristi and I will be happy to assist you. Please give me a moment to review your question.

_Kristi J: I can definitely understand your interest in this new device. I’d be more than happy to get further information about that for you today.

Eric Burke: ok

_Kristi J: You can only order the phone through the www.Google.com/phone website.

_Kristi J: The phone is being sold exclusively by Google, and cannot be ordered through T-Mobile.

Eric Burke: but it says I’m not eligible for the $179 price. why is that?

_Kristi J: The requirements of getting a discount on the phone are set by Google alone, not T-Mobile.

Eric Burke: do you know the date when my two year contract expires?

_Kristi J: One of the requirements to get the discounted price is that you are on a single line Even More plan for $79.99/ month.

_Kristi J: While I am looking into this information, may I ask why you are inquiring about your contract end date?

Eric Burke: so I can get a better phone. I’d be happy to stay with T-mobile if I could upgrade, but it sounds like I’m trapped with my now obsolete G1 phone.

_Kristi J: The G1 is not an obsolete phone, and is still being sold by T-Mobile.

Eric Burke: but it’s running Android 1.6, and as far as I know, won’t receive future updates to Android 2.1

_Kristi J: I regret that your account does not seem to meet the requirements set by Google to get the discounted pricing on the phone at this time, Eric.

Eric Burke: what’s my end date, and what is the penalty if I break the 2yr contract?

_Kristi J: Your contract on the line ending in **** ends on 11/14/2010, and you would have a Termination Fee of $200.00 if the line is cancelled at this time.

Eric Burke: $200 total, or per phone?

_Kristi J: That would be $200.00 per line.

Eric Burke: ok, thanks for the info. that’s all I need to know

_Kristi J: I’m glad I was able to answer those questions for you today. Thank you for contacting T-Mobile Chat, Eric. Have a great day!

Custom HTTP Headers with GWT RPC

Prior to GWT 2.0, there was no easy way to add custom HTTP headers when making remote procedure calls. The new RpcRequestBuilder in GWT 2.0 makes it easy to add custom headers.

// start with a custom RpcRequestBuilder RpcRequestBuilder reqBuilder = new RpcRequestBuilder() {   @Override   protected RequestBuilder doCreate(String serviceEntryPoint) {     RequestBuilder rb = super.doCreate(serviceEntryPoint);     rb.setHeader("username", "sookie_stackhouse");     return rb;   } };  // as with any other RPC, use GWT.create(...) to generate the client proxy MyServiceAsync service = (MyServiceAsync) GWT.create(MyService.class);  // all client proxies also implement ServiceDefTarget ((ServiceDefTarget) service).setRpcRequestBuilder(reqBuilder);  // make calls as normal service.doFunAndInterestingThings();

State Capitals 1.1.2

I just fixed a few bugs in State Capitals:

  • I drew the Hawaii state capital star on the wrong island (epic oops)
  • The “Move Known States to Last” preference was ignored, so you could not disable that behavior

I also reworked the graphics for Alaska and Hawaii. These two cards now show the state positions relative to the lower-48 states.

Publishing to the Market

Once I built the StateCapitals.apk file, I decided to announce my progress on Twitter in real time. Here are my updates:

  • Update 1: OK, I just compiled a new build of State Capitals for #android. It is 12:45 PM and I am preparing to upload to the Market.
  • Update 2: It is 12:46PM and the upgrade is published. Now I’ll check my phone. #android
  • Update 3: Yep, 12:47 PM and I’m downloading the update to my phone. #android
  • Update 4: And by 12:48 PM I’ve tested my changes on my phone, all is well. #android

Three minutes was excessive. I had to pause between steps to post those messages to Twitter.

Contrast this experience with other app stores.

As always, State Capitals is free, has no advertisements, and requires zero permissions to run.

Android Storage

The new DROID phone only offers 256 MB for app storage, as Taylor Wimberly points out:

The Motorola Droid will be the most powerful Android phone to date when it launches on November 6, 2009. However, the device still features the same shortcomings of all other Android phones. The Droid ships with a 512 MB ROM which contains only 256 MB available for app storage.

Fair enough. From this starting point, the article quickly devolves into speculation and FUD:

Google does not support installing apps to the SD card (and likely never will), so developers are limited in what they can create.

I question the “and likely never will” claim. Google knows about the issue and I believe they will eventually resolve it. It’s been discussed in public Google forums, and I think people on the outside are assuming the worst. I think it is far more plausible that the Android team has limited resources and this is a very hard problem to solve correctly.

Limited In What We Can Create?

I also question the “…so developers are limited in what they can create.” portion of the above claim. He goes on:

Have you seen all the awesome iPhone and iPod Touch games? Hardly any of them would fit on an Android phone. It is not uncommon for popular titles to easily exceed 100 MB. For example, the game Myst takes up a whopping 727MB.

The solution is easy. Make your app small and download textures and graphics separately to the SD card.

In Summary…

  1. We all want the ability to download apps to the SD card
  2. Google knows about the issue and understands its importance
  3. Google has not officially committed to fixing the issue, or declared a timeline
  4. Without an official Google statement, many members of the Android community assume the worst