Friday, June 17, 2011

What new Android developers need to know

Android is a new operating system. Apps are written in Java, which is a familiar language to many.  On the other hand, developing for mobile apps is a different beast than with other platforms.  Here are some things I've learned in my years of programming for Android, and I suggest if you are learning Android that you learn about these topics.  I think these make for great interview questions, so it would help to know about these topics if you are going for an Android related interview.


Android Topics

1.       Know what a task is in Android.
a.       How does the task and the navigation stack relate.
b.      What is the difference between default, singleTask, singleTop, etc.?
c.       What happens when you press BACK? 
d.      What happens when you press HOME?

2.       Know what activity lifecycles are. 
a.       When do you use onPause() vs. onDestroy()? 
b.      What are onConfigurationChange() and retainInstanceState() useful for? 
c.       What happens to static variables when you switch activities?

3.       Know what API levels are. 
a.       Unfortunately, the Android builder does not distinguish API levels.  You can build an application with minSdkVersion=3, targetSdkVersion=4 with code which uses methods only available on level 4.  This will build fine, but throw an exception when the class loader attempts to load your class files on an API level 3 phone.
b.      In Eclipse, change the API level to 3 briefly, just to see if the code can compile.
c.       We have to develop with API level 8 in order to use certain features in the manifest, so we have to be very careful about using API methods that are only API levels 1-3. 
d.      You can still use reflection and wrapper classes to prevent class loader from breaking, etc. to use newer classes; examples are available on the Android dev site.
e.      Be wary of the element in the Android manifest.
                                                               i.      An app may be filtered from the Marketplace based on these elements.
                                                             ii.      Bluetooth feature has special rules.

4.       Test your app in all sorts of UI configurations:
a.      Low density, extra large screens, landscape, etc.
b.      A layout may look good on a 320x480 screenshot in a mockup, but did the mockup address how it would look in landscape?
c.       Horizontally laid-out information isn’t good for mobile devices in general.  Keep the layouts flowing vertically.
d.      You get to create all sorts of UI configurations with emulators.

5.       Compress your graphics.  I use an open source program Paint.NET to adjust .PNG images. 
a.       PNG graphics can have unnecessary meta data from graphics programs which take up extra space.
b.      Sometimes encoding in 8-bit vs. 32-bit can save space, but careful that transparency is retained.
c.       If your business customer wants to give you graphics for every type of UI configuration, see if they can accept using a standard image size, and let Android scale the images.  It greatly increases the size of the app.  Android scales the images. 
d.      Use drawables defined in Android XML files when possible instead of bitmaps; they scale well in different sizes and take up less disk space.

6.       Don’t schedule services too often. 
a.       Do you really need to download data from the network every 15 minutes?  This is awful on battery life!
b.      You change the frequency of the service by rescheduling every time the service finishes instead of scheduling a periodic service.

Java in Android

1.       Learn what a strong reference, a weak reference, and a soft reference are.  Weak references are especially useful in Android.
a.       Use weak references when dealing with separate threads and timed operations: WeakReference. 
b.      Both WeakReference and SoftReferences can be useful for some types of caches.

2.       Always use separate threads when doing network operations, disk operations, and other long-running operations.
a.       It turns out that the same code which takes 5 ms can take 5000 ms when Android is out of memory or waiting for other processes to finish file I/O, killing and starting processes, and doing a GC on your app.
                                                               i.      Get used to doing lazy initialization.  It seems unnecessary until you get 500 ANRs on the Marketplace reports.
                                                             ii.      In startup methods, don’t initialize variables.  Wait until an accessor method such as getVariable().
b.      IntentServices, Handlers, Threads.  They are useful in different situations.
c.       IntentServices guarantee a separate thread and that multiple intents handled by the service are synchronized to be processed one after another.
d.      Handlers are useful for transferring messages from the network/etc. threads to the UI thread in an activity.
e.      Threads may be useful in some situations, but remember that a running thread is not a guarantee to keep your process alive; if all activities/services/etc. are closed, then a running thread can (and will) legally be destroyed by the OS.

3.       Be wary of static variables: you don’t have knowledge of their lifecycle, unlike instanced variables accessible through activities and services with onCreate() and onDestroy().
a.       Their value can be reset but
b.      Static variables are notorious for causing memory leaks.
c.      They are useful in some situations still.  For example, preventing code from executing more than once when your process has already started.

4.       Do you know what a memory leak in Java is?  It’s not the same as it is in C.  It refers to keeping strong references to objects which shouldn’t be used anymore (should be GC-able), but programming error has kept them strongly reachable.
a.       In Android especially, you never want to keep references to Activities and Services in variables, especially static variables. 
b.      Sometimes you do need contexts; you can either use Application as a context, or if you have to have the Activity context then 1. Use a weak reference, or 2. Don’t let the object which has a reference to the Activity be referenced by anything else: make sure the Activity completely “owns” the object.

5.       Don’t ever keep static references to Activities, Services, Views, or BroadcastReceivers.
a.       This causes memory leaks!
b.      You can use a global (static) context from the Application. 
c.       This is useful for getting resources, files, etc. Be careful; you can’t create dialogs from this context, and any activities started with the application context will always create a new task.
d.      If you have to use a static reference, use a WeakReference.


Standards

1.       Build machine is good.
a.       You can create custom Ant scripts.
b.      I use them to copy files based on build properties, and to change variables in the Config.java class.
c.       I also change AndroidManifest.xml using a script based on QA or release builds.
                                                               i.      No worry about developer forgetting to change items.
                                                             ii.      Add/remove debuggable attribute, permissions for logging to SD card, etc.

2.       Always use ProGuard in any app released to the Android Marketplace.
a.       Reduces app size by removing unused variables and methods.
b.      Obfuscates code, which theoretically cannot prevent hackers from snooping but does slow them down.
c.       Allows you to have code  like:
if (Config.LOGGING) print(“The data is: “ + data);
The above statement is completely removed when Config.LOGGING is false.

3.       Code formatters are useful
a.       Standardization is nice.
b.      Simple whitespace differences can cause merges to break.
c.       If you are using Eclipse, you can check in the project settings into the source repository.
d.      Deciding some standards can be akin to a religious war; after 50 years, lots and lots of smart people have debated this and they haven’t come to the same conclusion on what’s best.  Just go with something.

4.       Hungarian notation is used in Android OS and in some of our apps.
a.       It can be useful, but a developer can easily mess up.  In a strongly-typed symbolic language such as Java, source code formatters do a better job of telling you the data type of a variable.
b.      You don’t have to use the Android OS coding style, but it is an example of a coding style:
                                                               i.      mVariable means instanced field (member variable)
                                                             ii.      sVariable means non-final static field.
                                                            iii.      ALL_CAPS means a constant (final static)
c.       Hungarian Notation was originally meant to describe the type of data as in network response or pixel measurements.  It has been incorrectly used as data type as in “final static” or “DWORD LONG *”.

5.       Use themes and styles in your layouts. 
a.       It makes it easier to make changes.
b.      You’ll probably not use styles the first time you make your layouts.  Then when you have to go back and change 25 layout files just to move some pixels to the right, you’ll start using styles.

6.       Put logs everywhere. 
a.       Make a standard for how it’s done. 
b.      No need to remove them or comment them out when using ProGuard if wrapped in a constant boolean; this is a good thing.
c.       I have many ways of dealing with logs:
                                                               i.      Log items to logcat, filterable by one single tag. 
                                                             ii.      Log items to the SD card.  Great because this persists after device resets and lets you observe behavior overnight or over a long time.
                                                            iii.      Added menu item in debug area of app which will automatically e-mail logs to an e-mail address.

Useful reading: