Learn how to use Google Maps Platform and the Places SDKs for Android to present your users with a list of Places to identify their current location.


What you'll learn

What you'll build

You'll build your Android app from scratch, but you can download the sample code for comparison when debugging. Download the sample code from github, or, if you have git set up for command line use, enter the following:

git clone https://github.com/googlecodelabs/current-place-picker-android.git

If you run into any issues (code bugs, grammatical errors, unclear wording, etc.) as you work through this codelab, please report the issue via the Report a mistake link in the lower left corner of the codelab.

Before you can start coding, you'll need to set up a few things.

Prepare the emulator

Android Studio is already installed on this kiosk. To run your app, it has an emulator set up running a Pixel 2 with API 28 (Android Pie).

In the next steps you'll configure your emulator to use location services.

  1. Click the Android Studio icon at the bottom of the desktop.
  2. From the Android Studio Welcome Screen, click Configure at the bottom and select AVD Manager. This brings you to the Android Virtual Device Manager.
  3. Click the Start button under the Actions column:

After a few moments, the emulator will open.

Update Google Play services in the emulator

  1. Once the emulator launches, look for the action bar of controls on the right side. At the bottom of this bar, click the More options (...) button.

  1. This opens the Extended controls dialog. Choose Google Play from the menu. If an update is available, click UPDATE.

  1. Use the credentials provided to you on this kiosk to sign in to the emulator. (You can find them by clicking on the Chrome extension with a logo).
    Since the emulator interprets a keypress as a pinch-and-zoom gesture, you can copy the credentials from the Chrome extension, click the text field of the emulator to pull up the keyboard, and then use this command in Terminal to paste in your text input:
adb shell input text "whatever you want to paste, in between quotes"
  1. When you are signed in, Google Play will be open to Google Play services. Click UPDATE to get the latest version of Google Play services.

  1. If asked to complete your account setup and add a payment option, choose SKIP.
  2. Refresh the Google Play tab on the emulator's extended menu. The version should now be higher than 15.0.1.

Set location in the emulator

  1. Once the emulator launches, click the search bar on the home screen and type "maps" to pull up the Google Maps app icon.

  1. Click the icon. You'll see a default map.
  2. At the bottom right of the map, click the My Location button.

You may be asked to give the phone permissions to use location.

  1. To the right of the emulator, click the ... button again to open the Extended Controls menu.
  2. Click the Location tab on the left side menu.
  3. On the right side, enter a Latitude and Longitude. Enter anything you like here, but make sure it's in an area with plenty of places.
    (Use Latitude 20.7818 and Longitude -156.4624 for the town of Kihei on Maui in Hawaii to replicate the results from this lab.)
  4. Once you're done click Send, and the map will update with this location.

The emulator will now be ready to run your app with location services.

  1. On the Welcome to Android Studio screen, select Start a new Android Studio project.
  2. On the Phone and Table tab, select Google Maps Activity.

  1. The Configure your project dialog opens. Here is where you name your app and create the package based on your domain.
    Here are the settings for an app called Current Place, which corresponds to the package com.google.codelab.currentplace.

  1. Choose Java as the language and select Use androidx.* artifacts.Keep the defaults for the rest of the settings, then click Finish.

To access location permissions in Android, you'll need Google Location and Activity Recognition API from Google Play Services. You can see the latest guidance for adding this and other Play Services APIs on the Set Up Google Play Services page.

Android Studio projects typically have 2 build.gradle files. One is for the overall project, and one is for the app. If you have the Android Studio Project explorer in ‘Android' view, you'll see both of them in the ‘Gradle Scripts' folder. You'll need to edit the Gradle Scripts > build.gradle (Module: app) file to add Google services.

  1. Add two lines to the dependencies section to add Google services for location and the Places API (sample code in context).

build.gradle (Module: app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.google.codelab.currentplace"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'com.google.android.gms:play-services-maps:16.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

    implementation 'com.google.android.gms:play-services-location:16.0.0'
    implementation 'com.google.android.libraries.places:places:1.1.0'

This section explains how to authenticate your app to the Maps JavaScript API and Places API using your own API key.

Go to the Google Cloud Platform Console.

This kiosk provides one project for your use for this codelab. Click the Project menu in the top bar and select that project.

Link Billing

This kiosk provides you with a billing account for this codelab. Select the billing account.

Get an API key

Follow these steps to enable the APIs used in this lab and get an API key:

  1. From the Navigation menu, select APIs & Services > Library.
  2. Click the Maps SDK for Android tile and click Enable.
  3. Repeat steps 1 and 2 to return to the menu and enable the Places API.
  4. From the Navigation menu, select APIs & Services > Credentials.
  5. Click Create Credentials and choose API key.
  6. You will see an API key that has been generated. Copy it.
  7. Back in Android Studio, find the file google_maps_api.xml under Android > app > res > values. Replace YOUR_KEY_HERE with the API key you copied in the last step.

Your app is now configured. In the next step you'll edit the layout file containing your UI.

  1. In your project explorer, open the activity_maps.xml file in the Android > app > res > layout folder.

  1. You'll see the basic UI open on the right of the screen, with tabs at the bottom allowing you to select the Design or Text editor for your layout. Select Text, and replace the entire contents of the layout file with this:


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"



            tools:context=".MapsActivity" />



This will give you a user interface that looks like this:

To give the user a button to click when they want to pick their current place, add an app bar with an icon that finds the user's current place and displays nearby likely places. It will look like this: (On a phone, only the icon is shown. On a tablet with more space, the text is also included)

Create the icon

In the project explorer, right-click the Android > app > res folder and select New > Image Asset. The Asset Studio will open.

  1. In the Icon Type menu choose Action Bar and Tab Icons.
  2. Name your asset ic_geolocate.
  3. Make sure the Asset Type selected is Clip Art. Click on the graphic next to the Clip Art. This opens the Select Icon window.
  4. Choose an icon.
    You can use the search bar to find icons related to your intent.
  5. Search for "location" and pick a location-related icon. The my location icon is the same as the one used in the Google Maps app when a user wants to snap the camera to their current location.
  6. Click OK> Next > Finish, and confirm there is a new folder called res > drawable that contains your new icon files.

Add string resources

  1. In the project explorer, expand the Android > app > res > values folder and open the strings.xml file.
  2. Add three new lines; The first will be used in your app bar when there is space to include a text label next to the icon. The others will be used for markers that you add to the map.


    <string name="app_name">Current Place</string>
    <string name="title_activity_maps">Map</string>
    <string name="action_geolocate">Pick Place</string>
    <string name="default_info_title">Default Location</string>
    <string name="default_info_snippet">No places found, because location permission is disabled.</string>

Add the app bar

  1. In the project explorer, right-click on the Android > app > res folder and select New > Directory to create a new subdirectory under app/src/main/res. Name the directory menu.
  2. Right-click on your new res > menu folder and select New > File. Name the file menu.xml.
  3. Paste in this code:


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"

    <!-- "Locate me", should appear as action button if possible -->
        app:showAsAction="always|withText" />


Update the app bar style

  1. In the project explorer, expand the Android > app > res > values folder and open the file styles.xml inside.
  2. In the <style> tag edit the parent property to be "Theme.AppCompat.NoActionBar". Note the "name" property as well; you will use this in the next step.


<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">

Update the app theme in AndroidManifest.xml

  1. Expand the Android > app > manifests folder and open the AndroidManifest.xml file.
  2. Find the android:theme line and edit or confirm the value to be @style/AppTheme.



You're now ready to begin coding!

In your project explorer find the MapsActivity.java file. It will be in the folder corresponding to the package that you created for your app in step 1.

Open it, and you'll be in the Java Code editor.

Import the Places SDK and other dependencies

Add these lines at the top of MapsActivity.java, replacing the existing import statements. They include the existing imports and add many more that will be used in the code in this lab.


import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.PlaceLikelihood;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
import com.google.android.libraries.places.api.net.PlacesClient;

import java.util.Arrays;
import java.util.List;

Update the class signature

The Places API uses AndroidX components for backwards-compatible support, so you need to define it to extend the AppCompatActivity. It will replace the FragmentActivity extension that is defined by default for a Maps Activity.

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {

Add class variables

Next, declare the various class variables that will be used in different class methods. These include the UI elements, and status codes. These should be just below the variable declaration for GoogleMap mMap.

    // New variables for Current Place Picker
    private static final String TAG = "MapsActivity";
    ListView lstPlaces;
    private PlacesClient mPlacesClient;
    private FusedLocationProviderClient mFusedLocationProviderClient;

    // The geographical location where the device is currently located. That is, the last-known
    // location retrieved by the Fused Location Provider.
    private Location mLastKnownLocation;

    // A default location (Sydney, Australia) and default zoom to use when location permission is
    // not granted.
    private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
    private static final int DEFAULT_ZOOM = 15;
    private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
    private boolean mLocationPermissionGranted;

    // Used for selecting the current place.
    private static final int M_MAX_ENTRIES = 5;
    private String[] mLikelyPlaceNames;
    private String[] mLikelyPlaceAddresses;
    private String[] mLikelyPlaceAttributions;
    private LatLng[] mLikelyPlaceLatLngs;

Update the onCreate method

You'll need to update the onCreate method to handle runtime user permissions for location services, setting up the UI elements, and creating the Places API client.

Add the lines of code regarding the action toolbar, views setup, and Places client to the end of the existing onCreate() method.

MapsActivity.java onCreate()

    protected void onCreate(Bundle savedInstanceState) {
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()

        // Set up the action toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        // Set up the views
        lstPlaces = (ListView) findViewById(R.id.listPlaces);

        // Initialize the Places client
        String apiKey = getString(R.string.google_maps_key);
        Places.initialize(getApplicationContext(), apiKey);
        mPlacesClient = Places.createClient(this);
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);

Add code for your app bar menu

These two methods add the app bar menu (with a single item, the Pick Place icon) and handle the user click on the icon.

Copy these two methods into your file, after the onCreate method.

MapsActivity.java onCreateOptionsMenu() and onOptionsItemSelected()

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);

        return super.onCreateOptionsMenu(menu);

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
           case R.id.action_geolocate:
                // Present the current place picker
                // pickCurrentPlace();
                return true;

                // If we got here, the user's action was not recognized.
                // Invoke the superclass to handle it.
                return super.onOptionsItemSelected(item);


Test it out

From Android Studio, press the ‘Run' button or Run menu > Run ‘app' to start the app running.

You'll be asked to select your deployment target. The running emulator should appear on this list. Select it, and Android Studio will deploy the app to the emulator for you.

After a few moments, the app will launch. You'll see the map centered on Sydney, Australia with the single button and unpopulated places list.

The focus of the map will not move to the user's location unless we request permission to access the device's location. The next step teaches you how to request and handle location permissions.

Request location permissions after the map is ready

  1. Define a method called getLocationPermission that will request user permissions. Paste this code below the onOptionsSelected method you just created.

MapsActivity.java getLocationPermission()

    private void getLocationPermission() {
         * Request location permission, so that we can get the location of the
         * device. The result of the permission request is handled by a callback,
         * onRequestPermissionsResult.
        mLocationPermissionGranted = false;
        if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
                == PackageManager.PERMISSION_GRANTED) {
            mLocationPermissionGranted = true;
        } else {
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
  1. Add two lines to the end of the existing onMapReady method to enable zoom controls and request location permissions from the user.

MapsActivity.java onMapReady()

    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));


        // Enable the zoom controls for the map

        // Prompt the user for permission.


Handle the result from requested permissions.

When the user responds to the request permission dialog, this callback will be called by Android.

Paste this code below the getLocationPermission() method:

MapsActivity.java onRequestPermissionsResult()

     * Handles the result of the request for location permissions.
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        mLocationPermissionGranted = false;
        switch (requestCode) {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    mLocationPermissionGranted = true;

When the user taps on the Pick Place icon in the app bar, the app will call the method pickCurrentPlace() which calls the getDeviceLocation() method you defined earlier. The getDeviceLocation method calls another method, getCurrentPlaceLikelihoods, after retrieving the latest device location.

Call the findCurrentPlace API and handle the response

getCurrentPlaceLikelihoods constructs a findCurrentPlaceRequest and calls the Places API's findCurrentPlace task. If the task is successful, it returns a findCurrentPlaceResponse, which contains a list of placeLikelihood objects. Each of these have a number of properties, including the name and address of the place, and the likelihood probability that you are in that place (a double value from 0 to 1). This method handles the response by constructing lists of place details from the placeLikelihoods.

This code will iterate through the five most likely places, and add ones with a likelihood > 0 to a list which it will then render. If you would like to display more or less than five, edit the M_MAX_ENTRIES constant.

Paste this code below the onMapReady method.

MapsActivity.java getCurrentPlaceLikelihoods()

   private void getCurrentPlaceLikelihoods() {
        // Use fields to define the data types to return.
        List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS,

        // Get the likely places - that is, the businesses and other points of interest that
        // are the best match for the device's current location.
        @SuppressWarnings("MissingPermission") final FindCurrentPlaceRequest request =
        Task<FindCurrentPlaceResponse> placeResponse = mPlacesClient.findCurrentPlace(request);
                new OnCompleteListener<FindCurrentPlaceResponse>() {
                    public void onComplete(@NonNull Task<FindCurrentPlaceResponse> task) {
                        if (task.isSuccessful()) {
                            FindCurrentPlaceResponse response = task.getResult();
                            // Set the count, handling cases where less than 5 entries are returned.
                            int count;
                            if (response.getPlaceLikelihoods().size() < M_MAX_ENTRIES) {
                                count = response.getPlaceLikelihoods().size();
                            } else {
                                count = M_MAX_ENTRIES;

                            int i = 0;
                            mLikelyPlaceNames = new String[count];
                            mLikelyPlaceAddresses = new String[count];
                            mLikelyPlaceAttributions = new String[count];
                            mLikelyPlaceLatLngs = new LatLng[count];

                            for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
                                Place currPlace = placeLikelihood.getPlace();
                                mLikelyPlaceNames[i] = currPlace.getName();
                                mLikelyPlaceAddresses[i] = currPlace.getAddress();
                                mLikelyPlaceAttributions[i] = (currPlace.getAttributions() == null) ?
                                        null : TextUtils.join(" ", currPlace.getAttributions());
                                mLikelyPlaceLatLngs[i] = currPlace.getLatLng();

                                String currLatLng = (mLikelyPlaceLatLngs[i] == null) ?
                                        "" : mLikelyPlaceLatLngs[i].toString();

                                Log.i(TAG, String.format("Place " + currPlace.getName()
                                        + " has likelihood: " + placeLikelihood.getLikelihood()
                                        + " at " + currLatLng));

                                if (i > (count - 1)) {

                            // COMMENTED OUT UNTIL WE DEFINE THE METHOD
                            // Populate the ListView
                            // fillPlacesList();
                        } else {
                            Exception exception = task.getException();
                            if (exception instanceof ApiException) {
                                ApiException apiException = (ApiException) exception;
                                Log.e(TAG, "Place not found: " + apiException.getStatusCode());

Move the map camera to the device's current location

If the user grants permission, the app fetches the user's latest location and moves the camera to center around that location.

If the user denies permission, the app simply moves the camera to the default location defined among the constants at the beginning of this page (in the sample code, it is Sydney, Australia).

Paste this code below the getPlaceLikelihoods() method:

MapsActivity.java getDeviceLocation()

    private void getDeviceLocation() {
         * Get the best and most recent location of the device, which may be null in rare
         * cases when a location is not available.
        try {
            if (mLocationPermissionGranted) {
                Task<Location> locationResult = mFusedLocationProviderClient.getLastLocation();
                locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
                    public void onComplete(@NonNull Task<Location> task) {
                        if (task.isSuccessful()) {
                            // Set the map's camera position to the current location of the device.
                            mLastKnownLocation = task.getResult();
                            Log.d(TAG, "Latitude: " + mLastKnownLocation.getLatitude());
                            Log.d(TAG, "Longitude: " + mLastKnownLocation.getLongitude());
                                    new LatLng(mLastKnownLocation.getLatitude(),
                                            mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
                        } else {
                            Log.d(TAG, "Current location is null. Using defaults.");
                            Log.e(TAG, "Exception: %s", task.getException());
                                    .newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));

        } catch (SecurityException e)  {
            Log.e("Exception: %s", e.getMessage());

Check for location permissions when the user clicks the Pick Place button

When the user taps the Pick Place button you created, this method checks for location permissions and re-prompts the user for permission if it hasn't been granted.

If the user has granted permission, then the method calls getDeviceLocation to initiate the process of getting the current likely places.

  1. Add this method below getDeviceLocation():

MapsActivity.java pickCurrentPlace()

   private void pickCurrentPlace() {
        if (mMap == null) {

        if (mLocationPermissionGranted) {
        } else {
            // The user has not granted permission.
            Log.i(TAG, "The user did not grant location permission.");

            // Add a default marker, because the user hasn't selected a place.
            mMap.addMarker(new MarkerOptions()

            // Prompt the user for permission.
  1. Now that pickCurrentPlace is defined, find the line in onOptionsItemSelected() that calls pickCurrentPlace and un-comment it.

MapsActivity.java onOptionItemSelected()

           case R.id.action_geolocate:

                // Present the current place picker
                return true;

Test it out

If you run the app now and tap the Pick Place button that you created, it should prompt for location permissions.

Set up a handler for picked places

Let's think about what we want to happen when the user clicks an item in the ListView. To confirm the user's choice of which place they are currently, we can add a marker to the map at that place. If the user clicks that marker, an InfoWindow will pop up displaying the place name and address.

Paste this click handler below the pickCurrentPlace method.

MapsActivity.java listClickedHandler

    private AdapterView.OnItemClickListener listClickedHandler = new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView parent, View v, int position, long id) {
            // position will give us the index of which place was selected in the array
            LatLng markerLatLng = mLikelyPlaceLatLngs[position];
            String markerSnippet = mLikelyPlaceAddresses[position];
            if (mLikelyPlaceAttributions[position] != null) {
                markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[position];

            // Add a marker for the selected place, with an info window
            // showing information about that place.
            mMap.addMarker(new MarkerOptions()

           // Position the map's camera at the location of the marker.

Populate the ListView

Now that we have our list of most likely places that the user is currently visiting, we can present those options to the user in the ListView. We can also set the ListView's click listener to use the click handler we just defined above.

Paste this method below the click handler:

MapsActivity.java fillPlacesList()

    private void fillPlacesList() {
        // Set up an ArrayAdapter to convert likely places into TextViews to populate the ListView
        ArrayAdapter<String> placesAdapter =
                new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mLikelyPlaceNames);

Now that fillPlacesList is defined, find the line toward the end of findPlaceLikelihoods that calls fillPlacesList and un-comment it.

MapsActivity.java fillPlaceLikelihoods()

                // Populate the ListView

That is all the code needed for the place picker!

Test picking a place

Run the app again. This time when you press the Pick Place button, the app will now populate the list with named places close to the location. Close to this location on Maui are places like Ululani's Hawaiian Shave Ice and Sugar Beach Bake Shop. Because the several places are very close to the location coordinates, this is a list of likely places you may be in.

When you click on a place name in the ListView, you should see a marker added to the map. If you tap the marker, you can see place details.

Test a different location

If you want to change your location and are using the emulator, the device location will not automatically update when you update the location coordinates in the emulator's extended menu. To get around this, follow the steps below to use the native Google Maps app to force updates to the emulator's location:

  1. Open Google Maps.
  2. Click ... > Location to change the Latitude and Longitude to new coordinates, then click Send.
    For example, you can use Latitude: 49.2768 and Longitude: -123.1142 to set the location to downtown Vancouver, Canada.
  3. Verify that Google Maps has re-centered on your new coordinates. You may need to press the My Location button in the Google Maps app to request the re-centering.
  4. Return to your Current Place app and click the Pick Place button to get the map on the new coordinates and see a new list of likely current places.

And that's it! You've now built a simple app that checks for the places at the current location, and gives you a likelihood of which ones you're at. Enjoy!

You've now built a simple app that checks for the most likely places at the current location and adds a marker to the map for the place the user selects.

What we've covered

Learn more

What other codelabs would you like to see?

The Kotlin version of this Current Place Picker codelab The iOS version of this Current Place Picker codelab A codelab demonstrating Place Autocomplete in a mobile app

Is the codelab you want not listed above? Request it with a new issue here.