Android at Mobile World Congress

I'm happy to announce that we'll be hosting a very special Android Developer Lab at Mobile World Congress (MWC) in Barcelona on Wednesday, February 17th as part of the inaugural App Planet event.

There will be technical presentations throughout the day and a developer lounge where you can talk to Android team members and meet others in the growing Android developer community.

Whether you’re already developing Android apps, you're an experienced mobile developer, or you’re considering making your first foray into writing mobile applications, the Android Developer Lab will provide access to the resources you need to create innovative and compelling apps for the Android platform.

Space is limited in the technical sessions, so if you're attending MWC and want to come by the Android Developer Lab, make sure to sign up now.

Also, we're offering a limited number of complimentary passes that provide access to the Android Developer Lab, the rest of App Planet, and the general exhibition areas for MWC. Sign up to be considered to receive a pass.

Hope to see you in Barcelona!

Android Developer Labs World Tour

Late last year, we held a series of developer labs to give you a chance to ask questions and play with some new hardware. One of the most common questions we received was, "When are you going to visit my city?" It's a good question, and we're pleased to answer it today.

The Android team is embarking on a world tour, which will include cities in Europe, North America, and Asia.

At each stop, we'll be delivering an update on the state of the Android platform—including a look at the latest Android hardware. It's a great opportunity to meet like-minded Android app developers, play with the latest Android devices, test your apps, and ask Android team members any questions you might have. You can find out more on the Android Developer Lab site.

Here's the line-up of Android Developer Lab locations for February and March 2010:

North America

  • Austin, Texas – Feb 4
  • Seattle, Washington – Feb 8
  • Waterloo, Ontario, Canada – Feb 8
  • Washington, D.C. – Feb 9
  • Mountain View, California – Feb 10
  • Cambridge, Massachusetts – Feb 11
  • New York, New York – Feb 12

Europe

  • London, UK – Feb 2
  • Paris, France – Feb 8
  • Berlin, Germany – Feb 10
  • Zurich, Switzerland – Feb 12
  • Madrid, Spain – Feb 13

Asia

  • Singapore – Feb 28
  • Taipei, Taiwan – March 3
  • Hong Kong – March 5

If you'd like to attend, you'll need to request a spot by February 1st. Space is limited, so please wait for an email to confirm that you have a spot in the lab.

While we're on the road, we're also going to stop by and speak at the following local Android user groups:

  • Stockholm, Sweden – Feb 4
  • London, UK – Feb 5
  • Chicago, Illinois, USA – Feb 6

We're looking forward to meeting you in person!

Android at the 2010 Game Developers Conference

2009 has been a great year for Android Market. With the support of developers like you, Android Market now has more than 20,000 applications. Of these applications, games have proven to be particularly popular with Android users. Seven of the ten most popular paid applications on Android Market are games, so there's a significant opportunity for game developers as the number of Android devices continues to grow at a rapid pace.

To better support this trend, we are increasing our support of Android game development. As a first step, we will be presenting a number of Android sessions at the Game Developers Conference on March 9th and 10th in San Francisco. The sessions will be technical and will include everything you need to know about Android game development in Java or C++. Engineers from the Android team will also be available to answer your questions. Whether you are new to the platform or already have games in development, we would love to meet you face-to-face, answer your questions, and see what you're working on. Be sure to keep checking the GDC site because we'll be adding more sessions.

But that's not all. Google and GDC will also be providing complimentary Android phones to attendees who register for All Access or Tutorials and Summits passes by the Early Bird deadline of February 4, 2010. Qualified attendees will receive either a Nexus One or a Verizon Droid by Motorola, so they can quickly apply what they learn from the various Android sessions. You can find more details about the Android phone offer on the GDC site.

Our goal is to make it as easy as possible to develop awesome games for Android, and this is a first step. Hope to see you at GDC!

IRC office hours update


You may recall that we announced IRC Office Hours for Android app developers back in December. We just want to provide a quick update that upcoming office hours will be held on Thursdays from 5 p.m. to 6 p.m. PST, instead of twice weekly. These will be held in the #android-dev channel on irc.freenode.net as before.

Please post your questions on Stack Overflow with "from-irc" tag in addition to "android" tag one day before office hours. We will follow up on those specific questions during office hours, and will also post answers after.

We hope to see you there!

Android 2.1 SDK

Today, we are releasing the SDK component for Android 2.1, so that developers can take advantage of the new features introduced in Android 2.1. Please read the Android 2.1 release notes for more details. You can download the Android 2.1 component through the SDK Manager.

In addition to the new SDK, a new USB driver that supports Nexus One is also available today through the SDK Manager. The USB driver page contains more information.

Hello, Stack Overflow!

Over the past year, an Android presence has been growing on a relatively new technical Q&A web site called Stack Overflow. The site was designed specifically for programmers, with features like syntax highlighting, tagging, user reputation, and community editing. It's attracted a loyal software developer community, and developers continue to express great praise for this new tool. Well, the Android team has been listening...and we agree.

Today, I'm happy to announce that we're working with Stack Overflow to improve developer support, especially for developers new to Android. In essence, the Android tag on Stack Overflow will become an official Android app development Q&A medium. We encourage you to post your beginner-level technical questions there. It's also important to point out that we don't plan to change the android-developers group, so intermediate and expert users should still feel free to post there.

I think that this will be a great new resource for novice Android developers, and our team is really excited to participate in the growth of the Android developer community on Stack Overflow. I hope to see you all there!

Back and other hard keys: three stories

Android 2.0 introduces new behavior and support for handling hard keys such as BACK and MENU, including some special features to support the virtual hard keys that are appearing on recent devices such as Droid.

This article will give you three stories on these changes: from the most simple to the gory details. Pick the one you prefer.

Story 1: Making things easier for developers

If you were to survey the base applications in the Android platform, you would notice a fairly common pattern: add a little bit of magic to intercept the BACK key and do something different. To do this right, the magic needs to look something like this:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
        // do something on back.
        return true;
    }

    return super.onKeyDown(keyCode, event);
}

How to intercept the BACK key in an Activity is also one of the common questions we see developers ask, so as of 2.0 we have a new little API to make this more simple and easier to discover and get right:

@Override
public void onBackPressed() {
// do something on back.
return;
}

If this is all you care about doing, and you're not worried about supporting versions of the platform before 2.0, then you can stop here. Otherwise, read on.

Story 2: Embracing long press

One of the fairly late addition to the Android platform was the use of long press on hard keys to perform alternative actions. In 1.0 this was long press on HOME for the recent apps switcher and long press on CALL for the voice dialer. In 1.1 we introduced long press on SEARCH for voice search, and 1.5 introduced long press on MENU to force the soft keyboard to be displayed as a backwards compatibility feature for applications that were not yet IME-aware.

(As an aside: long press on MENU was only intended for backwards compatibility, and thus has some perhaps surprising behavior in how strongly the soft keyboard stays up when it is used. This is not intended to be a standard way to access the soft keyboards, and all apps written today should have a more standard and visible way to bring up the IME if they need it.)

Unfortunately the evolution of this feature resulted in a less than optimal implementation: all of the long press detection was implemented in the client-side framework's default key handling code, using timed messages. This resulted in a lot of duplication of code and some behavior problems; since the actual event dispatching code had no concept of long presses and all timing for them was done on the main thread of the application, the application could be slow enough to not update within the long press timeout.

In Android 2.0 this all changes, with a real KeyEvent API and callback functions for long presses. These greatly simplify long press handling for applications, and allow them to interact correctly with the framework. For example: you can override Activity.onKeyLongPress() to supply your own action for a long press on one of the hard keys, overriding the default action provided by the framework.

Perhaps most significant for developers is a corresponding change in the semantics of the BACK key. Previously the default key handling executed the action for this key when it was pressed, unlike the other hard keys. In 2.0 the BACK key is now execute on key up. However, for existing apps, the framework will continue to execute the action on key down for compatibility reasons. To enable the new behavior in your app you must set android:targetSdkVersion in your manifest to 5 or greater.

Here is an example of code an Activity subclass can use to implement special actions for a long press and short press of the CALL key:

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_CALL) {
        // a long press of the call key.
        // do our work, returning true to consume it.  by
        // returning true, the framework knows an action has
        // been performed on the long press, so will set the
        // canceled flag for the following up event.
        return true;
    }
    return super.onKeyLongPress(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_CALL && event.isTracking()
            && !event.isCanceled()) {
        // if the call key is being released, AND we are tracking
        // it from an initial key down, AND it is not canceled,
        // then handle it.
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

Note that the above code assumes we are implementing different behavior for a key that is normally processed by the framework. If you want to implement long presses for another key, you will also need to override onKeyDown to have the framework track it:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (keyCode == KeyEvent.KEYCODE_0) {
        // this tells the framework to start tracking for
        // a long press and eventual key up.  it will only
        // do so if this is the first down (not a repeat).
        event.startTracking();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

Story 3: Making a mess with virtual keys

Now we come to the story of our original motivation for all of these changes: support for virtual hard keys, as seen on the Droid and other upcoming devices. Instead of physical buttons, these devices have a touch sensor that extends outside of the visible screen, creating an area for the "hard" keys to live as touch sensitive areas. The low-level input system looks for touches on the screen in this area, and turns these into "virtual" hard key events as appropriate.

To applications these basically look like real hard keys, though the generated events will have a new FLAG_VIRTUAL_HARD_KEY bit set to identify them. Regardless of that flag, in nearly all cases an application can handle these "hard" key events in the same way it has always done for real hard keys.

However, these keys introduce some wrinkles in user interaction. Most important is that the keys exist on the same surface as the rest of the user interface, and they can be easily pressed with the same kind of touches. This can become an issue, for example, when the virtual keys are along the bottom of the screen: a common gesture is to swipe up the screen for scrolling, and it can be very easy to accidentally touch a virtual key at the bottom when doing this.

The solution for this in 2.0 is to introduce a concept of a "canceled" key event. We've already seen this in the previous story, where handling a long press would cancel the following up event. In a similar way, moving from a virtual key press on to the screen will cause the virtual key to be canceled when it goes up.

In fact the previous code already takes care of this — by checking isCanceled() on the key up, canceled virtual keys and long presses will be ignored. There are also individual flags for these two cases, but they should rarely be used by applications and always with the understanding that in the future there may be more reasons for a key event to be canceled.

For existing application, where BACK key compatibility is turned on to execute the action on down, there is still the problem of accidentally detecting a back press when intending to perform a swipe. Though there is no solution for this except to update an application to specify it targets SDK version 5 or later, fortunately the back key is generally positioned on a far side of the virtual key area, so the user is much less likely to accidentally hit it than some of the other keys.

Writing an application that works well on pre-2.0 as well as 2.0 and later versions of the platform is also fairly easy for most common cases. For example, here is code that allows you to handle the back key in an activity correctly on all versions of the platform:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
            && keyCode == KeyEvent.KEYCODE_BACK
            && event.getRepeatCount() == 0) {
        // Take care of calling this method on earlier versions of
        // the platform where it doesn't exist.
        onBackPressed();
    }

    return super.onKeyDown(keyCode, event);
}

@Override
public void onBackPressed() {
    // This will be called either automatically for you on 2.0
    // or later, or by the code above on earlier versions of the
    // platform.
    return;
}

For the hard core: correctly dispatching events

One final topic that is worth covering is how to correctly handle events in the raw dispatch functions such as onDispatchEvent() or onPreIme(). These require a little more care, since you can't rely on some of the help the framework provides when it calls the higher-level functions such as onKeyDown(). The code below shows how you can intercept the dispatching of the BACK key such that you correctly execute your action when it is release.

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        if (event.getAction() == KeyEvent.ACTION_DOWN
                && event.getRepeatCount() == 0) {

            // Tell the framework to start tracking this event.
            getKeyDispatcherState().startTracking(event, this);
            return true;

        } else if (event.getAction() == KeyEvent.ACTION_UP) {
            getKeyDispatcherState().handleUpEvent(event);
            if (event.isTracking() && !event.isCanceled()) {

                // DO BACK ACTION HERE
                return true;

            }
        }
        return super.dispatchKeyEvent(event);
    } else {
        return super.dispatchKeyEvent(event);
    }
}

The call to getKeyDispatcherState() returns an object that is used to track the current key state in your window. It is generally available on the View class, and an Activity can use any of its views to retrieve the object if needed.