ZOFTINO.COM android and web dev tutorials

Google Places SDK for Android Tutorial

Using Google places SDK for Android, current places, place details, nearby places and photos associated with a place can be displayed in apps and place search capability can be developed. The API uses current device location to fetch places.

New version of places SDK for Android is available now. The old version of the API which was part of Google Play Services is deprecated. In addition to extra features, the new places-SDK for android supports all the features which were supported by old version except Place Picker feature which is deprecated.

In this tutorial, we’ll go over all the features of places API with examples.

google places sdk for android examples

You can see examples of old version or Google play services version of places API, here.

Changes in New Places Library

Place picker is not supported and deprecated. With new library, you can request for only the required fields to be sent in the response for each place.

New methods are created for all place requests.

Enable Google Places API

To enable Google places API, first log on to Google Cloud Platform Console and then create or open Google cloud project.

google cloud platform open project places api for android

Then click API link in the left navigation to go to Google APIs list page. Then click places API.

google cloud platform apis places api for android

Then click enable button to enable the places api for the selected project.

google cloud platform enable places api for android

Create Google API Key

On the Google cloud console, click APIs in the left navigation, on the next page, now you will see places API in the enabled APIs list. Then click places API. On the next page, click credentials tab, then click create credentials dropdown button and then click API Key option.

create google api key

That action will create API key and it will be listed on credentials tab page.

Restricting Google API Key

To apply restrictions to the api key, you need to edit the key. To go to edit key screen, you need to click edit button for the key which is listed in credentials tab.

There are application and API restriction options. To restrict the usage of the key to an android app, you need to select Android Apps radio button and enter package and SHA1 certificate finger print into the corresponding text fields.

google api key restriction android apps enter package and sha1 fingerprint

For debug certificate SHA1 fingerprint, use below command.

keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android

Copy the SHA1 fingerprint and paste in the fingerprint field on the key restriction page of google cloud console and save the changes.

Make API Key Available in Android Project

The API key created on the Google cloud console needs to be added to android project as it needs to be passed in the API calls. To make the API Key available in your android project, add it to strings xml file. Before you place the key in strings.xml, make sure that the key is restricted to your project by following the steps listed in the previous section.

Libraries

Add following places library to module’s build.gradle file.

implementation 'com.google.android.libraries.places:places:1.0.0'

Permissions

The places API requires ACCESS_FINE_LOCATION and ACCESS_WIFI_STATE permissions which are already defined in manifest of the library. But app should check whether the permissions are granted or not and if not granted user should be prompted for permissions.

Initializing Places API

The main class which is used for getting place info is PlacesClient. An instance of PlacesClient can be obtained using Places class by calling createClient method on it. Before instantiating PlacesClient, places API needs to be initialized by calling initialize method on Places class passing context and Google API key to it.

if (!Places.isInitialized()) {
    String gApiKey = ctx.getString(R.string.api_key);
    Places.initialize(ctx, gApiKey);
}
placesClient = Places.createClient(ctx);

Using PlacesClient object, current place, place details, photos and place search API calls can be made.

Current Place

To get current place based on the device location, you can call findCurrentPlace() method on PlacesClient object by passing FindCurrentPlaceRequest object to it. The call returns 20 nearby places with each place having likelihood value which tells accuracy of the places with respect to the device’s current location.

You can create FindCurrentPlaceRequest object by calling newInstance() method on FindCurrentPlaceRequest and passing the required fields which you want in the response for each place. The newInstance() method takes a list of Place.Field items such as Place.Field.NAME, Place.Field.LAT_LNG, etc. To know all the place field names, see Place.Field documentation.

        List<Place.Field> fields = new ArrayList<>();
        fields.add(Place.Field.NAME);
        FindCurrentPlaceRequest currentPlaceRequest =
                FindCurrentPlaceRequest.newInstance(fields);

        currentPlaceTask =
                placesClient.findCurrentPlace(currentPlaceRequest);

You can add success and failure listeners to the task which is returned by findCurrentPlace method call and process the response.

myPlacesAPI.getCurrentPlacesNames().addOnSuccessListener(
        (response) -> {
            int size = response.getPlaceLikelihoods().size();
            String pname = response.getPlaceLikelihoods().get(0).getPlace().getName();
            textView.setText(pname);
        })
       .addOnFailureListener(
        (exception) -> {
            exception.printStackTrace();
            textView.setText("");
        });

Get Place By Place Id

Google place is identified by a place id. Places APIs will return place ids in the response. If you have a place id and want to get additional information about the place, you can get using fetchPlace API call. To get place by place id, first you need to create FetchPlaceRequest object. You can create it by passing place id and list of place fields you want in the response to FetchPlaceRequest.builder and calling build method on the builder. Then call fetchPlace() method on PlaceClient object passing FetchPlaceRequest object.

By adding listeners to the task returned by fetchPlace, you can capture and process FetchPlaceResponse.

        FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();

        placesClient.fetchPlace(placeRequest)
                .addOnSuccessListener(
                        (response)->{
				Place place = response.getPlace();
                        })
                .addOnFailureListener(
                        (exception)->{
                            exception.printStackTrace();
                        });

Place Photo

To get place photos, first you need to get photo metadata by calling findCurrentPlace or fetchPlace API and passing Place.Field.PHOTO_METADATAS in those requests. Each place contains list of photos, so you will get list of PhotoMetadata objects for each place.

After getting PhotoMetadata objects, pick one object, create FetchPhotoRequest object and pass it to fetchPhoto() API call to get photo.

        FetchPhotoRequest photoRequest = FetchPhotoRequest.builder(photoMetadata)
                .build();
        placesClient.fetchPhoto(photoRequest)
                .getPlacePhoto(photoMetadata).addOnSuccessListener(
                (response) -> {
                    Bitmap bitmap = response.getBitmap();
                    imageView.setImageBitmap(bitmap);
                })
                .addOnFailureListener(
                        (exception) -> {
                            exception.printStackTrace(); });

Search Places

To build search places feature in your app, you can use Google places API which allows you to get list of places for a given search string. It allows you to restrict results to a particular area by letting you to specify latitude and longitude bounds. You can use search components provided as part of the places library or build your own search components from scratch.

To get search result for the given search string, you need to call findAutocompletePredictions API. To call findAutocompletePredictions API, first you need to create FindAutocompletePredictionsRequest object with the request data. You can add user entered search string to the request object by calling setQuery method on it.

You can set type filter, to get the results of specified place type only, by calling setTypeFilter method on the request object and passing one of the TypeFilter to it, for example TypeFilter.REGION.

To restrict results to a rectangular area, you need to create RectangularBounds by passing latitude and longitude values of the area that you want the results from and add the RectangularBounds object to the request object by calling either setLocationBias or setLocationRestriction.

You can add country code to the request to get search results from that country only.

        AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();
        RectangularBounds bounds = RectangularBounds.newInstance(first, sec);
        FindAutocompletePredictionsRequest request = 
			FindAutocompletePredictionsRequest.builder()
                .setLocationBias(bounds)
                .setCountry(country)
                .setTypeFilter(TypeFilter.REGIONS)
                .setSessionToken(token)
                .setQuery(searchStr)
                .build();

        placesClient.findAutocompletePredictions(request)
                .addOnSuccessListener(
                (response) -> {
                    Log.i("", "number of results in search places response"
                            +response.getAutocompletePredictions().size());
                    StringBuilder sb = new StringBuilder();
                    for (AutocompletePrediction prediction :
                            response.getAutocompletePredictions()) {
                        sb.append(prediction.getPrimaryText(null).toString());
                        sb.append("\n");
                    }
                    searchResults.setText(sb.toString());
                })
                .addOnFailureListener((exception) -> {
                    exception.printStackTrace();
                });