Autocomplete places sdk example tutorial

Android AutoComplete Places SDK Example

Google’s AutoComplete service is provided by Places SDK. AutoComplete api is used to auto populate places in response to the user search input. AutoComplete api suggests addresses, location, businesses as the user types and search.

Auto Complete can be added by adding auto complete widget or programatically to create your own user experience.

Places API Key

This tutorial is based on the new Places SDK as Google Play Services version of the Places SDK for Android is deprecated and will be shut off soon.

In order to create location based application we need to first get API key to call Places SDK apis. Register your app with Google Maps Platform and select Places to get your key.

When you create your API key it can be used unrestricted which means any app or website that has access to the key can use it to call Places API. This may result in malicious intent and can incur cost to you. So its always advisable to restrict the key to be used only from your app. Let’s see how to restrict API key usage.

Open API credentials and select the API key. In the next page select Android apps in Application restrictions as shown in the images below.

Google API Credentials

Google Maps API key restriction For Android App AutoComplete Places

SHA-1 Certificate

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.codeexa.com.placesexample"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    signingConfigs {

        release {
            storeFile file("mystore.keystore")
            storePassword "codeexa"
            keyAlias "key0"
            keyPassword "codeexa"
        }
    }

    buildTypes {
        debug {
            minifyEnabled false
            signingConfig signingConfigs.release
        }
        release {
            minifyEnabled true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }
    }

}

Create your signing key mystore.keystore. To get SHA-1 certificate fingerprint you need to run this command in the terminal to get the details.

keytool -list -v -keystore app/mystore.keystore

There is another simple way to get the config details directly in Android Studio. Open Gradle and click on signingReport to get fingerprint data.

Generate SHA Signing Report in Android Studio

 

Gradle Dependency

After getting the API key we are ready to move on to the Android application. Add Places SDK gradle dependency in app’s build.gradle

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

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

Sync project to apply Places gradle changes.

Android Places SDK

Android AutoComplete Places SDK Example For Location

Initialize Places SDK with the API key as shown in the code below.

Places.initialize(getApplicationContext(), GOOGLE_PLACES_API_KEY);

Replace GOOGLE_PLACES_API_KEY with your API key. Now we are ready to call Places APIs.

AutoComplete Activity

The code below shows how to open AutoComplete intent and let user search locations based on the input text.

Create activity layout file activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnPlaces"
        style="@style/Widget.AppCompat.Button.Colored"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Search Place"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Search Result"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline" />
    </LinearLayout>

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="Location Name: "
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Place ID"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView3" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/linearLayout" />

    <TextView
        android:id="@+id/textView7"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/textView6" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="LatLon"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView4" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/textView7" />

</android.support.constraint.ConstraintLayout>

Add Internet permission in AndroidManifest.xml file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.codeexa.com.placesexample">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Update activity code and call AutoComplete intent after initializing Places SDK.

package com.codeexa.com.placesexample;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.common.api.Status;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.net.PlacesClient;
import com.google.android.libraries.places.widget.Autocomplete;
import com.google.android.libraries.places.widget.AutocompleteActivity;
import com.google.android.libraries.places.widget.AutocompleteSupportFragment;
import com.google.android.libraries.places.widget.listener.PlaceSelectionListener;
import com.google.android.libraries.places.widget.model.AutocompleteActivityMode;

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

public class MainActivity extends AppCompatActivity {

    private static final String GOOGLE_PLACES_API_KEY = "__REPLACE_WITH_YOUR_KEY__";
    private static final int AUTOCOMPLETE_REQUEST_CODE = 123;
    private TextView tvLocationName, tvPlaceId, tvLatLon;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Places.initialize(getApplicationContext(), GOOGLE_PLACES_API_KEY);

        tvLocationName = findViewById(R.id.textView6);
        tvPlaceId = findViewById(R.id.textView7);
        tvLatLon = findViewById(R.id.textView5);

        Button btnPlaces = findViewById(R.id.btnPlaces);
        btnPlaces.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createAutoCompleteIntent();

            }
        });

    }

    private void createAutoCompleteIntent() {
        tvLocationName.setText("");
        tvPlaceId.setText("");
        tvLatLon.setText("");
        List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG);
        Intent intent = new Autocomplete.IntentBuilder(
                AutocompleteActivityMode.FULLSCREEN, fields)
                .build(MainActivity.this);
        startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                Place place = Autocomplete.getPlaceFromIntent(data);
                Log.i("tag", "Place: " + place.getName() + ", " + place.getLatLng());
                tvLocationName.setText(place.getName());
                tvPlaceId.setText(place.getId());
                tvLatLon.setText(String.valueOf(place.getLatLng()));

            } else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
                // TODO: Handle the error.
                Status status = Autocomplete.getStatusFromIntent(data);
                Log.i("tag", status.getStatusMessage());
            } else if (resultCode == RESULT_CANCELED) {
                // The user canceled the operation.
            }
        }
    }


}

Place Details

Places SDK can be requested to provide extra information about the place. When Place request is constructed you can provide what type of data to be returned. As in the example above we have added LatLon and Name in the fields to be returned.

List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG);

In addition to these fields we can request following fields:

  • Place.Field.ADDRESS
  • Place.Field.ID
  • Place.Field.LAT_LNG
  • Place.Field.NAME
  • Place.Field.OPENING_HOURS
  • Place.Field.PHONE_NUMBER
  • Place.Field.PHOTO_METADATAS
  • Place.Field.PLUS_CODE
  • Place.Field.PRICE_LEVEL
  • Place.Field.RATING
  • Place.Field.TYPES
  • Place.Field.USER_RATINGS_TOTAL
  • Place.Field.VIEWPORT
  • Place.Field.WEBSITE_URI

If you have any query or suggestion do comment below. Happy coding!

Leave a Reply