I got introduced to an Android application development during Philly ETE conference by listening to “A guided tour of the Android ETE mobile application” talk, where Andrew Oswald ( a Java Architect from Chariot Solutions ) talked about creating an Android app for the conference, which was a cool introduction to “what it takes” to write one of those apps from scratch. I am looking forward to more talks around mobile development this year at Philly ETE conference as well.
Meanwhile I rely mostly on Android’s Developer Guide whenever I seek answers to my questions or/and best practices. Here are my notes on such practices I picked up listening to “A Beginner’s Guide to Android” Google I/O 2010 talk:
1. Avoid creating objects unless you really need to, try reusing Android’s API instead. Creating an object in a “desktop” world is relatively cheap, however in such a resource constraint environment as a mobile phone, it will drastically impact the performance.. not in a good way.
2. In order to avoid friendly “Force Close” popups from your applications, use Android’s “AsyncTask” which will allow to execute a certain activity in background:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
} |
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
read more about AsyncTask in Android Developer Guide
3. Think about what an absolute minimum amount of updates / syncs you can do, and stick to this minimum. This will greatly improve battery life as well resource usage by the application.
4. Only use a WakeLock when you need one with as minimum level as possible: PARTIAL_WAKE_LOCK, SCREEN_DIM_WAKE_LOCK, FULL_WAKE_LOCK. Here is more about PowerManager
5. Respect a “Back” button: make sure it actually brings user back to a previous state rather than to another state of the application’s flow.
6. Always check whether “data transfer” is enabled on a device, before attempting to transfer data:
ConnectivityManager cm= ( ConnectivityManager ) getSystemService( Context.CONNECTIVITY_SERVICE );
boolean backgroundEnabled = cm.getBackgroundDataSetings(); |
ConnectivityManager cm= ( ConnectivityManager ) getSystemService( Context.CONNECTIVITY_SERVICE );
boolean backgroundEnabled = cm.getBackgroundDataSetings();
this is especially important while roaming, when that “twitter update” can cost user a lot. So do respect user settings.
7. Don’t use undocumented ( not officially supported ) APIs => Next Android release your app is going to break.
8. Respect and use an application lifecycle:
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy() |
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
read more about Android Application Lifecycle
9. Externalize resources: localization / optimized layouts / strings / array of strings / etc.. Android compiles them into a list of internal resources by assigning an integer ID to each of them, hence making it “cheaper” at runtime, and easier to change => since they are defined in a single location. Here is an example of auto generated ( random layout ) resources:
public static final class layout {
public static final int about_details=0x7f030000;
public static final int all_upcoming_filtered_buttons=0x7f030001;
public static final int details_text=0x7f030002;
public static final int details_webview=0x7f030003;
public static final int faq_details=0x7f030004;
public static final int faq_details_row=0x7f030005;
public static final int main_tabs=0x7f030006;
public static final int map_details=0x7f030007;
//.... the above is auto generated |
public static final class layout {
public static final int about_details=0x7f030000;
public static final int all_upcoming_filtered_buttons=0x7f030001;
public static final int details_text=0x7f030002;
public static final int details_webview=0x7f030003;
public static final int faq_details=0x7f030004;
public static final int faq_details_row=0x7f030005;
public static final int main_tabs=0x7f030006;
public static final int map_details=0x7f030007;
//.... the above is auto generated
10. Think of hiring or delegating UI to people who are designers. Beauty is important
11. Be resolution independent. Check out “layoutopt” and “hierarchyviewer” that come with Android SDK under “tools”. They help analyzing and optimizing layouts.
12. Consider using a “non sticky” services when appropriate:
@Override
public int onStartCommand( Intent intent, int flags, int startId ) {
handleCommand( intent );
// If this Service gets killed, don't restart it
return START_NOT_STICKY;
} |
@Override
public int onStartCommand( Intent intent, int flags, int startId ) {
handleCommand( intent );
// If this Service gets killed, don't restart it
return START_NOT_STICKY;
}
this is useful for services that are going to be executed on a regular basis. So when you are pulling for updates every 10, 15 minutes, it is ok if one of such updates is missed in favor to a healthy resource management
13. Do not use foreground services unless you absolutely need to.
And if you do use foreground services, use an ongoing notification ( which, starting from Android 2.0, used automatically, if a service is started as a foreground one, but just to keep something in mind to be used for older OS versions )
14. Kill your own services via stopSelf():
@Override
prtoceted void onPostExecute( Void result ) {
stopSelf();
} |
@Override
prtoceted void onPostExecute( Void result ) {
stopSelf();
}
15. Use Intents and Intent Filters to Leverage Other Apps
16. Prefer Alarms and Intent Receivers to Services
Now, with this in mind, go and Rock That Android Space!