Alexandra's Mobile [Ad]itude - We obsess about user experience



In my last post, some of you expressed concern that intrusive and oversized advertisements on a small screen could result in a poor mobile user experience. You asked how we strike the delicate balance between ensuring a good user experience while providing effective advertising. At Google, we care very deeply about this balance and we're constantly striving to make sure that you have the best experience possible. In this post, I'll tell you more about some of the things we're doing to try to achieve this.

At the core of striking this balance is working hard to improve ad quality. The more relevant the ads, the fewer ads there need to be. In fact, when you go to google.com on your phone and do a search, we now return no more than two text ads per query. These ads can appear above or below the organic search results and most take up just two lines of text on larger mobile screens. And while a single ad may appear at the top or bottom of a mobile content page, a double ad unit can only appear at the bottom of a page. Watch the video below to learn more about ad size and placement.

Of course, we also want to make sure our advertisers have a good experience with Google mobile ads. Fewer ads per page can be beneficial for an advertiser because there is less clutter on each page and each ad gets more visibility. More importantly, showing relevant ads and maintaining a good user experience results in better click-through rates and return on investment.

I hope this addresses some of your questions. Thanks so much for your comments on my last post and keep submitting more questions. This is your opportunity to guide the direction of this series!

Google Maps now native on more phones: Do UIQ? We do.



As a mobile user, you choose a carrier, subscription plan, platform and handset model (think of it as a flavour) that suits your fancy. And with mobile applications becoming more and more important in your everyday wireless experience, you want to be sure that the apps you know and love will run beautifully on the phone you finally decide to call your own.

That's why we've just released a "native" UIQ version of our Google Maps for mobile client application. Native applications are optimized for the platform on which they're built, meaning they run fast and feel right. UIQ is an open mobile software platform that supports rich user interfaces like touch- and full-screen. Now that Google Maps for mobile runs natively on UIQ for Symbian OS, you can get the full benefit of handy features like My Location on a wider range of phones.

You can already get Google Maps for mobile clients custom-built for Palm, BlackBerry, Windows Mobile, iPhone, and Symbian S60, in addition to the widely-used Java version of the application. Now, this list includes the following UIQ handsets (version 3.0 and up): new Sony Ericsson phones with touch screens -- P1, W960i, W950, M600 or P990 -- and the Motorola Z8. And new UIQ phones are coming out all the time; look for the soon-to-be-released Sony Ericsson G700 and G900, as well as the Motorola Z10.

Supporting so many platforms means only one thing: whatever gold-plated, diamond-encrusted or mint-scented handset you choose, a zippy mobile mapping experience is never more than a download away. Just visit google.com/gmm from your phone's web browser, and we'll get you sorted.

WikiNotes for Android: Routing Intents

In the last article, we talked about using Linkify to turn wiki words (those that match a regular expression we defined) into a content: URI and defining a path to data that matched a note belonging to that wiki word. As an example, a matching word like ToDoList would be turned into a content: URI like content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList and then acted upon using the VIEW action from the Linkify class.



This article will examine how the Android operating system takes this combination of VIEW action and content: URI and finds the correct activity to fire in order to do something with the data. It will also explain how the other default links created by Linkify, like web URLs and telephone numbers, also result in the correct activity to handle that data type being fired. Finally, this article will start to examine the custom ContentProvider that has been created to handle WikiNotes data. The full description of the ContentProvider and what it does will span a couple more articles as well, because there is a lot to cover.



The Linkify-calls-intent Workflow


At a high level, the steps for Linkify to invoke an intent and for the resulting activity (if any) to handle it looks like this:




  1. Linkify is invoked on a TextView to turn matching text patterns into Intent links.

  2. Linkify takes over monitoring for those Intent links being selected by the user.

  3. When the user selects a link, Linkify calls the VIEW action using the content: URI associated with the link.

  4. Android takes the content: URI that represents the data, and looks for a ContentProvider registered in the system that matches the URI.

  5. If a match is found, Android queries the ContentProvider using the URI, and asks what MIME type the data that will be returned from the URI is.

  6. Android then looks for an activity registered in the system with an intent-filter that matches both the VIEW action, and the MIME type for the data represented by the content: URI.

  7. Assuming a match is found, Linkify then invokes the intent for the URI, at which point the activity takes over, and is handed the content: URI.

  8. The activity can then use the URI to retrieve the data and act on it.



If this sounds complicated, it really is a simpler process than it sounds, and it is quite lightweight as well. Perhaps a more understandable statement about how it works might be:



Linkify is used to turn matching text into hot-links. When the user selects a hot-link, Android takes the data locator represented by the hot-link and looks for a data handler for that data locator. If it finds one, it asks for what type of data is returned for that locator. It then looks for something registered with the system that handles that type of data for the VIEW action, and starts it, including the data locator in the request.



The real key here is the MIME type. MIME stands for Multipurpose Internet Mail Extensions - a standard for sending attachments over email. The MIME type (which is the part Android uses) is a way of describing certain kinds of data. That type is then used to look for an Activity that can do something with that data type. In this way, ContentProviders and Activities (or other IntentReceivers) are decoupled, meaning that a given Content URI might have a different ContentProvider to handle it, but could still use the same MIME type meaning that the same activity could be called upon to handle the resulting data.



Linkify on a Wiki Word



Using the above workflow, let's take a look at exactly how the process works in WikiNotes for Android:



First, Linkify is used to turn text matching the wiki word regular expression into a link that provides a Content URI for that wiki word, for example content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList.



When the user clicks on the wiki word link, Linkify invokes the VIEW action on the Content URI. At this point, the Android system takes over getting the Intent request to the correct activity.



Next, Android looks for a ContentProvider that has been registered with the system to handle URIs matching our Content URI format.



In our case, we have a definition inside our application in the AndroidManifest.xml file that reads:



<provider name="com.google.android.wikinotes.db.WikiNotesProvider" 
android:authorities="com.google.android.wikinotes.db.wikinotes" />


This establishes that we have a ContentProvider defined in our application that provides the "root authority": com.google.android.wikinotes.db.wikinotes. This is the first part of the Content URI that we create for a wiki word link. Root Authority is just another way of thinking about a descriptor that is registered with Android to allow requests for certain URLs to be routed to the correct class.



So, the whole definition is that a class called com.google.android.wikinotes.db.WikiNotesProvider is registered with the system as able to handle the com.google.android.wikinotes.db.wikinotes root authority (i.e. URIs starting with that identifier).



From here, Android takes the rest of the URI and present it to that ContentProvider. If you look at the WikiNotesProvider class and scroll to the very bottom - the static block there, you can see the pattern definitions to match the rest of the URL.



In particular, take a look at the two lines:



URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes", NOTES);
URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes/*", NOTE_NAME);


These are the definitions of URIs that our ContentProvider recognizes and can handle. The first recognizes a full URI of content://com.google.android.wikinotes.db.wikinotes/wikinotes and associates that with a constant called NOTES. This is used elsewhere in the ContentProvider to provide a list of all of the wiki notes in the database when the URI is requested.



The second line uses a wildcard - '*' - to match a request of the form that Linkify will create, e.g. content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList. In this example, the * matches the ToDoList part of the URI and is available to the handler of the request, so that it can fish out the matching note for ToDoList and return it as the data. This also associates that match with a constant called NOTE_NAME, which again is used as an identifier elsewhere in the ContentProvider.



The other matches in this static block are related to forms of searching that have been implemented in the WikiNotes for Android application, and will be covered in later articles. Likewise, how the data is obtained from this matching pattern will be the subject of the next article.



For right now we are concerned with the MIME type for the URI. This is defined in the getType() method also in the WikiNotesProvider class (about half way through the file). Take a quick look at this. The key parts for now are:



case NOTES:
return "vnd.android.cursor.dir/vnd.google.wikinote";


and

case NOTE_NAME:
return "vnd.android.cursor.item/vnd.google.wikinote";


These are the same constant names we defined in our pattern matchers. In the first case, that of the all notes URI, the MIME type returned is vnd.android.cursor.dir/vnd.google.wikinote which is like saying an Android list (dir) of Google wiki notes (the vnd bit is MIME speak for "vendor specific definition"). Likewise, in the case of a NOTE_NAME match, the MIME type returned is vnd.android.cursor.item/vnd.google.wikinote which is like saying an Android item of Google wiki notes.



Note that if you define your own MIME data types like this, the vnd.android.cursor.dir and vnd.android.cursor.item categories should be retained, since they have meaning to the Android system, but the actual item types should be changed to reflect your particular data type.



So far Android has been able to find a ContentProvider that handles the Content URI supplied by the Linkify Intent call, and has queried the ContentProvider to find out the MIME types for that URI. The final step is to find an activity that can handle the VIEW action for that MIME type. Take a look in the the AndroidManifest.xml file again. Inside the WikiNotes activity definition, you will see:



<intent-filter>
<action name="android.intent.action.VIEW"/>
<category name="android.intent.category.DEFAULT"/>
<category name="android.intent.category.BROWSABLE"/>
<data mimetype="vnd.android.cursor.item/vnd.google.wikinote"/>
</intent-filter>


This is the correct combination of matches for the VIEW action on a WikiNote type that is requested from the LINKIFY class. The DEFAULT category indicates that the WikiNotes activity should be treated as a default handler (a primary choice) for this kind of data, and the BROWSABLE category means it can be invoked from a "browser", in this case the marked-up Linkified text.



Using this information, Android can match up the VIEW action request for the WikiNotes data type with the WikiNotes activity, and can then use the WikiNotes activity to handle the request.



Why do it like this?



It's quite a trip through the system, and there is a lot to absorb here, but this is one of the main reasons I wanted to write WikiNotes in the first place. If you follow and understand the steps here, you'll have a good grasp of the whole Intents mechanism in Android, and how it helps loosely coupled activities cooperate to get things done.



In this case, we could have found another way to detect wiki words based on a regular expression, and maybe written our own handler to intercept clicks within the TextView and dig out the right data and display it. This would seem to accomplish the same functionality just as easily as using intents, so what is the advantage to using the full Intents mechanism?



In fact there are several advantages:



The most obvious is that because we are using the standard Intent based approach, we are not limited to just linking and navigating to other wiki notes. We get similar behavior to a number of other data types as well. For example, a telephone number or web URL in a wiki note will be marked up by Linkify, and using this same mechanism (VIEW action on the linked data type) the browser or dialer activities will be automatically fired.



It also means that each operation on a wiki note can be treated as a separate life cycle by our activity. We are not dealing with swapping data in and out of an existing activity - each activity works on a particular wiki note and that's all you have to worry about.



Another advantage is that we now have a public activity to handle VIEW actions in WikiNotes no matter where the request comes from. Another application could request to view a wiki note (perhaps without even knowing what kind of data it is) and our activity could start up and handle it.



The backstack is automatically maintained for you too. As you forward navigate through WikiNotes, Android maintains the history of notes visited, and so when you hit the back button you go back to the last note you were on. All this is free because we rely on the Android intents mechanism.



Finally, if you run WikiNotes for Android and then start DDMS to take a look at the Activity threads in the WikiNotes application while it is running, you can see that despite what you might think, letting Android manage the navigation is very efficient. Create a few linked notes, as many links deep as you like, and then follow them. If you follow links hundreds of notes deep, you will still only see a handful of WikiNotes activities. Android is managing the activities, closing the older ones as necessary and using the life cycle to swap data in and out.



Next Time



This was a long article, but necessarily so. It demonstrates the importance of the Intents mechanism and to reinforce the notion that it should be used whenever possible for forward navigation, even within a single application. Illustrating this is one of the primary reasons I wrote WikiNotes for Android in the first place.



In the next article we will look deeper into the ContentProvider and examine how it turns a Content URI into a row (or several rows) of data that can be used by an activity.

Fast is better than slow



A few weeks ago, we launched a plug-in for Symbian devices that put a Google search shortcut onto the phone's home screen. This shortcut reduces the time it takes for you to get answers from Google by eliminating the initial search steps (e.g. finding the browser application, opening it, and navigating to Google.com before entering your query). The same plug-in has been available for BlackBerry devices since last December. Today, we're making this available for Windows Mobile devices too.

If you're a Windows Mobile user, browse to mobile.google.com on your device to download the plug-in and start searching faster than ever. Once you do, we think you'll find it so much faster and easier that you'll start conducting more mobile web searches than you ever had before. How do we know this? Well, when we look at the combined usage numbers for BlackBerry and Symbian versions of this plug-in, we see that users are able to get Google search results up to 40 percent faster. And, BlackBerry and Symbian users with the plug-in installed search 20 percent more than those without it.

We saw something similar after we launched an updated interface for Gmail on the iPhone during MacWorld earlier this year. Lots of iPhone users tried the new interface (hence the bump in Gmail pageviews between January and February), but they didn't stick around like we hoped they would. Over the course of the next few weeks, we made some tweaks to drastically improve the speed of the product, and Gmail pageviews on the iPhone not only stabilized, but began to rise, as the graph below shows:
This link between increased usage and a faster user experience -- be it search or mobile Gmail -- reinforces something we at Google have known for a long time: Fast is better than slow. With mobile applications, we're seeing that fast is much better than slow. Although this may seem pretty intuitive, it's always nice to see new data backing this up. Moving forward, we'll continue to focus on bringing you the fastest and most compelling mobile experiences that we can. So stay tuned!

Linkify your Text!

This is the first in a series of technical articles about WikiNotes for Android, part of the Apps for Android project.



This article covers the use of Linkify to turn ordinary text views into richer link-oriented content that causes Android intents to fire when a link is selected.



Linkify: The Linkify class in the SDK is perfect for creating a wiki note pad. This class lets you specify a regular expression to match, and a scheme to prepend. The scheme is a string that, when the matched text is added, forms a Content URI to allow the correct data to be looked up.



For example, in our case we want to look for a regular expression match for a WikiWord (that is, a word with camel case and no spaces). Linkify can then turn this into a Content URI - something like >content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord which can then be used to locate the correct wiki page from a content provider.



As a bonus, the Linkify class also defines several default matches, in particular it is able to turn web URLs, email addresses and telephone numbers into active links which fire Android intents automatically.



Linkify can be passed any TextView in your application, and will take care of creating the links and enabling their "clickability" for you.



Default Linkify: Using the set of default active link options is very straightforward - simply pass it a handle to a TextView with content in it, and the Linkify.ALL flag:



TextView noteView = (TextView) findViewById(R.id.noteview);
noteView.setText(someContent);
Linkify.addLinks(noteView, Linkify.ALL);


and that's it. The Linkify.ALL flag applies all of the predefined link actions, and the TextView will be immediately updated with a set of active links which, if you select them, fire default intents for the actions (e.g. a web URL will start the browser with that URL, a telephone number will bring up the phone dialer with that number ready to call, etc.).



Custom Linkify: So what about our WikiWord? There is no pre-defined action for that, so it needs to be defined and associated with a scheme.



The first task is to defined a regular expression that matches the kind of WikiWords we want to find. The regex in this case is:



\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b


Obvious no? Well actually this is equivalent to the following description: "Starting with a word boundary (the \b) find at least one upper case letter, followed by at least one lower case letter or a numeric digit, followed by another upper case letter, and then any mix of upper case, lower case or numeric until the next word boundary (the final \b)". Regular expressions are not very pretty, but they are an extremely concise and accurate way of specifying a search pattern.



We also need to tell Linkify what to do with a match to the WikiWord. Linkify will automatically append whatever is matched to a scheme that is supplied to it, so for the sake of argument let's assume we have a ContentProvider that matches the following content URI:



content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord


The WikiWord part will be appended by Linkify when it finds a match, so we just need the part before that as our scheme.



Now that we have these two things, we use Linkify to connect them up:



Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);


Note that the \b's had to be escaped with double backslashes for the Java Pattern.compile line.



Linkify can be used multiple times on the same view to add more links, so using this after the Default Linkify call means that the existing active links will be maintained and the new WikiWords will be added. You could define more Linkify actions and keep applying them to the same TextView if you wanted to.



Now, if we have a WikiWord in the TextView, let's say MyToDoList, Linkify will turn it into an active link with the content URI:



content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList


and if you click on it, Android will fire the default intent for that content URI.



For this to all work, you will need a ContentProvider that understands that Content URI, and you will need a default activity capable of doing something with the resulting data. I plan to cover these in future blog entries (and soon). In fact, the whole Wiki Note Pad application is currently undergoing some clean up and review, and will then hopefully be released as a sample application.

Fast tip: one-click access to Google mobile applications on your phone



I've heard it said that user interfaces are measured in "hurts." Here at Google we like things to be as painless as possible. That's why we're happy to share a little-known feature of many phones that allows you to launch your favorite app (hopefully Google Maps!) with the press of a button.

Buried in the settings menu of many phones is the option to configure "convenience keys" (or "sidekeys," or "shortcuts," depending on the device). Convenience keys let you configure a physical key, usually on the side of your phone, to instantly launch whatever application you choose. For instance, here are some instructions for how to configure a BlackBerry, Blackjack, and Nokia N95 for one-click access to Google Maps for mobile:

BlackBerry 8800: Go to Options->Screen/Keyboard->Convenience Key -> select 'Google Maps'
Samsung BlackJack: Select 'Settings' icon ->More ->Key settings ->Side key settings ->Select 'Google Maps'
Nokia N95: Press the 'Menu' button ->Tools ->Settings ->Personalization ->Standby mode ->Shortcuts ->Left/Right selection key -> Select 'Google Maps'

In the video below Steve Lee and I show you how to set up these quick access keys. Be sure to catch our death-defying duel at the end of the video, where one of us bites the dust while the other hurls obscure movie references.

Finally, if you use shortcut keys on other phones please submit a comment below so that others can give them a try.

Android Developer Challenge Deadline Approaching Quickly

The Android Developer Challenge is proceeding nicely. We're excited about the interest people have shown so far and have enjoyed talking to everyone working on new Android Apps.

As a quick reminder, the first phase of the challenge will be ending on April 14. In the Android Developer Challenge I, the 50 most promising entries received by April 14 will each receive a $25,000 award to fund further development. Those selected will then be eligible for even greater recognition via ten $275,000 awards and ten $100,000 awards.

Keep working on your applications, and be sure to post in the forums if you have any questions!

Announcing: Apps for Android

Screenshot of WikiNotes for AndroidWe are pleased to announce that a new open source project has been created on Google code hosting called apps-for-android. Our goal is to share some sample applications that demonstrate different aspects of the Android platform.



The first application to be included in the new project is called WikiNotes for Android.



For anyone not familiar with the concept of a wiki, it is a simple way to link up pages of information using WikiWords (words that use CamelCase). For example, in the previous sentence, both WikiWords and CamelCase would become live links in a Wiki, and would take you to pages of information.



WikiNotes for Android is a form of wiki known as a personal wiki. These run on desktops or (in this case) mobile computing devices, and many people like them. They bring a bit more structure to your notes than just a list of subjects. You can choose to link notes or pages up in any manner you like.



This particular implementation uses a regular expression to match WikiWords and turn them into links that fire Intents to go to other notes. Because of the way the links are implemented, the application will also create links out of telephone numbers that take you to the dialer and URLs that start up the browser.



Search by title and content is also implemented, so even if you forget the structure, you can still find that all-important note about where you left your car in the airport car park.



This wiki has a view mode and an edit mode. In view mode, the links become active and allow you to navigate to other notes, or to other activities like dialer and web browser. In edit mode, you see a plain text view that you can edit, and when you confirm the changes it goes back to view mode. There is both a menu entry and keyboard shortcut to switch to edit view, so that you can very quickly make changes. And, if you get lost in the note structure, there is also an option to take you back to the start page.



WikiNotes for Android was written to demonstrate a number of core concepts in Android, including:




  • Multiple Activities in an Application (View, Edit, Search, etc.)

  • Default intent filters for View/Edit/Search based on MIME types

  • Life cycle of Activities

  • Message passing via Bundles in Intents

  • Use of Linkify to add Intent-firing links to text data

  • Using Intents within an application

  • Using Intents to use an Activity within another application

  • Writing a custom ContentProvider that implements search by note title

  • Registration of ReST-like URIs to match titles, and do contents searches

  • SQLite implementations for insert, retrieve, update, delete and search

  • UI layout and creation for multiple activities

  • Menus and keyboard shortcuts



The application remains small in size and features to make it easy to understand. In time, more features will be added to the application to make it more useful, but a sample version with the minimal functionality will always be available for developers new to the Android platform.



If you believe that firing an Intent for every link that is clicked is sub-optimal and will waste resources, please take a look at the running application using DDMS. You will see how efficiently Android re-uses the running Activities and indeed, this is one of the main reasons WikiNotes for Android was written. It demonstrates that using the Android Activities and Intents infrastructure not only makes construction of component-based applications easy, but efficient as well.



There will also be a series of technical articles about the application right here on the Android Developer blog.



And please, keep an eye on the apps-for-android project, as more sample applications will be added to it soon.



Happy wiki-ing.

Shifting Google Gears to mobile



Ever use a mobile web application and suddenly lose your cell connection? That's happened to me many times. If you've shared my pain, you'll be excited to know that we've launched Google Gears for mobile, which lets users access Gears-enabled mobile web apps offline. Initially available for Internet Explorer Mobile on Windows Mobile 5 and 6 devices, mobile web app developers have already started integrating Gears for mobile into their online services.

Take Zoho and Buxfer, for example: Zoho is a powerful suite of web-based productivity applications, while Buxfer is an innovative personal finance web application that helps you track your money. With Google Gears for mobile integrated into mobile Zoho and Buxfer, you can now access these web applications even when your phone is disconnected from the mobile web. Stuck on a plane? No problem — you can still read your docs on your mobile with Zoho Writer Mobile offline. Want to buy that new plasma TV, but can't remember how much is in your account? Check your balance with Buxfer's mobile web application, even if there is no cell phone signal. Try them out on your Windows Mobile 6 device by going to m.buxfer.com or mobile.zoho.com.

When you first access mobile Buxfer or Zoho Writer on your Windows Mobile device and go offline, you will be asked to install Google Gears for mobile. Once installed, Gears sits happily on your phone helping you stay connected to your data -- even when you lose your network connection.

If you're a developer who's interested in creating mobile web applications using Google Gears for mobile you can find out more information on our developer site. Finally, if you're not a Windows Mobile user, stay tuned -- we're working to roll out Google Gears for other platforms with capable web browsers, including Android.

Android SDK update: m5-rc15 released

Earlier today we released an update to the Android SDK – we're calling it m5-rc15. With this update, the SDK now includes all of the incremental changes we've been making to the online documentation since m5-rc14 was released in mid-February. In addition to the latest documentation, we've also fixed a security issue involving handling of image files.



We recommend that you install m5-rc15 at your earliest convenience. The update doesn't change any of the Android APIs or introduce any new ones. Eclipse users don't need to update the ADT plug-in either.



Once you've unzipped the file on your machine, you will want to update things like your PATH variable and, if you're using Eclipse, the SDK location setting for ADT (hint: Preferences > Android).