Best Practices for Team Android Development

by

I’d like to take a moment to offer a few suggestions that will hopefully help your Android project along. First I’ll go over the Designer-Developer asset communication and then we’ll look at a few Resources management tips.

1. Quick Tips for Designers:

It generally takes more than one iteration (and often MANY) to finally end up with an app that will passably well satisfy the designers ;D. Going back and forth is a necessity as the app just doesn’t look the same on the device as on paper.

Here are a few conventions we decided on prior to even adding assets to an app:

a. Use an online shared drive like Dropbox or Google Drive. If the developer has it set to synchronize to his hard drive, he’ll be able to copy/paste or drag assets like a snapping of the fingers.

b. Distribute the drawables in a flat hierarchy, only separated by density. Naming the folders drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-xhdpi is a +. No deep state hierarchy.

c. Decide on a file naming convention asap. eg. btn_login_pressed.9.png

d. When replacing a graphic; don’t change it’s name. Naming files based on their location/purpose in the app vs. what they represent will be more practical.

For example: btn_general_purpose_pressed.9.png vs. btn_light_blue_pressed.9.png
Changing color of the buttons from light blue to dark blue will now require a lot less work.

2. Split the Strings

Strings in most cases are stored by the developers in the strings.xml file. That can get messy.
Why not have some minimum organization?
There’s a few ways you can proceed, depending on how organized you think it’s worth to be (KISS):

a. One level:

  • strings.xml
  • messages.xml
  • placeholders.xml

That’s the most basic breakdown.
strings.xml will contain the application strings that are seen by the user on the screen, They’ll generally show up in TextViews, Spinners, Action Bars, etc.
messages.xml contains the strings that are shown in Dialogs; it can be message dialogs, toasts or other messaging for the user.
placeholders.xml contains the strings that you, the developer have there pre-populating EditTexts, etc. The number of strings in it is generally low, so it’s not always necessary to have that file, but once you reach a stage closer to production, all you have to do is remove the file, and eclipse will give you all the errors corresponding the missing strings. That way you can easily go through the resources and classes to remove the references to those placeholders.
In short, it’s an easy way to make sure you don’t leave any leftover placeholders in your app.

b. Deep level:

Splitting the strings into more files becomes rapidly counter-productive, but here is an example of a more structured splitting of strings:

  • placeholders.xml
  • globals.strings.xml
  • globals.messages.xml
  • news.strings.xml
  • news.messages.xml

We could go on: news.recent.strings.xml, etc.

2. How to encourage the use of resource strings and discourage string literals:

A bigger problem than keeping the strings organized is leaving string literals in the code. Removing them can be a time consuming issue at the end of a project, when generally, that time becomes as a rarefied resource.
For that:

a. Awareness:

Sometimes it’s worth it to remind to the team that adding an entry to the strings.xml files is worth their/your while (And it’s not THAT time consuming).

b. Deprecation:

Create methods that take in resource id’s rather than strings.
In a recent project, we had to show some messages, so we rapidly added some utility methods to show general purpose messages.
Those were available in our base activity (subclass of SherlockActivity):

[code lang=”java”]
public class MyActivity extends Activity {
protected void showMessageDialog(int titleResId, int bodyResId) {
showMessageDialog(getString(titleResId), getString(bodyResId));
}

@deprecated
protected void showMessageDialog(String title, String messageBody) {
//my code
}
}
[/code]

Note that rather than completely preventing the user from passing String literals in the parameters, we provide a deprecated method that will still allow them to pass in formatted text when necessary (eg. getString(String, …args))
In this case we use the annotation as an indication to the developer that he shouldn’t be using this method except under those precise circumstances.

4. Embedding/including layouts:

It’s quite a simple thing but I see it used only sporadically, so I thought it would be worth mentioning it here: You can include layouts within other layouts.
This means that when you have complicated skeletons, rather than trying to maintain multiple copies of the same layout, and looking for it within all the layouts in your app; you can now just change it in one place and it will be propagated to all your containing layouts.
This also means that you can change the enclosing file across multiple versions or device types, without affecting the included part of the screen.
It’s not for nothing that object oriented programing is so prevalent. Creating sub layouts when appropriate diminishes the complexity, and increases the overall readability of your app.
Example:
screen1:
> header
>> image_with_overlaying_text
> body
> footer

screen2:
> list1
>> row
>>> image_with_overlaying_text

When my designer says: “Hmm…., the text should probably be at the top of the image instead of centered. Think you can do that?”, I don’t have to turn an ashen face on him, wondering how long changing 500 layouts would take. I can smile and say: “Mais bien sûr!”

Note that you can override the properties of the containing ViewGroup of the included layout. Setting a id or background

That’s it for now. I’m missing a lot of things here, but please feel free to provide some useful tips that you think could be mentioned too.

Leave a Reply

Your email address will not be published. Required fields are marked