8.1: Using the Places API
Contents:
- Introduction
- What you should already KNOW
- What you will LEARN
- What you will DO
- App overview
- Task 1. Sign up and obtain API keys
- Task 2. Get details on the current place
- Task 3. Add the place-picker UI
- Coding challenge
- Solution code
- Summary
- Related concept
- Learn more
The Location APIs can provide timely and accurate location information, but these APIs only return a set of geographic coordinates. In 7.1 Using the device location, you learned how to make geographic coordinates more useful by reverse geocoding them into physical addresses.
But what if you want to know more about a location, like the type of place it is? In this practical, you use the Google Places API for Android to obtain details about the device's current location. You also learn about the place picker and the place-autocomplete APIs. The place picker and autocomplete let users search for places rather than having your app detect the device's current place.
What you should already KNOW
You should be familiar with:
- Creating, building, and running apps in Android Studio.
- The activity lifecycle.
- Including external libraries in your
build.gradlefile. - Creating responsive layouts with
ConstraintLayout.
What you will LEARN
You will learn how to:
- Get details about the user's current place.
- Launch the place-picker UI so the user can select a place.
- Include a place-autocomplete fragment to allow the user to search for places.
What you will DO
- Get an API key from the Google API Console and register the key to your app.
- Get the name of the place where the device is located.
- If the place is a school, gym, restaurant, or library, change an image in the UI to reflect the place type.
- Add a button to allow the user to select a place.
- Add a search bar that autocompletes a user's search for a place.
App overview
The app for this practical extends the WalkMyAndroid app from the previous practical in two ways:
Get details about the current location of the device, including the place type and place name. Display the name in the label
TextViewand change the Android robot image to reflect the place type.
Add a Pick a Place button that launches the place-picker UI, allowing the user to select a place.

Task 1. Sign up and obtain API keys
In this task you set up the starter app, WalkMyAndroidPlaces-Starter, with an API key. Every app that uses the Google Places API for Android must have an API key. The key is linked to the app by the app's package name and by a digital certificate that's unique to the app.
To set up an API key in your app, you need to do the following:
- Get information about your app's digital certificate.
- Get an API key. To do this, you register a project in the Google API Console and add the Google Places API for Android as a service for the project.
- Add the key to your app by adding a
meta-dataelement to yourAndroidManifest.xmlfile.
1.1 Get your app's certificate information
The API key is based on a short form of your app's digital certificate, known as the certificate's SHA-1 fingerprint . This fingerprint uniquely identifies the app, and identifies you as the app's owner, for the lifetime of the app.
You might have two certificates:
- A debug certificate , which is the certificate you use for this practical. The Android SDK tools generate a debug certificate when you do a debug build. Don't attempt to publish an app that's signed with a debug certificate. The debug certificate is described in more detail in Sign your debug build.
- A release certificate , which you don't need for this practical. The Android SDK tools generate a release certificate when you do a release build. You can also generate a release certificate using the
keytoolutility. Use the release certificate when you're ready to release your app to the world. For information about release certificates, see Signup and API Keys.
For this practical, make sure that you use the debug certificate.
To view the debug certificate's fingerprint:
Locate your debug
keystorefile, which is nameddebug.keystore. By default, the file is stored in the same directory as your Android Virtual Device (AVD) files:- macOS and Linux:
~/.android/ - Windows Vista and Windows 7:
C:\Users\your_user_name.android\
The file is created the first time you build your project.
- macOS and Linux:
List the SHA-1 fingerprint:
- For Linux or macOS, open a terminal window and enter the following:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android - For Windows Vista and Windows 7, run:
You should see output similar to the following:keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore"\ -alias androiddebugkey -storepass android -keypass android
The line that begins withAlias name: androiddebugkey Creation date: Jan 01, 2013 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Android Debug, O=Android, C=US Issuer: CN=Android Debug, O=Android, C=US Serial number: 4aa9b300 Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033 Certificate fingerprints: MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9 SHA1: BB:0D:AC:44:D3:21:E1:41:07:71:9C:62:90:AF:A4:66:6E:44:5D:95 Signature algorithm name: SHA1withRSA Version: 3SHA1contains the certificate's SHA-1 fingerprint. The fingerprint is the sequence of 20 two-digit hexadecimal numbers separated by colons.
- For Linux or macOS, open a terminal window and enter the following:
Copy this value to your clipboard. You need it in the next set of steps.
- Download the starter code for this practical, WalkMyAndroidPlaces-Starter.
- Open Android Studio and open your
AndroidManifest.xmlfile. Note thepackagestring in themanifesttag. You need the package name in future steps.
keystore file and key, don't enter the storepass or keypass arguments on the command line unless you're confident of your computer's security. For example, on a public computer, someone could look at your terminal window history or list of running processes, get the password, and have write-access to your signing certificate. That person could modify your app or replace your app with their own.
1.2 Get an API key from the Google API Console
- Go to the Google API Console.
- Create or select a project. You can reuse the same project and API key for multiple apps.
- From the Dashboard page, click ENABLED APIS AND SERVICES. The API Library opens.
- Search for "Places" and select Google Places API for Android.
- Click ENABLE.
- If a warning appears telling you to create credentials, click Create credentials. Otherwise, open the Credentials page and click Create credentials.
- If you see a Find out what kind of credentials you need step, skip the prompts. Click directly on the API key link.
- Name the key whatever you like.
Restrict the key to Android apps:
- Follow the prompts to restrict the key to Android apps.
- Click Add package name and fingerprint.
Add your app's SHA-1 fingerprint to the key. (You copied this fingerprint to your clipboard in 1.1 Get your app's certificate information.) Also enter the package name from Android Studio.
For example:
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75 com.example.android.walkmyandroidplacesSave your changes.
On the Credentials page, your new Android-restricted API key appears in the list of API keys for your project. An API key is a string of characters, something like this:
AIzaSyBdVl-cTCSwYZrZ95SuvNw0dbMuDt1KG0- Copy the API key to your clipboard. You'll paste the key into your app manifest in the next step.
1.3 Add the key to the manifest
Add your API key to your AndroidManifest.xml file as shown in the following code. Replace YOUR_API_KEY with your own API key:
<application>
...
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY"/>
...
Task 2. Get details on the current place
Now that you have your API key set up, you're ready to start using the Places API. In this task, you use the PlaceDetectionClient.getCurrentPlace() method to obtain the place name and place type for the device's current location. You use these place details to enhance the WalkMyAndroidPlaces UI.

2.1 Add the Places API to your project
To use the Places API, you need to add it to the app-level build.gradle file. You also need to connect to the API using the GoogleApiClient class.
- Add the following statement to your app-level
build.gradlefile. ReplaceXX.X.Xwith the appropriate support library version. For the latest version number, see Add Google Play Services to Your Project.compile 'com.google.android.gms:play-services-places:XX.X.X' - In the
MainActivity, in theonCreate()method, initialize aPlaceDetectionClientobject. You use this object to get information about the device's current location.mPlaceDetectionClient = Places.getPlaceDetectionClient(this, null);Note: To use thePlaceDetectionClientinterface, your app needs theACCESS_FINE_LOCATIONpermission. You don't need to add this permission, because the WalkMyAndroidPlaces-Starter code includes it.
2.2 Get the place name
In this step, you extend the WalkMyAndroidPlaces app to show the place name associated with the current device location.
- In the
MainActivity, create aStringmember variable calledmLastPlaceName. This member variable will hold the name of the device's most probable location. - In
strings.xml, modify theaddress_textstring to include the place name as an additional variable:<string name="address_text">"Name: %1$s \n Address: %2$s \n Timestamp: %3$tr"</string> - In the
onClick()method for the Start Tracking Location button, add another argument to thesetText()call. Pass in theloadingstring so that theTextViewlabel shows "Loading..." for theNameandAddresslines:
When themLocationTextView.setText(getString(R.string.address_text, getString(R.string.loading),// Name getString(R.string.loading),// Address new Date())); // TimestampAsyncTaskreturns anAddress, theonTaskCompleted()method is called. In theonTaskComplete()method, obtain the current place name and update theTextView. To get the current place name, callPlaceDetectionClient.getCurrentPlace().
The getCurrentPlace() method returns a Task object. A Task object represents an asynchronous operation and contains a parameterized type that's returned when the operation completes in its onComplete() callback. In this case, the parameterized type is a PlaceLikelihoodBufferResponse.
The returned PlaceLikelihoodBufferResponse instance is a list of Place objects, each with a "likelihood" value between 0 and 1. The likelihood value indicates the likelihood that the device is at that place. The strategy shown below is to use a loop to determine the place that has the highest likelihood, then display that place name.
- In the
onTaskCompleted()method, callgetCurrentPlace()on yourPlaceDetectionClientApiinstance. Store the result in a local variable. Because you are interested in all places, you can pass innullfor thePlaceFilter:Task<PlaceLikelihoodBufferResponse> placeResult = mPlaceDetectionClient.getCurrentPlace(null); - The
getCurrentPlace()method call is underlined in Android Studio, because the method may throw aSecurityExceptionif you don't have the right location permissions. Have theonTaskCompleted()method throw aSecurityExceptionto remove the warning. - Add an
OnCompleteListenerto theplaceResult:placeResult.addOnCompleteListener (new OnCompleteListener<PlaceLikelihoodBufferResponse>() { @Override public void onComplete(@NonNull Task<PlaceLikelihoodBufferResponse> task) { }); - Create an if/else statement to check whether the
Taskwas successful:if (task.isSuccessful()) { } else { { - If the
Taskwas successful, callgetResult()on the task to obtain thePlaceLikelihoodBufferResponse. Initialize an integer to hold the maximum value. Initialize aPlaceto hold the highest likelihoodPlaceobject.if (task.isSuccessful()) { PlaceLikelihoodBufferResponse likelyPlaces = task.getResult(); float maxLikelihood = 0; Place currentPlace = null; } - Iterate over each
PlaceLikelihoodobject and check whether it has the highest likelihood so far. If it does, update themaxLikelihoodandcurrentPlaceobjects:if (task.isSuccessful()) { PlaceLikelihoodBufferResponse likelyPlaces = task.getResult(); float maxLikelihood = 0; Place currentPlace = null; for (PlaceLikelihood placeLikelihood : likelyPlaces) { if (maxLikelihood < placeLikelihood.getLikelihood()) { maxLikelihood = placeLikelihood.getLikelihood(); currentPlace = placeLikelihood.getPlace(); } } } - If the
currentPlaceis notnull, update theTextViewwith the result. The following code should all be within theif (task.isSuccessful())loop:if (currentPlace != null) { mLocationTextView.setText( getString(R.string.address_text, currentPlace.getName(), result //This is the address from the AsyncTask, System.currentTimeMillis())); } - After you use the place information, release the buffer:
likelyPlaces.release(); - In the
elseblock for the case where theTaskis not successful, show an error message instead of a place name:else { mLocationTextView.setText( getString(R.string.address_text, "No Place name found!", result, System.currentTimeMillis())); } - Run the app. You see the place name along with the address in the label
TextView.
2.3 Get the place type
The Place object you obtained from the PlaceLikelihood object contains a lot more than just the name of the place. The object can also include the place type, rating, price level, website URL, and more. (For a list of all the fields, see the Place reference.)
In this step, you change the image of the Android robot to reflect the place type of the current location. The starter code includes a bitmap image for a "plain" Android robot, plus images for four other Android robots, one for each these place types: school, gym, restaurant, and library.
If you want to add support for other place types, use the Androidify tool to create a custom Android robot image and include the image in your app.
In
MainActivity, create asetAndroidType()method that uses aPlaceobject. Have the method assign the appropriate drawable to theImageView, based on the place type:private void setAndroidType(Place currentPlace) { int drawableID = -1; for (Integer placeType : currentPlace.getPlaceTypes()) { switch (placeType) { case Place.TYPE_SCHOOL: drawableID = R.drawable.android_school; break; case Place.TYPE_GYM: drawableID = R.drawable.android_gym; break; case Place.TYPE_RESTAURANT: drawableID = R.drawable.android_restaurant; break; case Place.TYPE_LIBRARY: drawableID = R.drawable.android_library; break; } } if (drawableID < 0) { drawableID = R.drawable.android_plain; } mAndroidImageView.setImageResource(drawableID); }Note: ThesetAndroidType()method is where you can add support for more place types. All you need to do is add anothercaseto theswitchstatement and select the appropriate drawable. For a list of supported place types, see Place Types.In the
onComplete()callback where you obtain the currentPlaceobject, callsetAndroidType(). Pass in thecurrentPlaceobject.- Run your app. Unless you happen to be in one of the supported place types, you don't see any difference in the Android robot image. To get around this, run the app on an emulator and follow the steps below to set up fake locations.
How to test location-based features on an emulator
Testing location-based features on an emulator can be challenging. The FusedLocationProviderClient and the Places API have to use a location that you provide through the emulator settings.
To simulate a location, use a GPX file, which provides a set of GPS coordinates over time:
- Download the WalkMyAndroidPlaces-gpx file. The file contains five locations. The first location doesn't correspond to any of the supported place types. The other four locations have the place types that the WalkMyAndroidPlaces app supports: school, gym, restaurant, library.
- Start an emulator of your choice.
- To navigate to your emulator settings, select the three dots at the bottom of the menu next to the emulator, then select the Location tab.
In the bottom right corner, click Load GPX/KML. Select the file you downloaded.
Five locations load in the GPS data playback window.
Notice the Delay column. By default, the emulator changes the location every 2 seconds. Change the delay to 10 seconds for each item except the first item, which should load immediately and have a delay of 0.
(A delay of 10 seconds makes sense because your location updates happen approximately every 10 seconds. Recall the
LocationRequestobject, in which the interval is set to 10,000 milliseconds, or 10 seconds.)Run the WalkMyAndroid app on the emulator to start tracking the device location.
- Use the play button in the bottom left corner of the emulator Location tab to deliver the GPX file's location information to your app. The location
TextViewand the Android robot image should update every 10 seconds to reflect the new locations as they are "played" by the GPX file!
The screenshot below shows the Location tab (1) for emulator location settings, the GPS data playback button (2), and the Load GPX/KML button (3).

Task 3. Add the place-picker UI
At this point, the WalkMyAndroidPlaces app only looks for places in the device's current location, but there are many use cases where you want the user to select a location from a map. For example, if you create an app to help users decide on a restaurant, you want to show restaurants in the area that the user selects, not just restaurants in the user's current location.
Having the user select a location from a map seems complicated: you need a map with places of interest already on it, and you need a way for the user to search for a place and select a place. Fortunately, the Place API includes the place picker, a UI that greatly simplifies the work.
In this task, you add a button that launches the place-picker UI. The place-picker UI lets the user select a place, and it displays the place information in the UI, as before. (It displays the relevant Android robot image, if available, and it displays the place name, address, and update time.)
|
|
3.1 Add a PlacePicker button
The place-picker UI is a dialog where the user can search for a place and select a place. To add the place picker to your app, use the PlacePicker.IntentBuilder intent to launch a special Activity. Get the result in your activity's onActivityResult() method:
- Add a button next to the Start Tracking Location button. Use "Pick a Place" as the button's text in both the portrait and the landscape layout files.
Add a click handler that executes the following code to start the
PlacePicker. Create an arbitrary constant calledREQUEST_PICK_PLACEthat you'll use later to obtain the result. (This constant should be different from your permission-check integer.)private static final int REQUEST_PICK_PLACE = 2; PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder(); try { startActivityForResult(builder.build(MainActivity.this), REQUEST_PICK_PLACE); } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) { e.printStackTrace(); }- Run your app. When you click Pick a Place, a
PlacePickerdialog opens. In the dialog, you can search for and select any place.
The next step is to get whatever place the user selects in onActivityResult(), then update the TextView and Android robot image.
3.2 Obtain the selected place
The result from the PlacePicker is sent automatically to the activity's onActivityResult() override method. Use the passed-in requestCode integer to get the result. The result should match the integer you passed into the startActivityForResult() method.
- To override the
onActivityResult()method, select Code > Override Methods in Android Studio. Find and select theonActivityResult()method, then click OK. In
onActivityResult(), create anifstatement that checks whether therequestCodematches your request integer.To get the
Placeobject that was selected from thePlacePicker, use thePlacePicker.getPlace()method.If the
resultCodeisRESULT_OK, get the selected place from the dataIntentusing thePlacePicker.getPlace()method. Pass in the application context and the dataIntent, which the system passes intoonActivityResult().If the
resultCodeisn'tRESULT_OK, show a message that says that a place was not selected.if (resultCode == RESULT_OK) { Place place = PlacePicker.getPlace(this, data); } else { mLocationTextView.setText(R.string.no_place); }- After you get the
Placeobject, callsetAndroidType(). Pass in your obtained object. - Update the label
TextViewwith the place name and address from thePlaceobject. Set the update time to be the current time:mLocationTextView.setText( getString(R.string.address_text, place.getName(), place.getAddress(), System.currentTimeMillis())); - Run the app. You can now use the
PlacePickerto choose any place in the world, provided that the place exists in the Places API. To test your app's functionality, search for one of the place types for which you have an Android robot image.
PlacePicker, this data is not persisted using the SavedInstanceState. For this reason, when you rotate the device, the app resets to the initial state.
Coding challenge
Challenge: Add a place autocomplete search dialog UI element to your Activity. The place autocomplete dialog lets the user search for a place without launching the PlacePicker.
Solution code
Summary
- To use the Google Places API for Android, you must create an API key that's restricted to Android apps. You do this in the Google API Console. In your project in the API Console, you also need to enable the Google Places API for Android.
- Include the API key in a metadata tag in your
AndroidManifest.xmlfile. - The
Placeobject contains information about a specific geographic location, including the place name, address, coordinates, and more. - Use the
PlaceDetectionClient.getCurrentPlace()method to get information about the device's current location. PlaceDetectionClient.getCurrentPlace()returns aPlaceLikelihoodBufferin aTask.- The
PlaceLikelihoodBuffercontains a list ofPlaceLikelihoodobjects that represent likely places. For each place, the result includes the likelihood that the place is the right one. - The Places API includes the
PlacePicker, which you use to include the place-picker UI in your app. The place-picker UI is a dialog that lets the user search for places and select places. - Launch the
PlacePickerusingstartActivityForResult(). Pass in anIntentcreated withPlacePicker.IntentBuilder(). - Retrieve the selected place in
onActivityResult()by callingPlacePicker.getPlace(). Pass in the activity context and the dataIntent.
Related concept
The related concept documentation is in 8.1: Places API.
Learn more
Android developer documentation: