Android Development Gotchas
This isn’t designed to be a definitive list of unexpected occurrences while developing for Android, but it is a list that I scratched down while I was picking up some skill for myself. It won’t save you from every issue but there may be cases where you can stop and think “Yeah, Dave told me that would happen”.
My development environment included Eclipse 3.5 with the Google ADT plugin and all testing was against a rooted HTC Desire and unroot Samsung Galaxy SII both running Android 2.2, development code targeted Android 2.1. Problems may be an issue with ADT, HTC, Samsung, Android 2.1 or 2.2, rooting or the specific hand sets 🙂
Java 1.6 on a Dell XPS 1530 running Ubuntu 10.10, if that matters.
I found these too slow and unusable.
Early on in development I gave up trying to use the the ADT virtual devices and tested directly against the target hardware devices. Luckily for me the application was for internal use only and would be released to specific clients with specific handsets, but I was disappointed at how slow the VMs were start and how slow they ran. The develop-deploy-test cycle was just too slow using the ADT.
Virtual Devices Cannot Support Bluetooth
ADT Virtual Devices cannot support Bluetooth, and as our application includes Bluetooth communication this was another reason ADT development was excluded.
Inconsistent Bluetooth Support Between Vendors
This was a strange one to us, and not one that we have (to this point) been able to resolve although my guess is that it is a problem with the HTC code.
Our application involved having a file sent to the phone using OBEX over Bluetooth. No problems so far. Pair the devices, enter the code, initiate the file transfer.
The Samsung Galaxy SII displayed the preferred behaviour, where the incoming file prompt the phone user to accept the file, but also provides a checkbox to always accept files from this device. If you don’t select the checkbox then you are prompted each time a file arrives, but you are still able to check the box later on.
When the first file arrives, HTC Desire asks if you want to allow the remote device to synchronize contacts, and whether you always want to allow this. If you don’t allow this, you aren’t able to get to the next step where you accept the file. If you don’t accept contact swap all the time you’ll be prompted each time. Regardless of whether you swap contacts or not, you must accept each file as it comes in. Accepting every file manually is not our preferred behaviour.
Android Apps Run on a Single Thread
Some of this cuts into Android’s Handlers, task scheduling and communication across threads, but it may come as a surprise during development that all standard processing occurs on a single Thread. This is something that you’ll want to play with and become familiar with as it may be surprising that UI performance is impacted by Runnables and Services.
I do recommend you have a play.
Creating new Threads is one option, although Android’s AsyncTask is the preferred mechanism for truly asynchronous processing that doesn’t freeze the GUI.
… and that Thread is a UI Thread
Following on from the previous point, the main thread is a UI thread and that that thread is only active when the UI is active. Sort of. Check the Android fundamentals processes and threads page, but just be aware that if you want something to process while (for example) the screen is locked, you need to be aware of the processing thread.
Beware Empty Elements in XML Layouts
If you’re like me, you like tidy XML and prefer an empty element (where applicable) to an element which is not ’empty’ but has no child elements.
<!-- this element has no children --> <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/list"></ListView> <!-- this is an empty element --> <TextView android:id="@android:id/empty" style="@style/EmptyContent" android:text="@string/emptyResponseEntries" />
In this example, the TextView is empty and causes no problems, but the ListView will. If you make the ListView an empty XML element, you can write items to the List, but they won’t show up on the screen. There won’t be any error reported, it just won’t show up.
Can’t Read Property Defaults
Property defaults were also something I found perplexing. If you specify a properties.xml file, each property is able to define a default value. Likewise when reading properties via the SharedPreferences you can specify a default value if the property doesn’t exist, but the two default values aren’t related. You can’t read the default value as defined in the preferences.xml file for use elsewhere, the API doesn’t provide access.
Note that recommended properties management is via the PreferenceFragment
Notifications Can Be Empty
I found this one amusing. It is possible to create an empty Notification using new Notification(), specify a notification sound, and annoy users without providing any indication of where the annoying sounds are coming from.
I’d add one of my own experiences: if you’ll ever have problems with image displaying (like displaying wrong image or displaying none image at all) – check image size variants in folders /res/drawable-ldpi, /res/drawable-mdpi … It got me stuck in one place for a long time 🙂
I have another regarding preferences with a defined type (moral: treat all properties as strings, don’t use numeric properties unless absolutely necessary) but I ran out of time to try to create an example on how to create the problem and how to recover (the only solution I found was to clear all data for the application)