When a requirement in your application, you want implement Autocomplete Google Places API. A new API was released name as Google Places API . This API gives full access to Google's database for places, for this you have to include Google Play Services in your app.
Screen Shots:
Download Source Code
1. Build Gradle:
Add the "play-services-places" dependency in your app build.gradle file dependencies and sync library.
2. XML Layout:
open activity_main.xml file, modify the below changes.
3. Generate Places API key For Android
1. Create a project in Google Developers Console see the below image.
2. Open API Manager for this click on Menu Icon at top left. and click on Google Places API for
Android. And click on Enable button to enable API. look at below images.
3. Then go to the Credentials section and click on Create Credentials.
4. For getting SHA1 fingerprint open CMD prompt change the directory to the JDK bin directory,
my JDK bin path "C:\Program Files\Java\jdk1.8.0_102\bin". (Could be different for you)
Windows:
5. Next we have to run the keytool.exe for getting SHA1 fingerprint.Use the below command for getting SHA1 fingerprint.
Windows:
6. Enter your SHA1 fingerprint with you package name for restrict Android Application and click save button, see below images.
7. Paste the API key in a meta tag under the application tag in your AndroidManifest.xml as shown below.
4. Android Manifest
Open Android Manifest file add the permissions and meta tag under application tag.
5. MainActivity Class
Open Main Activity java class and modify the below changes in your java class.
6. PlaceArrayAdapter
Create PlaceArrayAdapter java class and copy the below code.
Screen Shots:
Download Source Code
1. Build Gradle:
Add the "play-services-places" dependency in your app build.gradle file dependencies and sync library.
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.prasad.autocompleteplaceapi" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.1.0' compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4' testCompile 'junit:junit:4.12' compile 'com.google.android.gms:play-services-places:10.2.1' }
2. XML Layout:
open activity_main.xml file, modify the below changes.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" tools:context=".MainActivity"> <AutoCompleteTextView android:id="@+id/autoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:drawableRight="@drawable/location" android:hint="Enter Place Here" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_below="@+id/autoCompleteTextView" android:src="@drawable/powered_by_google_light" /> <TextView android:id="@+id/select" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/autoCompleteTextView" android:layout_marginTop="20dp" android:text="Selected Place:" android:textStyle="bold" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/select" android:layout_marginTop="20dp" /> </RelativeLayout>
3. Generate Places API key For Android
1. Create a project in Google Developers Console see the below image.
2. Open API Manager for this click on Menu Icon at top left. and click on Google Places API for
Android. And click on Enable button to enable API. look at below images.
3. Then go to the Credentials section and click on Create Credentials.
4. For getting SHA1 fingerprint open CMD prompt change the directory to the JDK bin directory,
my JDK bin path "C:\Program Files\Java\jdk1.8.0_102\bin". (Could be different for you)
Windows:
cd C:\Program Files\Java\jdk1.7.0_05\bin
5. Next we have to run the keytool.exe for getting SHA1 fingerprint.Use the below command for getting SHA1 fingerprint.
Windows:
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
6. Enter your SHA1 fingerprint with you package name for restrict Android Application and click save button, see below images.
7. Paste the API key in a meta tag under the application tag in your AndroidManifest.xml as shown below.
<meta-data android:name="com.google.android.geo.API_KEY" android:value="{YOUR_API_KEY}"/>
4. Android Manifest
Open Android Manifest file add the permissions and meta tag under application tag.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.prasad.autocompleteplaceapi"> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <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"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <meta-data android:name="com.google.android.geo.API_KEY" android:value="AIzaSyBqLsXyr7sniC1ATs-E7-AI15U4v_qpkug" /> </application> </manifest>
5. MainActivity Class
Open Main Activity java class and modify the below changes in your java class.
package com.prasad.autocompleteplaceapi; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.text.Html; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AutoCompleteTextView; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.location.places.Place; import com.google.android.gms.location.places.PlaceBuffer; import com.google.android.gms.location.places.Places; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks { private static final String TAG = "MainActivity"; private static final int GOOGLE_API_CLIENT_ID = 0; private AutoCompleteTextView mAutocompleteTextView; private TextView mNameView; private GoogleApiClient mGoogleApiClient; private PlaceArrayAdapter mPlaceArrayAdapter; private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds( new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090)); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutocompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView); mAutocompleteTextView.setThreshold(3); mNameView = (TextView) findViewById(R.id.name); mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this) .addApi(Places.GEO_DATA_API) .enableAutoManage(this, GOOGLE_API_CLIENT_ID, this) .addConnectionCallbacks(this) .build(); mAutocompleteTextView.setOnItemClickListener(mAutocompleteClickListener); mPlaceArrayAdapter = new PlaceArrayAdapter(this, android.R.layout.simple_list_item_1, BOUNDS_MOUNTAIN_VIEW, null); mAutocompleteTextView.setAdapter(mPlaceArrayAdapter); } private AdapterView.OnItemClickListener mAutocompleteClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final PlaceArrayAdapter.PlaceAutocomplete item = mPlaceArrayAdapter.getItem(position); final String placeId = String.valueOf(item.placeId); Log.i(TAG, "Selected: " + item.description); PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi .getPlaceById(mGoogleApiClient, placeId); placeResult.setResultCallback(mUpdatePlaceDetailsCallback); Log.i(TAG, "Fetching details for ID: " + item.placeId); } }; private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback = new ResultCallback<PlaceBuffer>() { @Override public void onResult(PlaceBuffer places) { if (!places.getStatus().isSuccess()) { Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString()); return; } // Selecting the first object buffer. final Place place = places.get(0); CharSequence attributions = places.getAttributions(); mNameView.setText(Html.fromHtml(place.getAddress() + "")); } }; @Override public void onConnected(@Nullable Bundle bundle) { mPlaceArrayAdapter.setGoogleApiClient(mGoogleApiClient); Log.i(TAG, "Google Places API connected."); } @Override public void onConnectionSuspended(int i) { mPlaceArrayAdapter.setGoogleApiClient(null); Log.e(TAG, "Google Places API connection suspended."); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { Log.e(TAG, "Google Places API connection failed with error code: " + connectionResult.getErrorCode()); Toast.makeText(this, "Google Places API connection failed with error code:" + connectionResult.getErrorCode(), Toast.LENGTH_LONG).show(); } }
6. PlaceArrayAdapter
Create PlaceArrayAdapter java class and copy the below code.
package com.prasad.autocompleteplaceapi; import android.content.Context; import android.util.Log; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget.Filterable; import android.widget.Toast; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.Status; import com.google.android.gms.location.places.AutocompleteFilter; import com.google.android.gms.location.places.AutocompletePrediction; import com.google.android.gms.location.places.AutocompletePredictionBuffer; import com.google.android.gms.location.places.Places; import com.google.android.gms.maps.model.LatLngBounds; import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.TimeUnit; public class PlaceArrayAdapter extends ArrayAdapter<PlaceArrayAdapter.PlaceAutocomplete> implements Filterable { private static final String TAG = "PlaceArrayAdapter"; private GoogleApiClient mGoogleApiClient; private AutocompleteFilter mPlaceFilter; private LatLngBounds mBounds; private ArrayList<PlaceAutocomplete> mResultList; public PlaceArrayAdapter(Context context, int resource, LatLngBounds bounds, AutocompleteFilter filter) { super(context, resource); mBounds = bounds; mPlaceFilter = filter; } public void setGoogleApiClient(GoogleApiClient googleApiClient) { if (googleApiClient == null || !googleApiClient.isConnected()) { mGoogleApiClient = null; } else { mGoogleApiClient = googleApiClient; } } @Override public int getCount() { return mResultList.size(); } @Override public PlaceAutocomplete getItem(int position) { return mResultList.get(position); } @Override public Filter getFilter() { Filter filter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); if (constraint != null) { mResultList = getPredictions(constraint); if (mResultList != null) { results.values = mResultList; results.count = mResultList.size(); } } return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { if (results != null && results.count > 0) { // The API returned at least one result, update the data. notifyDataSetChanged(); } else { // The API did not return any results, invalidate the data set. notifyDataSetInvalidated(); } } }; return filter; } private ArrayList<PlaceAutocomplete> getPredictions(CharSequence constraint) { if (mGoogleApiClient != null) { Log.i(TAG, "Executing autocomplete query for: " + constraint); PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi .getAutocompletePredictions(mGoogleApiClient, constraint.toString(), mBounds, mPlaceFilter); // Wait for predictions, set the timeout. AutocompletePredictionBuffer autocompletePredictions = results .await(60, TimeUnit.SECONDS); final Status status = autocompletePredictions.getStatus(); if (!status.isSuccess()) { Toast.makeText(getContext(), "Error: " + status.toString(), Toast.LENGTH_SHORT).show(); Log.e(TAG, "Error getting place predictions: " + status .toString()); autocompletePredictions.release(); return null; } Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount() + " predictions."); Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator(); ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount()); while (iterator.hasNext()) { AutocompletePrediction prediction = iterator.next(); resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getFullText(null))); } // Buffer release autocompletePredictions.release(); return resultList; } Log.e(TAG, "Google API client is not connected."); return null; } class PlaceAutocomplete { public CharSequence placeId; public CharSequence description; PlaceAutocomplete(CharSequence placeId, CharSequence description) { this.placeId = placeId; this.description = description; } @Override public String toString() { return description.toString(); } } }