Improved Google Search for BlackBerry 6.0 devices

Today we’ve updated the Google search experience for BlackBerry 6.0 WebKit enabled devices. We’ve added a number of enhanced search features integrated throughout the homepage and search result pages, making searching faster and easier on www.google.com, especially on touch-enabled Blackberry devices.


Left: Improved homepage with autocomplete and search history as you type.
Right: See more information with search options and enhanced results.

  • Enter searches faster: Save time by using autocomplete and search history queries that appear beneath the search box as you type.
  • Web search: Find what you're searching for fast. Comprehensive results pages let you see relevant websites, images, videos, news, real-time results and more. Simply click on the arrow button ‘>>’ to the left of the top search box for more refinement options.
  • Image search: Swipe through image results quickly and easily on touch enabled devices. Start by selecting ‘Images’ at the top of www.google.com, then enter a search. From there, click on any image to view a larger size.
  • Local search: Find restaurants, shops and other popular business categories with a single tap. Start by selecting ‘Places’ at the top of www.google.com, then click on an icon from the Places homepage.

These features and more are available on most RIM OS 6.0+ devices with WebKit browsers like the BlackBerry Torch and BlackBerry Bold 9780, and can be accessed in 20 languages across 70 countries.

To try out the new features, go to www.google.com in your mobile browser. We recommend that you bookmark Google Search to your phone’s home screen, so that Google search is just one click away.

The J. Paul Getty Museum collection comes alive with Google Goggles

The Google Goggles team has worked with The J. Paul Getty Museum in Los Angeles to “Goggles-enable” their permanent collection of paintings. You can use the Google Goggles app on your phone to take a photo of a painting from the collection and instantly access information about it from the Getty’s mobile-optimized website and the rest of the web. It's possible to fit only a small amount of information on the wall next to a painting but visitors with Goggles can now enjoy the full story online.

Google Goggles results and the Getty webpage for Portrait of the Sisters Bonaparte

Learn more on the Official Google Blog.

A Deep Dive Into Location

[This post is by Reto Meier, Tech Lead for Android Developer Relations, who wrote the book on Android App development. — Tim Bray]

I'm a big fan of location-based apps, but not their seemingly-inevitable startup latency.

Whether it's finding a place to eat or searching for the nearest Boris Bike, I find the delay while waiting for the GPS to get a fix, and then for the results list to populate, to be interminable. Once I’m in a venue and ready to get some tips, check-in, or review the food, I’m frequently thwarted by a lack of data connection.

Rather than shaking my fist at the sky, I’ve written an open-source reference app that incorporates all of the tips, tricks, and cheats I know to reduce the time between opening an app and seeing an up-to-date list of nearby venues - as well as providing a reasonable level of offline support — all while keeping the impact on battery life to a minimum.

Show Me the Code

You can check-out the Android Protips for Location open source project from Google Code. Don’t forget to read the Readme.txt for the steps required to make it compile and run successfully.

What Does it Actually Do?

It uses the Google Places API to implement the core functionality of apps that use location to provide a list of nearby points of interest, drill down into their details, and then check-in/rate/review them.

The code implements many of the best-practices I detailed in my Google I/O 2011 session, Android Protips: Advanced Topics for Expert Android Developers (video), including using Intents to receive location updates, using the Passive Location Provider, using and monitoring device state to vary refresh rates, toggling your manifest Receivers at runtime, and using the Cursor Loader.

The app targets Honeycomb but supports Android platforms from 1.6 and up.

Nothing would make me happier than for you to cut/copy/borrow / steal this code to build better location-based apps. If you do, I’d love it if you told me about it!

Now that you’ve got the code, let’s take a closer look at it

My top priority was freshness: Minimize the latency between opening the app and being able to check in to a desired location, while still minimizing the impact of the app on battery life.

Related requirements:

  • The current location has to be found as quickly as possible.


  • The list of venues should update when the location changes.


  • The list of nearby locations and their details must be available when we’re offline.


  • Check-ins must be possible while we’re offline.


  • Location data and other user data must be handled properly (see our prior blog post on best practices).


Freshness means never having to wait

You can significantly reduce the latency for getting your first location fix by retrieving the last known location from the Location Manager each time the app is resumed.

In this snippet taken from the GingerbreadLastLocationFinder, we iterate through each location provider on the device — including those that aren't currently available — to find the most timely and accurate last known location.

List<String> matchingProviders = locationManager.getAllProviders();
for (String provider: matchingProviders) {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
float accuracy = location.getAccuracy();
long time = location.getTime();

if ((time > minTime && accuracy < bestAccuracy)) {
bestResult = location;
bestAccuracy = accuracy;
bestTime = time;
}
else if (time < minTime &&
bestAccuracy == Float.MAX_VALUE && time > bestTime){
bestResult = location;
bestTime = time;
}
}
}

If there is one or more locations available from within the allowed latency, we return the most accurate one. If not, we simply return the most recent result.

In the latter case (where it’s determined that the last location update isn't recent enough) this newest result is still returned, but we also request a single location update using that fastest location provider available.

if (locationListener != null &&
(bestTime < maxTime || bestAccuracy > maxDistance)) {
IntentFilter locIntentFilter = new IntentFilter(SINGLE_LOCATION_UPDATE_ACTION);
context.registerReceiver(singleUpdateReceiver, locIntentFilter);
locationManager.requestSingleUpdate(criteria, singleUpatePI);
}

Unfortunately we can’t specify “fastest” when using Criteria to choose a location provider, but in practice we know that coarser providers — particularly the network location provider — tend to return results faster than the more accurate options. In this case I’ve requested coarse accuracy and low power in order to select the Network Provider when it’s available.

Note also that this code snippet shows the GingerbreadLastLocationFinder which uses the requestSingleUpdate method to receive a one-shot location update. This wasn’t available prior to Gingerbread - check out the LegacyLastLocationFinder to see how I have implemented the same functionality for devices running earlier platform versions.

The singleUpdateReceiver passes the received update back to the calling class through a registered Location Listener.

protected BroadcastReceiver singleUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(singleUpdateReceiver);

String key = LocationManager.KEY_LOCATION_CHANGED;
Location location = (Location)intent.getExtras().get(key);

if (locationListener != null && location != null)
locationListener.onLocationChanged(location);

locationManager.removeUpdates(singleUpatePI);
}
};

Use Intents to receive location updates

Having obtained the most accurate/timely estimate of our current location, we also want to receive location updates.

The PlacesConstants class includes a number of values that determine the frequency of location updates (and the associated server polling). Tweak them to ensure that updates occur exactly as often as required.

// The default search radius when searching for places nearby.
public static int DEFAULT_RADIUS = 150;
// The maximum distance the user should travel between location updates.
public static int MAX_DISTANCE = DEFAULT_RADIUS/2;
// The maximum time that should pass before the user gets a location update.
public static long MAX_TIME = AlarmManager.INTERVAL_FIFTEEN_MINUTES;

The next step is to request the location updates from the Location Manager. In this snippet taken from the GingerbreadLocationUpdateRequester we can pass the Criteria used to determine which Location Provider to request updates from directly into the requestLocationUpdates call.

public void requestLocationUpdates(long minTime, long minDistance, 
Criteria criteria, PendingIntent pendingIntent) {

locationManager.requestLocationUpdates(minTime, minDistance,
criteria, pendingIntent);
}

Note that we're passing in a Pending Intent rather than a Location Listener.

Intent activeIntent = new Intent(this, LocationChangedReceiver.class);
locationListenerPendingIntent =
PendingIntent.getBroadcast(this, 0, activeIntent, PendingIntent.FLAG_UPDATE_CURRENT);

I generally prefer this over using Location Listeners as it offers the flexibility of registering receivers in multiple Activities or Services, or directly in the manifest.

In this app, a new location means an updated list of nearby venues. This happens via a Service that makes a server query and updates the Content Provider that populates the place list.

Because the location change isn’t directly updating the UI, it makes sense to create and register the associated LocationChangedReceiver in the manifest rather than the main Activity.

<receiver android:name=".receivers.LocationChangedReceiver"/>

The Location Changed Receiver extracts the location from each update and starts the PlaceUpdateService to refresh the database of nearby locations.

if (intent.hasExtra(locationKey)) {
Location location = (Location)intent.getExtras().get(locationKey);
Log.d(TAG, "Actively Updating place list");
Intent updateServiceIntent =
new Intent(context, PlacesConstants.SUPPORTS_ECLAIR ? EclairPlacesUpdateService.class : PlacesUpdateService.class);
updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_LOCATION, location);
updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_RADIUS, PlacesConstants.DEFAULT_RADIUS);
updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_FORCEREFRESH, true);

context.startService(updateServiceIntent);
}

Monitor inactive providers for a better option

The snippet from PlacesActivity below shows how to monitor two important conditions:

  • The Location Provider we are using being deactivated.


  • A better Location Provider becoming available.


In either case, we simply re-run the process used to determine the best available provider and request location updates.

// Register a receiver that listens for when the provider I'm using has been disabled. 
IntentFilter intentFilter = new IntentFilter(PlacesConstants.ACTIVE_LOCATION_UPDATE_PROVIDER_DISABLED);
registerReceiver(locProviderDisabledReceiver, intentFilter);

// Listen for a better provider becoming available.
String bestProvider = locationManager.getBestProvider(criteria, false);
String bestAvailableProvider = locationManager.getBestProvider(criteria, true);
if (bestProvider != null && !bestProvider.equals(bestAvailableProvider))
locationManager.requestLocationUpdates(bestProvider, 0, 0,
bestInactiveLocationProviderListener, getMainLooper());

Freshness means always being up to date. What if we could reduce startup latency to zero?

You can start the PlacesUpdateService in the background to refresh the list of nearby locations while your app is in the background. Done correctly, a relevant list of venues can be immediately available when you open the app.

Done poorly, your users will never find this out as you’ll have drained their battery too quickly.

Requesting location updates (particularly using the GPS) while your app isn’t in the foreground is poor practice, as it can significantly impact battery life. Instead, you can use the Passive Location Provider to receive location updates alongside other apps that have already requested them.

This extract from the FroyoLocationUpdateRequester enables passive updates on Froyo+ platforms.

public void requestPassiveLocationUpdates(long minTime, long minDistance, PendingIntent pendingIntent) {
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
PlacesConstants.MAX_TIME, PlacesConstants.MAX_DISTANCE, pendingIntent);
}

As a result receiving background location updates is effectively free! Unfortunately the battery cost of your server downloads aren’t, so you’ll still need to carefully balance how often you act on passive location updates with battery life.

You can achieve a similar effect in pre-Froyo devices using inexact repeating non-wake alarms as shown in the LegacyLocationUpdateRequester.

public void requestPassiveLocationUpdates(long minTime, long minDistance, 
PendingIntent pendingIntent) {

alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,
System.currentTimeMillis()+PlacesConstants.MAX_TIME,
PlacesConstants.MAX_TIME, pendingIntent);
}

Rather than receiving updates from the Location Manager, this technique manually checks the last known location at a frequency determined by the maximum location update latency.

This legacy technique is significantly less efficient, so you may choose to simply disable background updates on pre-Froyo devices.

We handle updates themselves within the PassiveLocationChangedReceiver which determines the current location and starts the PlaceUpdateService.

if (location != null) {
Intent updateServiceIntent =
new Intent(context, PlacesConstants.SUPPORTS_ECLAIR ? EclairPlacesUpdateService.class : PlacesUpdateService.class);

updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_LOCATION, location);
updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_RADIUS,
PlacesConstants.DEFAULT_RADIUS);
updateServiceIntent.putExtra(PlacesConstants.EXTRA_KEY_FORCEREFRESH, false);
context.startService(updateServiceIntent);
}

Using Intents to passively receive location updates when your app isn't active

You’ll note that we registered the Passive Location Changed Receiver in the application manifest.

<receiver android:name=".receivers.PassiveLocationChangedReceiver"/>

As a result we can continue to receive these background updates even when the application has been killed by the system to free resources.

This offers the significant advantage of allowing the system to reclaim the resources used by your app, while still retaining the advantages of a zero latency startup.

If your app recognizes the concept of “exiting” (typically when the user clicks the back button on your home screen), it’s good form to turn off passive location updates - including disabling your passive manifest Receiver.

Being fresh means working offline

To add offline support we start by caching all our lookup results to the PlacesContentProvider and PlaceDetailsContentProvider.

Under certain circumstances we will also pre-fetch location details. This snippet from the PlacesUpdateService shows how pre-fetching is enabled for a limited number of locations.

Note that pre-fetching is also potentially disabled while on mobile data networks or when the battery is low.

if ((prefetchCount < PlacesConstants.PREFETCH_LIMIT) &&
(!PlacesConstants.PREFETCH_ON_WIFI_ONLY || !mobileData) &&
(!PlacesConstants.DISABLE_PREFETCH_ON_LOW_BATTERY || !lowBattery)) {
prefetchCount++;

// Start the PlaceDetailsUpdateService to prefetch the details for this place.
}

We use a similar technique to provide support for offline checkins. The PlaceCheckinService queues failed checkins, and checkins attempted while offline, to be retried (in order) when the ConnectivityChangedReceiver determines that we’re back online.

Optimizing battery life: Smart Services and using device state to toggle your manifest Receivers

There's no point running update services when we aren’t online, so the PlaceUpdateService checks for connectivity before attempting an update.

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();

If we’re not connected, the Passive and Active Location Changed Receivers are disabled and the the ConnectivityChangedReceiver is turned on.

ComponentName connectivityReceiver = 
new ComponentName(this, ConnectivityChangedReceiver.class);
ComponentName locationReceiver =
new ComponentName(this, LocationChangedReceiver.class);
ComponentName passiveLocationReceiver =
new ComponentName(this, PassiveLocationChangedReceiver.class);

pm.setComponentEnabledSetting(connectivityReceiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);

pm.setComponentEnabledSetting(locationReceiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);

pm.setComponentEnabledSetting(passiveLocationReceiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);

The ConnectivityChangedReceiver listens for connectivity changes. When a new connection is made, it simply disables itself and re-enables the location listeners.

Monitoring battery state to reduce functionality and save power

When your phone is on its last 15%, most apps are firmly in the back seat to conserving what watts you have remaining. We can register manifest Receivers to be alerted when the device enters or leaves the low battery state.

<receiver android:name=".receivers.PowerStateChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
<action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
</intent-filter>
</receiver>

This snippet from the PowerStateChangedReceiver disables the PassiveLocationChangedReceiver whenever the device enters a low battery state, and turns it back on once the battery level is okay.

boolean batteryLow = intent.getAction().equals(Intent.ACTION_BATTERY_LOW);

pm.setComponentEnabledSetting(passiveLocationReceiver,
batteryLow ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED :
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP);

You can extend this logic to disable all prefetching or reduce the frequency of your updates during low battery conditions.

What’s Next?

This is already a monster post, so I’m going to leave it there. I’ll follow up in the next week with a post on my personal blog, The Radioactive Yak, that will go in to more detail on the psychic and smooth elements of this app like using the Backup Manager and the Cursor Loader.

I also plan to build a similar reference app for news apps, so that I can spend more time reading and less time waiting.

In the mean time, happy coding!

Google Sites owners: Sites now auto-optimizes for mobile devices

As the dramatic growth of the mobile web changes the way people consume content, it’s becoming increasingly important for publishers to provide a good mobile experience. With this in mind, we just added automatic mobile rendering in Google Sites for iOS 3.0+ and Android 2.2+ devices, and a mobile version of the Google Sites lists. Learn more on the Google Docs blog.

Posted by Luciano Cheng, Software Engineer

Google Goggles learns Russian and gets a new view

Some of you may already be using the new optical character recognition (OCR) and translation of Russian in Google Goggles that we previewed at last week’s Inside Search event. Starting today, we’re pleased to introduce some additional new features, including a map view of your Search History and the ability to copy contact and text results to the clipboard. We’ve also changed the results interface to make it easier to view and navigate through your results.

Russian optical character recognition (OCR) and translation
Since Google Goggles first launched in 2009, it has been able to recognize and translate text in a number of different languages, as long as the language used Latin characters. With the launch of OCR for Russian, Goggles is now able to read Cyrillic characters. Goggles will recognize a picture of Russian text and allow you to translate the text into one of over 40 other languages. Russian OCR is also available for users of Google Goggles on the Google Search app for iOS. Очень полезно!

You can take a picture of Russian text and translate it into over 40 languages.


Map view of your search history
If you’ve enabled search history on Goggles, your history contains a list of all the images that you’ve searched for, as well as some information about where you performed the search if you chose to share your location with Google. Sometimes this can be a pretty long list, so we wanted to give you another way to sort and visualize your Goggles results.

We’ve added a map view, which shows your Goggles image search history on a map so you can quickly zoom and pan to find a query from a particular location.

Easily toggle between map view and list view with the button in the upper right.


Copy contact and text results to clipboard
Finally, imagine that you wanted to grab a URL or telephone number from a sign and email it to yourself. Now, Goggles gives you the option of copying the recognized text to your phone’s clipboard, allowing you to paste the test into a number of applications.

To try these new features download Google Goggles 1.5 from Android Market, or scan the QR code below with your phone.


Things That Cannot Change

[This post is by Dianne Hackborn, whose fingerprints can be found all over the Android Application Framework — Tim Bray]

Sometimes a developer will make a change to an application that has surprising results when installed as an update to a previous version — shortcuts break, widgets disappear, or it can’t even be installed at all. There are certain parts of an application that are immutable once you publish it, and you can avoid surprises by understanding them.

Your package name and certificate

The most obvious and visible of these is the “manifest package name,” the unique name you give to your application in its AndroidManifest.xml. The name uses a Java-language-style naming convention, with Internet domain ownership helping to avoid name collisions. For example, since Google owns the domain “google.com”, the manifest package names of all of our applications should start with “com.google.” It’s important for developers to follow this convention in order to avoid conflicts with other developers.

Once you publish your application under its manifest package name, this is the unique identity of the application forever more. Switching to a different name results in an entirely new application, one that can’t be installed as an update to the existing application.

Just as important as the manifest package name is the certificate that application is signed with. The signing certificate represents the author of the application. If you change the certificate an application is signed with, it is now a different application because it comes from a different author. This different application can’t be uploaded to Market as an update to the original application, nor can it be installed onto a device as an update.

The exact behavior the user sees when installing an application that has changed in one of these two ways is different:

  • If the manifest package name has changed, the new application will be installed alongside the old application, so they both co-exist on the user’s device at the same time.

  • If the signing certificate changes, trying to install the new application on to the device will fail until the old version is uninstalled.

If you change the signing certificate of your application, you should always change its manifest package name as well to avoid failures when it’s installed. In other words, the application coming from a different author makes it a different application, and its package name should be changed appropriately to reflect that. (Of course it’s fine to use the same package name for the development builds of your app signed with your test keys, because these are not published.)

Your AndroidManifest.xml is a public API

More than just your package name that is immutable. A major function of the AndroidManifest.xml is essentially to declare a public API from your application for use by other applications and the Android system. Every component you declare in the manifest that is not private (that is whose android:exported state is true) should be treated as a public API and never changed in a way that breaks compatibility.

A subtle but important aspect of what constitutes a break in compatibility is the android:name attribute of your activity, service, and receiver components. This can be surprising because we think of android:name as pointing to the private code implementing our application, but it is also (in combination with the manifest package name) the official unique public name for that component, as represented by the ComponentName class.

Changing the component name inside of an application can have negative consequences for your users. Some examples are:

  • If the name of a main activity of your application is changed, any shortcuts the user made to it will no longer work. A shortcut is an Intent that directly specifies the ComponentName it should run.

  • If the name of a service implementing a Live Wallpaper changes, then a user who has enabled your Live Wallpaper will have their wallpaper revert to the system default when getting the new version of your app. The same is true for Input Methods, Accessibility Services, Honeycomb’s new advanced Widgets, and so on.

  • If the name of a receiver implementing a Device Admin changes, then as with the live wallpaper example, the device admin will be disabled when the application is updated. This also applies to other kinds of receivers, such as App Widgets.

These behaviors are an outcome of how the Intent system is used on Android. There are two main kinds of Intents:

  • Implicit Intents only specify “what” they should match, using actions, categories, data, MIME types, and so on. The exact components that they will find are only determined at run-time, by the Package Manager matching it against the current applications.

  • Explicit Intents specify a single explicit “who” they should match, through a ComponentName. Regardless of whatever else is in the Intent, it is only associated with the exact manifest package name and class name as given in its ComponentName.

Both of these types of Intents are important to how Android interacts with your application. A typical example of this is how users browse and select live wallpapers.

To let the user pick a live wallpaper, the first thing Android must do is show them a list of the available live wallpaper services. It does this by building an implicit Intent with the appropriate action for a live wallpaper and asking the Package Manager for all services that support this Intent. The result is then the list of live wallpapers shown to the user.

When the user actually selects a specific live wallpaper they want to use, however, Android now must build an explicit Intent that identifies that particular live wallpaper. This is what is handed to the WallpaperManager to tell it which wallpaper to show.

This is why changing the name of the component in your manifest will cause the wallpaper to disappear: the explicit Intent that was previously saved is now invalid because the ComponentName it references no longer exists. There is no information available to indicate what the new name of the component is. (For example consider if your application had two different live wallpaper services the user could select.) Instead, Android must treat that live wallpaper as uninstalled and revert to its default wallpaper.

This is how input methods, device administrators, account managers, app widgets, and even application shortcuts work. The ComponentName is the public unique name of the components you declare in your manifest, and must not change if they are visible to other applications.

In conclusion: There are some parts of your application that can not change. Please be careful.

Three new updates to Google Sync for iPhone and iPad

(Cross-posted on the Google Enterprise Blog)

We don’t have to tell you that the workforce is increasingly mobile, and that workers on the go expect to be fully productive on email and calendar from their mobile devices. But we do want to tell you that we have a few new features for Google Sync users that will help employees work efficiently from anywhere on their iPhones and iPads.

Google Sync keeps your phone’s native mail and calendar apps in sync with your Gmail, Calendar and Contacts. Today, three new updates to Google Sync for iOS will allow you to:
  • Search all your emails in Gmail, not just the emails stored locally by the iOS mail app.



  • Accept, decline or edit calendar events from the iOS calendar app.

  • Send email from the address you want. We recognize that some of you manage multiple email addresses from a single Gmail account.Gmail’s “Send Mail as” feature lets you send messages with another email address listed as the sender instead of your Gmail address, e.g. joe@altostrat.com instead of joe@gmail.com. Now the iOS mail app will respect these settings.
These three updates are available to both Gmail and Google Apps email accounts.
For more information, visit Setting up Google Sync with your iOS device

Posted by Steve Hardt, Software Engineer

Introducing new features to mobile search

Our thirst for knowledge extends beyond the time we spend in front of our desktop computers. At Google, we are seeing mobile search grow at an exponential rate, increasing five-fold worldwide in just the past two years - a rate comparable to the early days of desktop Google Search. Today on mobile, we can get whatever information we’re looking for anytime, anywhere.

And I'm not just talking about looking up basic information like the weather or a stock quote, which is what people used to do in the early days of mobile search. As mobile devices have become more powerful and connected to faster networks, smartphone users are doing a surprisingly diverse set of search tasks -- from simple lookups, to tasks that involve multiple complex searches.

But it's not always easy to search from a mobile device, especially with the smaller screens and keyboards. We’ve worked relentlessly to make mobile search faster, easier, and more intuitive with features like autocomplete, Voice Search, Google Goggles, Google Instant and Instant Previews on mobile. Our work in mobile has now inspired desktop innovations like Voice Search and Search by Image, two new ways to search from your desktop, announced today at our Inside Search media event. We’re also excited to introduce two new mobile features designed to make mobile search even better.

With more searches happening when people are on the go, we’ve noticed an increase in searches for nearby places. To make it easier for people to search for what’s around them, we’ve introduced new shortcuts to commonly searched local categories, like restaurants, coffee shops and bars, in the form of icons on the mobile google homepage (www.google.com):



Shortcut icons appear at the bottom of the mobile homepage. Tap “More”, to select from additional popular categories like shopping, ATMs, gas stations, etc., a new part of our simplified Places homepage (www.google.com/m/places).


On the results page, you'll see a map with markers for your current location and places around you. When you scroll through the results, the map remains at the top of the page and adjusts automatically to the listing you are looking at. That way, you can see the listing information while still getting location context from the map. Tapping on a result will quickly show you more about a place including reviews and other useful details. Discovering great places nearby has never been easier on your mobile phone.




Another mobile improvement we’ve introduced today is an easier way to build longer, more complicated searches. You can now add suggested phrases to the search box and “build” your search piece by piece. This feature is already available on the Google Search app for Android and iOS devices and we’re now making this available on www.google.com from your mobile browser. Watch the video below to see how you can search faster with less typing.





These new mobile features are now available on www.google.com on Android (version 2.2+) and iOS (version 4.0+) in 40 languages worldwide.

If you would like to learn more about today’s announcements, visit the Inside Search website, our new one-stop shop for Google search tips, features and an under the hood look at our technology. Check the site later today and you’ll find a recording of the event, answers to common questions and links to other blogs posts today on the Official Google Blog, Inside Search blog and the Chrome blog.

We hope you enjoy these new search features and we look forward to bringing you further improvements by making mobile search even faster, easier, and more useful.

Know when your bus is late with live transit updates in Google Maps


(Cross-posted on the Official Google Blog)

Often when I’m taking public transit, I arrive at my stop on time only to anxiously check my watch and look down the street for my bus, which is running late once again. Those extra minutes I’m forced to wait seem like an eternity, and the only information I can access on my phone is when the bus was supposed to arrive.

Starting now, Google Maps for mobile and desktop can tell you when your ride is actually going to arrive with new live transit updates. We partnered with transit agencies to integrate live transit data in four U.S. cities and two European cities: Boston, Portland, Ore., San Diego, San Francisco, Madrid and Turin.



When you click on a transit station or plan a transit route with Google Maps and there are delays or alerts related to your trip, you’ll now see “live departure times” (indicated with a special icon) and service alerts.



Live transit departure times after tapping on a station



Live service alerts when receiving transit directions



Live departures and alerts on desktop


We’re working with our public transit partners to help them provide live data to more people in more cities. You can get live transit updates in the latest version of Google Maps for mobile (requires Android 1.6+), as well as Google Maps on all supported desktop and mobile browsers.

New Editing Features in Eclipse plug-in for Android

At the Google I/O conference a month ago, we demonstrated the next version of the Android Development Tools (ADT) plugin. Today we’re happy to announce that version 11 is done and available for download!

ADT 11 focuses on editor improvements. First, it offers several new visual refactoring operations, such as “Extract Include” and “Extract Style,” which help automatically extract duplicated layout fragments and style attributes into reusable layouts, styles, and themes.

Second, the visual layout editor now supports fragments, palette configurations, and improved support for custom views.

Last, XML editing has been improved with new quick fixes, code completion in more file types and many “go to declaration” enhancements.

ADT 11 packs a long list of new features and enhancements. Please visit our ADT page for more details. For an in-depth demo, check out the video of our Android Development Tools session at Google I/O, below.

Please note that the visual layout editor depends on a layout rendering library that ships with each version of the platform component in the SDK. We are currently working on a number of improvements to this library as well, which we plan to release soon for all platform versions. When we release the updates, some new features in ADT 11 will be “unlocked” - such as support for ListView previewing - so keep an eye on this blog for further announcements.