29 September 2009

Now available: Android 1.6 NDK

Today Android 1.6 NDK, release 1 is available for download from the Android developer site.

To recap, the NDK is a companion to the SDK that provides tools to generate and embed native ARM machine code within your application packages. This native code has the same restrictions as the VM code, but can execute certain operations much more rapidly. This is useful if you're doing heavy computations, digital processing, or even porting existing code bases written in C or C++.

If you already use the Android 1.5 NDK, upgrading to this release is highly recommended. It provides the following improvements:

  • The ability to use OpenGL ES 1.1 headers and libraries If your application targets Android 1.6, your native code can now directly call OpenGL ES 1.1 functions to perform graphics rendering. This will help those programs that need to send large amounts of vertex data to the GPU. Note, however, that activity lifecycle and surface creation must still be performed from the VM. This NDK contains a new sample ("san-angeles") that shows exactly how to do that with a GLSurfaceView object.
  • The ability to target either Android 1.5 or 1.6 devices The NDK parses your project's properties to know which platform release it is targeting. It will then automatically use the proper headers and libraries to generate your native code. Any application that targets 1.5 will run on Android 1.5, Android 1.6 and any future official system release. Targeting 1.6 should, thus, only be done if your application requires new 1.6 features / APIs, like the ability to call OpenGL ES 1.x headers from native code.
  • The ability to put your native sources under your application's project tree You can now conveniently place all your sources (C, C++ and Java) under the same tree, for editing or version control purposes.
  • Many fixes to the NDK's build scripts The changes to the build scripts fix some annoying bugs and also increase host system compatibility.

If you have any questions, please join us in the Android NDK forum.

28 September 2009

Zipalign: an easy optimization

The Android 1.6 SDK includes a tool called zipalign that optimizes the way an application is packaged. Doing this enables Android to interact with your application more efficiently and thus has the potential to make your application and the overall system run faster. We strongly encourage you to use zipalign on both new and already published applications and to make the optimized version available—even if your application targets a previous version of Android. We'll get into more detail on what zipalign does, how to use it, and why you'll want to do so in the rest of this post.

In Android, data files stored in each application's apk are accessed by multiple processes: the installer reads the manifest to handle the permissions associated with that application; the Home application reads resources to get the application's name and icon; the system server reads resources for a variety of reasons (e.g. to display that application's notifications); and last but not least, the resource files are obviously used by the application itself.

The resource-handling code in Android can efficiently access resources when they're aligned on 4-byte boundaries by memory-mapping them. But for resources that are not aligned (i.e. when zipalign hasn't been run on an apk), it has to fall back to explicitly reading them—which is slower and consumes additional memory.

For an application developer like you, this fallback mechanism is very convenient. It provides a lot of flexibility by allowing for several different development methods, including those that don't include aligning resources as part of their normal flow.

Unfortunately, the situation is reversed for users—reading resources from unaligned apks is slow and takes a lot of memory. In the best case, the only visible result is that both the Home application and the unaligned application launch slower than they otherwise should. In the worst case, installing several applications with unaligned resources increases memory pressure, thus causing the system to thrash around by having to constantly start and kill processes. The user ends up with a slow device with a poor battery life.

Luckily, it's very easy to align the resources:

  • Using ADT:
    • ADT (starting with 0.9.3) will automatically align release application packages if the export wizard is used to create them. To use the wizard, right click the project and choose "Android Tools" > "Export Signed Application Package..." It can also be accessed from the first page of the AndroidManifest.xml editor.
  • Using Ant:
    • The Ant build script that targets Android 1.6 (API level 4) can align application packages. Targets for older versions of the Android platform are not aligned by the Ant build script and need to be manually aligned.
    • Debug packages built with Ant for Android 1.6 applications are aligned and signed by default.
    • Release packages are aligned automatically only if Ant has enough information to sign the packages, since aligning has to happen after signing. In order to be able to sign packages, and therefore to align them, Ant needs to know the location of the keystore and the name of the key in build.properties. The name of the properties are key.store and key.alias respectively. If those properties are present, the signing tool will prompt to enter the store/key passwords during the build, and the script will sign and then align the apk file. If the properties are missing, the release package will not be signed, and therefore will not get aligned either.
  • Manually:
    • In order to manually align a package, zipalign is in the tools folder of the Android 1.6 SDK. It can be used on application packages targeting any version of Android. It should be run after signing the apk file, using the following command:
      zipalign -v 4 source.apk destination.apk
  • Verifying alignment:
    • The following command verifies that a package is aligned:
      zipalign -c -v 4 application.apk

We encourage you manually run zipalign on your currently published applications and to make the newly aligned versions available to users. And don't forget to align any new applications going forward!

25 September 2009

A Note on Google Apps for Android

Lately we've been busy bees in Mountain View, as you can see from the recent release of Android 1.6 to the open-source tree, not to mention some devices we're working on with partners that we think you'll really like. Of course, the community isn't sitting around either, and we've been seeing some really cool and impressive things, such as the custom Android builds that are popular with many enthusiasts. Recently there's been some discussion about an exchange we had with the developer of one of those builds, and I've noticed some confusion around what is and isn't part of Android's open source code. I want to take a few moments to clear up some of those misconceptions, and explain how Google's apps for Android fit in.

Everyone knows that mobile is a big deal, but for a long time it was hard to be a mobile app developer. Competing interests and the slow pace of platform innovation made it hard to create innovative apps. For our part, Google offers a lot of services — such as Google Search, Google Maps, and so on — and we found delivering those services to users' phones to be a very frustrating experience. But we also found that we weren't alone, so we formed the Open Handset Alliance, a group of like-minded partners, and created Android to be the platform that we all wished we had. To encourage broad adoption, we arranged for Android to be open-source. Google also created and operates Android Market as a service for developers to distribute their apps to Android users. In other words, we created Android because the industry needed an injection of openness. Today, we're thrilled to see all the enthusiasm that developers, users, and others in the mobile industry have shown toward Android.

With a high-quality open platform in hand, we then returned to our goal of making our services available on users' phones. That's why we developed Android apps for many of our services like YouTube, Gmail, Google Voice, and so on. These apps are Google's way of benefiting from Android in the same way that any other developer can, but the apps are not part of the Android platform itself. We make some of these apps available to users of any Android-powered device via Android Market, and others are pre-installed on some phones through business deals. Either way, these apps aren't open source, and that's why they aren't included in the Android source code repository. Unauthorized distribution of this software harms us just like it would any other business, even if it's done with the best of intentions.

I hope that clears up some of the confusion around Google's apps for Android. We always love seeing novel uses of Android, including custom Android builds from developers who see a need. I look forward to seeing what comes next!

24 September 2009

ADC 2 Judging Has Begun!

ADC 2 App LogoADC 2 Judging App ScreenshotI am happy to announce that Android Developer Challenge 2's first round of judging has begun!

As a reminder, user voting determines which apps will make it to the second round. Voting will occur through an application called Android Developer Challenge 2, which is now available for download from Android Market. Android Developer Challenge 2 presents apps for each user to download and score according to a set of criteria, such as originality and effective use of the Android platform, among others. The first round of judging will last at least two weeks from today. Judging will continue until we receive a sufficient number of votes to identify the top 20 applications in each of the 10 categories (200 apps total) that qualify for the second round.

During the second round, judging will occur through a combination of user voting and input from a panel of industry experts. User voting will continue to occur via Android Developer Challenge 2 and will account for 40% of the final score that each app receives in round two. The remaining 60% of the final score will be determined by the industry expert panel.

It has been a little less than a year since the first Android-powered phones became available. Today, there are more than 10,000 applications available in Android Market. We are pleased by the energy and commitment demonstrated by developers in such a short period of time. Our goal with Android Developer Challenge 2 is to inspire the developer community to produce even more innovative apps for Android. Now on to the voting!

Download Android Developer Challenge 2:

QR code for ADC2 app download

23 September 2009

An introduction to Text-To-Speech in Android

We've introduced a new feature in version 1.6 of the Android platform: Text-To-Speech (TTS). Also known as "speech synthesis", TTS enables your Android device to "speak" text of different languages.

Before we explain how to use the TTS API itself, let's first review a few aspects of the engine that will be important to your TTS-enabled application. We will then show how to make your Android application talk and how to configure the way it speaks.

Languages and resources

About the TTS resources

The TTS engine that ships with the Android platform supports a number of languages: English, French, German, Italian and Spanish. Also, depending on which side of the Atlantic you are on, American and British accents for English are both supported.

The TTS engine needs to know which language to speak, as a word like "Paris", for example, is pronounced differently in French and English. So the voice and dictionary are language-specific resources that need to be loaded before the engine can start to speak.

Although all Android-powered devices that support the TTS functionality ship with the engine, some devices have limited storage and may lack the language-specific resource files. If a user wants to install those resources, the TTS API enables an application to query the platform for the availability of language files and can initiate their download and installation. So upon creating your activity, a good first step is to check for the presence of the TTS resources with the corresponding intent:

Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);

A successful check will be marked by a CHECK_VOICE_DATA_PASS result code, indicating this device is ready to speak, after the creation of our android.speech.tts.TextToSpeech object. If not, we need to let the user know to install the data that's required for the device to become a multi-lingual talking machine! Downloading and installing the data is accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take the user to Android Market, and will let her/him initiate the download. Installation of the data will happen automatically once the download completes. Here is an example of what your implementation of onActivityResult() would look like:

private TextToSpeech mTts;
protected void onActivityResult(
        int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_DATA_CHECK_CODE) {
        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
            // success, create the TTS instance
            mTts = new TextToSpeech(this, this);
        } else {
            // missing data, install it
            Intent installIntent = new Intent();
            installIntent.setAction(
                TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
            startActivity(installIntent);
        }
    }
}

In the constructor of the TextToSpeech instance we pass a reference to the Context to be used (here the current Activity), and to an OnInitListener (here our Activity as well). This listener enables our application to be notified when the Text-To-Speech engine is fully loaded, so we can start configuring it and using it.

Languages and Locale

At Google I/O, we showed an example of TTS where it was used to speak the result of a translation from and to one of the 5 languages the Android TTS engine currently supports. Loading a language is as simple as calling for instance:

mTts.setLanguage(Locale.US);

to load and set the language to English, as spoken in the country "US". A locale is the preferred way to specify a language because it accounts for the fact that the same language can vary from one country to another. To query whether a specific Locale is supported, you can use isLanguageAvailable(), which returns the level of support for the given Locale. For instance the calls:

mTts.isLanguageAvailable(Locale.UK))
mTts.isLanguageAvailable(Locale.FRANCE))
mTts.isLanguageAvailable(new Locale("spa", "ESP")))

will return TextToSpeech.LANG_COUNTRY_AVAILABLE to indicate that the language AND country as described by the Locale parameter are supported (and the data is correctly installed). But the calls:

mTts.isLanguageAvailable(Locale.CANADA_FRENCH))
mTts.isLanguageAvailable(new Locale("spa"))

will return TextToSpeech.LANG_AVAILABLE. In the first example, French is supported, but not the given country. And in the second, only the language was specified for the Locale, so that's what the match was made on.

Also note that besides the ACTION_CHECK_TTS_DATA intent to check the availability of the TTS data, you can also use isLanguageAvailable() once you have created your TextToSpeech instance, which will return TextToSpeech.LANG_MISSING_DATA if the required resources are not installed for the queried language.

Making the engine speak an Italian string while the engine is set to the French language will produce some pretty interesting results, but it will not exactly be something your user would understand So try to match the language of your application's content and the language that you loaded in your TextToSpeech instance. Also if you are using Locale.getDefault() to query the current Locale, make sure that at least the default language is supported.

Making your application speak

Now that our TextToSpeech instance is properly initialized and configured, we can start to make your application speak. The simplest way to do so is to use the speak() method. Let's iterate on the following example to make a talking alarm clock:

String myText1 = "Did you sleep well?";
String myText2 = "I hope so, because it's time to wake up.";
mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, null);
mTts.speak(myText2, TextToSpeech.QUEUE_ADD, null);

The TTS engine manages a global queue of all the entries to synthesize, which are also known as "utterances". Each TextToSpeech instance can manage its own queue in order to control which utterance will interrupt the current one and which one is simply queued. Here the first speak() request would interrupt whatever was currently being synthesized: the queue is flushed and the new utterance is queued, which places it at the head of the queue. The second utterance is queued and will be played after myText1 has completed.

Using optional parameters to change the playback stream type

On Android, each audio stream that is played is associated with one stream type, as defined in android.media.AudioManager. For a talking alarm clock, we would like our text to be played on the AudioManager.STREAM_ALARM stream type so that it respects the alarm settings the user has chosen on the device. The last parameter of the speak() method allows you to pass to the TTS engine optional parameters, specified as key/value pairs in a HashMap. Let's use that mechanism to change the stream type of our utterances:

HashMap<String, String> myHashAlarm = new HashMap();
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
        String.valueOf(AudioManager.STREAM_ALARM));
mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);

Using optional parameters for playback completion callbacks

Note that speak() calls are asynchronous, so they will return well before the text is done being synthesized and played by Android, regardless of the use of QUEUE_FLUSH or QUEUE_ADD. But you might need to know when a particular utterance is done playing. For instance you might want to start playing an annoying music after myText2 has finished synthesizing (remember, we're trying to wake up the user). We will again use an optional parameter, this time to tag our utterance as one we want to identify. We also need to make sure our activity implements the TextToSpeech.OnUtteranceCompletedListener interface:

mTts.setOnUtteranceCompletedListener(this);
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
        String.valueOf(AudioManager.STREAM_ALARM));
mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
        "end of wakeup message ID");
// myHashAlarm now contains two optional parameters
mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);

And the Activity gets notified of the completion in the implementation of the listener:

public void onUtteranceCompleted(String uttId) {
    if (uttId == "end of wakeup message ID") {
        playAnnoyingMusic();
    } 
}

File rendering and playback

While the speak() method is used to make Android speak the text right away, there are cases where you would want the result of the synthesis to be recorded in an audio file instead. This would be the case if, for instance, there is text your application will speak often; you could avoid the synthesis CPU-overhead by rendering only once to a file, and then playing back that audio file whenever needed. Just like for speak(), you can use an optional utterance identifier to be notified on the completion of the synthesis to the file:

HashMap<String, String> myHashRender = new HashMap();
String wakeUpText = "Are you up yet?";
String destFileName = "/sdcard/myAppCache/wakeUp.wav";
myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, wakeUpText);
mTts.synthesizeToFile(wakuUpText, myHashRender, destFileName);

Once you are notified of the synthesis completion, you can play the output file just like any other audio resource with android.media.MediaPlayer.

But the TextToSpeech class offers other ways of associating audio resources with speech. So at this point we have a WAV file that contains the result of the synthesis of "Wake up" in the previously selected language. We can tell our TTS instance to associate the contents of the string "Wake up" with an audio resource, which can be accessed through its path, or through the package it's in, and its resource ID, using one of the two addSpeech() methods:

mTts.addSpeech(wakeUpText, destFileName);

This way any call to speak() for the same string content as wakeUpText will result in the playback of destFileName. If the file is missing, then speak will behave as if the audio file wasn't there, and will synthesize and play the given string. But you can also take advantage of that feature to provide an option to the user to customize how "Wake up" sounds, by recording their own version if they choose to. Regardless of where that audio file comes from, you can still use the same line in your Activity code to ask repeatedly "Are you up yet?":

mTts.speak(wakeUpText, TextToSpeech.QUEUE_ADD, myHashAlarm);

When not in use...

The text-to-speech functionality relies on a dedicated service shared across all applications that use that feature. When you are done using TTS, be a good citizen and tell it "you won't be needing its services anymore" by calling mTts.shutdown(), in your Activity onDestroy() method for instance.

Conclusion

Android now talks, and so can your apps. Remember that in order for synthesized speech to be intelligible, you need to match the language you select to that of the text to synthesize. Text-to-speech can help you push your app in new directions. Whether you use TTS to help users with disabilities, to enable the use of your application while looking away from the screen, or simply to make it cool, we hope you'll enjoy this new feature.

17 September 2009

Introducing Quick Search Box for Android

One of the new features we're really proud of in the Android 1.6 release is Quick Search Box for Android. This is our new system-wide search framework, which makes it possible for users to quickly and easily find what they're looking for, both on their devices and on the web. It suggests content on your device as you type, like apps, contacts, browser history, and music. It also offers results from the web search suggestions, local business listings, and other info from Google, such as stock quotes, weather, and flight status. All of this is available right from the home screen, by tapping on Quick Search Box (QSB).

What we're most excited about with this new feature is the ability for you, the developers, to leverage the QSB framework to provide quicker and easier access to the content inside your apps. Your apps can provide search suggestions that will surface to users in QSB alongside other search results and suggestions. This makes it possible for users to access your application's content from outside your application—for example, from the home screen.

The code fragments below are related to a new demo app for Android 1.6 called Searchable Dictionary.


The story before now: searching within your app

In previous releases, we already provided a mechanism for you to expose search and search suggestions in your app as described in the docs for SearchManager. This mechanism has not changed and requires the following two things in your AndroidManifest.xml:

1) In your <activity>, an intent filter, and a reference to a searchable.xml file (described below):

<intent-filter>
    <action android:name="android.intent.action.SEARCH" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
            
<meta-data android:name="android.app.searchable"
       android:resource="@xml/searchable" />

2) A content provider that can provide search suggestions according to the URIs and column formats specified by the Search Suggestions section of the SearchManager docs:

<!-- Provides search suggestions for words and their definitions. -->
<provider android:name="DictionaryProvider"
       android:authorities="dictionary"
       android:syncable="false" />

In the searchable.xml file, you specify a few things about how you want the search system to present search for your app, including the authority of the content provider that provides suggestions for the user as they type. Here's an example of the searchable.xml of an Android app that provides search suggestions within its own activities:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/search_label"
        android:searchSuggestAuthority="dictionary"
        android:searchSuggestIntentAction="android.intent.action.VIEW">
</searchable>

Note that the android:searchSuggestAuthority attribute refers to the authority of the content provider we declared in AndroidManifest.xml.

For more details on this, see the Searchability Metadata section of the SearchManager docs.

Including your app in Quick Search Box

In Android 1.6, we added a new attribute to the metadata for searchables: android:includeInGlobalSearch. By specifying this as "true" in your searchable.xml, you allow QSB to pick up your search suggestion content provider and include its suggestions along with the rest (if the user enables your suggestions from the system search settings).

You should also specify a string value for android:searchSettingsDescription, which describes to users what sorts of suggestions your app provides in the system settings for search.

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
       android:label="@string/search_label"
       android:searchSettingsDescription="@string/settings_description"
       android:includeInGlobalSearch="true"
       android:searchSuggestAuthority="dictionary"
       android:searchSuggestIntentAction="android.intent.action.VIEW">
</searchable>

These new attributes are supported only in Android 1.6 and later.

What to expect

The first and most important thing to note is that when a user installs an app with a suggestion provider that participates in QSB, this new app will not be enabled for QSB by default. The user can choose to enable particular suggestion sources from the system settings for search (by going to "Search" > "Searchable items" in settings).

You should consider how to handle this in your app. Perhaps show a notice that instructs the user to visit system settings and enable your app's suggestions.

Once the user enables your searchable item, the app's suggestions will have a chance to show up in QSB, most likely under the "more results" section to begin with. As your app's suggestions are chosen more frequently, they can move up in the list.

Shortcuts

One of our objectives with QSB is to make it faster for users to access the things they access most often. One way we've done this is by 'shortcutting' some of the previously chosen search suggestions, so they will be shown immediately as the user starts typing, instead of waiting to query the content providers. Suggestions from your app may be chosen as shortcuts when the user clicks on them.

For dynamic suggestions that may wish to change their content (or become invalid) in the future, you can provide a 'shortcut id'. This tells QSB to query your suggestion provider for up-to-date content for a suggestion after it has been displayed. For more details on how to manage shortcuts, see the Shortcuts section within the SearchManager docs.


QSB provides a really cool way to make your app's content quicker to access by users. To help you get your app started with it, we've created a demo app which simply provides access to a small dictionary of words in QSB—it's called Searchable Dictionary, and we encourage you to check it out.

15 September 2009

Android 1.6 SDK is here

I am happy to let you know that Android 1.6 SDK is available for download. Android 1.6, which is based on the donut branch from the Android Open Source Project, introduces a number of new features and technologies. With support for CDMA and additional screen sizes, your apps can be deployed on even more mobile networks and devices. You will have access to new technologies, including framework-level support for additional screen resolutions, like QVGA and WVGA, new telephony APIs to support CDMA, gesture APIs, a text-to-speech engine, and the ability to integrate with Quick Search Box. What's new in Android 1.6 provides a more complete overview of this platform update.

The Android 1.6 SDK requires a new version of Android Development Tools (ADT). The SDK also includes a new tool that enables you to download updates and additional components, such as new add-ons or platforms.

You can expect to see devices running Android 1.6 as early as October. As with previous platform updates, applications written for older versions of Android will continue to run on devices with Android 1.6. Please test your existing apps on the Android 1.6 SDK to make sure they run as expected.

Over the next several weeks, we will publish a series of blog posts to help you get ready for the new developer technologies in Android 1.6. The following topics, and more, will be covered: how to adapt your applications to support different screen sizes, integrating with Quick Search Box, building gestures into your apps, and using the text-to-speech engine.

If you are interested to see some highlights of Android 1.6, check out the video below.

Happy coding!

03 September 2009

Some News from Android Market

I'm pleased to let you know about several updates to Android Market. First, we will soon introduce new features in Android Market for Android 1.6 that will improve the overall experience for users. As part of this change, developers will be able to provide screenshots, promotional icons and descriptions that will better show off applications and games.

We have also added four new sub-categories for applications: sports, health, themes, and comics. Developers can now choose these sub-categories for both new and existing applications via the publisher website. Finally, we have added seller support for developers in Italy. Italian developers can go to the publisher website to upload applications and target any of the countries where paid applications are currently available to users.

To take advantage of the upcoming Android Market refresh, we encourage you to visit the Android Market publisher website and upload additional marketing assets. Check out the video below for some of the highlights.