Monday, November 7, 2011

Startup Weekend Google Tech Bootcamp

I'm excited to annouce the upcoming SW / GTUG Bootcamp. There will be lots of good Android information and a code jam to get you ready for Startup Weekend. Here are the details:
Startup Weekend - Google Tech Bootcamp
Admission $5
Saturday November 12, 1:00pm - 5:00pm
ng Connect Gravity Centre
2900 West Plano Pkwy Plano, TX 75075
The following topics are on the agenda with more to come soon:
  • Android Cookbook - Scraps and Ideas for Startup Weekend 
  • Getting Started with App Engine
Keep an eye on this page for updates!

Monday, September 26, 2011

Software Versioning

This post describes a strategy for version numbering software builds. We’ll assume that we have 4 digit places to work with. Before we look at how to version a build, let’s look at the audience for each section of the version number. In this example, we’ll use version v1.2.35.76.


Each section of the version has a different “owner”. By investigating what each part of the organization requires from a version number, we can plan a numbering system effectively.

Numbering Versions: 

The first two sections of a version number are owned by marketing. I mean "owned" in that the marketing organization should control what appears here. Imagine that this is the customer-facing section of your version number. From a marketing perspective, code changes may result in an increment from v1.2 to v.1.3 or we may decide to jump to v2.0. If we imagine that marketing owns the first two digits, none of the rest of the business is impacted by these decisions. We can do what's best and most meaningful for the customer.

 The third section (35 in our example) is owned by the Quality Assurance and Testing organization. In most cases, QA will want this number to perpetually increment with each build they receive. So, if they’ve just received version X.X.34.X, they will expect the next version to be X.X.35.X. This number should never reset to 0! Having assigned the 3rd section completely to QA, we can assume they will ignore every other section. Marketing will be free to increment (or decrement) the first two sections and dev can have their way with the fourth.

The fourth section (76 in the example) is owned by the development organization. Each time a build is produced to be shared outside of the developers desk, this number should be incremented. This way if a manager reports an issue, the question “What build do you have?” will always yield a useful answer. This number should also never reset to 0! By constantly incremental this number, dev will always know where a bug occurs when it is reported.

When to Version: 

As we’ve said, the final “build number” section of the version should be incremented each time a build leaves the developers desk. But when do we change the other numbers? The answer is as soon as possible.

For example, let’s say you’ve just delivered v1.2.35.76 to QA. Your very next code change should be to increment the QA section from 35 to 36 because you know that all further changes will be targeting the 36 QA release.

Similarly, as soon as marketing decides that there is funding to deliver a v1.5 of the product, we should increment our first two digits. Anyone can look in our source code system at any time and know that we're contributing code to what will become the revision 1.5.

By incrementing immediately after you generate a release, you’re ensuring that if someone pulls a build at any time, they will have the correct version number.

Thursday, May 5, 2011

Landing Activity Icons The Easy Way

Many Android applications include a landing activity or a "main page" full of icon options. Typically this activity does little more than throw intents to launch other Activities when a user clicks one of the icons. In this post, I'm going to take advantage of the onClick, tag, and drawableTop attributes of TextView to make this work with very little code.

 Let's imagine that I'd like to write a media playing application that includes main activity icons for Music, Photos, and Video. For each icon on the landing activity, I'm going to use just a tiny bit of xml in my layout:

<TextView
android:text="Music"
android:drawableTop="@drawable/icon_music"
style="@style/mainicon"
android:tag="com.example.action.MUSIC"/>


First, you'll notice that the text and drawableTop attributes specify the drawable and the text for the icon. Using drawableTop keeps you from having to define a linear layout for each icon to stack the icon on the text. Here you can do it with just the TextView element and that's all.

Second, notice the style attribute. Here's the style I've defined for a main icon:

<resources>
<style name="mainicon">
<item name="android:layout_width">100dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:clickable">true</item>
<item name="android:onClick">click</item>
</style>
</resources>


The obvious bits of style specify the height, width, and gravity. What isn't so obvious is the definition of clickable and onClick. Basically, the onClick attribute is telling every View that has this style to execute the method called "click" in the parent Activity. But wait, hows that going to work? We're telling every icon to run exactly the same code. Here's the code for the click event method:

public void click(View view) {
   String action = (String) view.getTag();
   Intent intent = new Intent(action);
   startActivity(intent);
}


The click method pulls the tag from the view that was clicked and fires an Intent using that string as the action. Take a look again at the XML that defines our music icon. See the tag attribute?

Now, there's one final step to make this work. The AndroidMainifest.xml must be modified so that the music Activity knows how to receive the intent we're throwing. Easy:

<activity android:name=".Music">
<intent-filter>
<action android:name="com.example.action.MUSIC"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>


The intent filter will route all of the action.MUSIC intents to the Music activity. Hopefully this will simplify your code and clean things up a bit Have fun.

Sunday, May 1, 2011

Deep Linking in Android Applications

I'd like to write a little bit about best practice ideas for loading data in Android applications. I'm hoping to encourage you to rethink how you visualize an Android application. In general I'm going to advocate the use of implicit intents and loaders. Here's my main point of the post:

Good Android applications can be started from any Activity.

Here's the issue. A lot of mobile programmers come from a history of designing applications that load view controllers in a sequence. iOS and WinMo applications typically launch by firing up a specific controller. Many developers will make this a splash page or a welcome screen of some sort. From there, users navigate through the app, but the developer is always sure that the code in the starting controller has executed. It often becomes a sort of dumping ground for "init" code.

 Android isn't designed this way. You should think of your Android application as a mesh of Activities like a web site is a mesh of pages. You can't (and shouldn't) control how your user enters your application. Consider Amazon.com for example. A sizable amount of traffic to the site does not come in through the home page. Many people post links to specific product pages and the design encourages traffic to enter any place in the site. Effectively there is no front door.

 Good applications on Android are the same. They all offer deep-linking through the Intent mechanism. In this post, I'm not going to describe how intents work. I'll assume you know the basics. Most app developers know how to start an activity using an explicit intent:

startActivity(new Intent(context, MovieActivity.class));

Note that the explicit intent includes a class reference to the Activity you're launching. While this gets the job done, it doesn't open any doors for other apps to deep link into yours. Instead you should use an implicit intent such as the following:

startActivity(new Intent("app://com.example.movies/viewmovie/5"));

 Using an implicit intent enables other applications to launch this activity directly. However, if your application isn't designed correctly this may cause problems. What if you haven't loaded the data you need for the activity? Let's imagine that you have a master-detail arrangement where activity A shows a list and activity B shows the detail for a list item. In a poor application design, activity A loads the data for all items and passes the information to activity B.

FAIL! 

In a better design, activity A loads only the data required to display the list. It should pass only an id to activity B which will load the detail page on it's own.

WINNING! 

Each activity should have it's own Loader. The Android 3.0 SDK made the idea of loaders official, but the principle of each activity loading it's own data is solid even in older versions of the SDK.