Google Play Services: Using the Places API

In March of 2015, Google released the Places API for Android as a part of Google's Play Services. This API allows developers to access a wealth of information from Google to provide users with an experience tailored to their current location by using the names and information of places, rather than a set of coordinates.

In this tutorial, you will learn how to present your users with the Place Picker component, use the Places API to guess the user's current place, search for a place by its ID, and allow the user to type into a text field to present them with predictive results.

1. Getting Set Up

If you don't already have an Android public API key, you will need to create a public Google API key for Android applications. You can do this by visiting the Google's Developers Console. Instructions for creating a key based on your signing certificate and package name are available in Google's documentation and are beyond the scope of this article.

When you've created a key, search for the Places API and set it to enabled. Some calls to the Places API are limited in how many requests can be sent per 24 hour period. At the time of writing, an account without a billing profile can send up to 1,000 requests while an account with a billing profile can send 150,000 requests. If you require more, you can submit a request to have this limit increased as described in the Usage Limits documentation.

With the API key ready to use, it is time to start working on the demo project. Create a project in Android Studio and set the minimum supported SDK version to at least 9. This is the minimum requirement for using Google's Play Services.

Once Android Studio has created the Hello World template project, open the build.gradle file and, under the dependencies node, add the required dependency of Play Services 7.0. This is the latest at the time of writing, but you can verify the latest version by checking Google's documentation.

Next, open AndroidManifest.xml, add the required permissions for the project, and state that OpenGL version 2 is required by the application.

The last thing you will need to do in the manifest is adding two <meta-data> tags to set the gms version and API key for the app within the <application> tag.

When you're done with the manifest, you are ready to start writing code. As this is a component from Play Services, you will need to initialize your GoogleApiClient and connect/disconnect it during your Activity's life cycle. We do this in the onCreateonStart, and onStop methods of the Activity class.

2. Using the Place Picker Widget

The Place Picker widget is a user interface component provided by Play Services that allows the user to see a map of their surrounding area. The component includes a list of nearby places that can be used by your app. By using this component, you are able to follow a standard design that your users will know how to interact with while being able to save on development time.

Place Picker Widget

To use the Place Picker, you need to create an intent and listen for the Activity result to retrieve the Place selected by the user. The following method shows how you would launch this Activity.

The PlacePicker.IntentBuilder is used to create the Intent that will be used to launch the Place Picker. It also has an method available, setLatLngBounds, that lets you place a geographic boundary from a southwest corner to a northeast corner to control the search area.

The Intent can be built using the build method from PlacePicker.IntentBuilder and launched using the startActivityForResult method from your Activity. It should be noted that using the build method does have the possibility of throwing a GooglePlayServicesRepairableException or a GooglePlayServicesNotAvailableException exception, so those should be checked for using a standard try/catch block and handled gracefully if they occur.

If the user selects a location from the place picker list, that Place object is packaged into an Intent and sent back to the calling Activity. Using the PlacePicker.getPlace method, you can extract the Place data from the returned Intent.

Once the Place object is extracted, it can be treated as a model object to display or use within your app.

The Places API In Action

3. Finding the User's Current Place

Another interesting feature of the Places API is that you can use it to guess if the user is currently at a listed place. The API will also provide a likelihood so that you can make informed decisions about how your app should interact with the user. It should be noted that this is one of the features of the API that requires a request against your allotted usages.

To detect the user's place, you will need to use the Places.PlacesDetectionApi.getCurrentPlace method to create a PendingIntent that returns with a PlaceLikelihoodBuffer object. Using a ResultCallBack, you can take the first, and most likely, place from the buffer and use that in your app.

If your app needs more information, you can extract other PlaceLikelihood items from the buffer by looping through it. The likelihood that this place is where the user is currently located is passed back in each PlaceLikelihood object as a floating point value from 0.0 to 1.0, 1.0 being almost a guaranteed match. Don't forget to call release on the PlaceLikelihoodBuffer to avoid any memory leaks.

Asking the Places API for the Likelihood of the Current Place

4. Predicting Places

The next, and most complex, topic we will go over in this tutorial is predicting and displaying places to the user as they enter a search query. Again, this API call also counts towards the API's usage limits. However, it is invaluable for making your app more useable.

Predicting Places

For this portion of the tutorial, you will use an AutoCompleteTextView and a custom adapter in the app to type the name of a place for predictions. Almost all of the work is done in the adapter. However, we will need to pass a reference to the GoogleApiClient to the adapter for it to access the API.

This can be done in the standard GoogleApiClient callback, onConnected, and we can remove the instance of the client in onStop where mAdapter is an instance of our custom  Adapter class, AutoCompleteAdapter.

To trigger an API call whenever the user types a new letter into the AutoCompleteTextView, you need to override the getFilter method of the ArrayAdapter. This method is triggered whenever the user changes the content of the view associated with the adapter. It allows you to change the content of the adapter of the AutoCompleteTextView. In the following example, constraints is the content of the view.

The displayPredictiveResults method is where the actual interaction with the API occurs. There are a few different objects that can be made to customize your predictions.

The first is a LatLngBounds object that creates a square boundary from a southwest point to a northeast point to localize the query. If null is passed instead of an initialized LatLngBounds object, then no geographic restrictions will be placed on the query.

The second object that you can create to customize the query is a filter for the API request. The filter for the Places AutoCompletePredictions call is a list of Integer objects representing different types of filters. At this point, only one filter type can be applied to a query. The acceptable values can be found in the documentation. If the Integer list is empty or null is passed, then all result types are returned.

Once you are ready to make the request, you can use the Places.GeoDataApi.getAutocompletePredictions method to return a PendingIntent, which can be associated with a ResultCallback to display the returned information.

It's important to note that a custom object representing the AutoCompletePrediction objects from the buffer is used to store the data in the ArrayAdapter. Otherwise an IllegalArgumentsException exception would be thrown as soon as the buffer is released, which is crucial to avoid a memory leak.

The content in AutoCompleteAdapter is displayed using a android.R.layout.simple_list_item_1 layout and standard ViewHolder pattern in getView.

When an item is clicked from this list, the ID of the selected Place is passed to the onItemClickedListener and searched for to display.

5. Searching for a Place by ID

The final part of this tutorial covers finding a Place object based on its ID. This works similarly to the other API calls by creating a PendingIntent and interacting with a returned buffer to retrieve the place. Like the other buffer objects you have worked with, the  PlaceBuffer must call release to avoid any memory leaks.

Conclusion

The Places API is a powerful tool for making your apps aware of the user's location to provide them with contextual information. In this tutorial, you have learned how to use the Place Picker component, guess the user's place, present them with predictive results when searching, and find a place based on a given ID. In addition to the topics covered here, it is also possible to submit new places to Google to help expand the information the API has access to.

Tags:

Comments

Related Articles