I need to show list of places in dropdown using google placeAutocomplete widgets. Here I\'m getting dialog to show places according to my query but
In view of the latest changes in the AutocompletePrediction API, here is the revised Adapter and Filter code:
PlaceAutoCompleteAdapter.java
package com.equinox.prologix.Adapters;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.Toast;
import com.equinox.prologix.Activities.LocationChooseActivity;
import com.equinox.prologix.Filters.PlaceAutoCompleteFilter;
import com.equinox.prologix.R;
import com.equinox.prologix.ViewHolders.PlaceAutoCompleteHolder;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.places.AutocompletePrediction;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBufferResponse;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.ui.PlaceAutocomplete;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import java.util.List;
/**
* Created by Mohammed Mukhtar on 12/1/2017.
*/
public class PlaceAutoCompleteAdapter extends RecyclerView.Adapter implements Filterable {
private Context context;
private GoogleMap googleMap;
private PlaceAutoCompleteFilter placeAutoCompleteFilter;
private GeoDataClient mGeoDataClient;
private GoogleApiClient googleApiClient;
private Handler autoCompleteSelected;
private List resultPlaceList;
public PlaceAutoCompleteAdapter(Context context, GoogleApiClient googleApiClient, List resultPlaceList, Handler autoCompleteSelected) {
this.context = context;
this.resultPlaceList = resultPlaceList;
this.googleApiClient = googleApiClient;
this.autoCompleteSelected = autoCompleteSelected;
mGeoDataClient = Places.getGeoDataClient(context, null);
}
@Override
public PlaceAutoCompleteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).inflate(R.layout.list_item_google_place_autocomplete, parent, false);
return new PlaceAutoCompleteHolder(itemView);
}
@Override
public void onBindViewHolder(final PlaceAutoCompleteHolder holder, final int position) {
final AutocompletePrediction autocompletePrediction = resultPlaceList.get(position);
holder.getLocationAddressView().setText(autocompletePrediction.getPrimaryText(null));
holder.getLocationLocalityView().setText(autocompletePrediction.getSecondaryText(null));
holder.getItemView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mGeoDataClient.getPlaceById(autocompletePrediction.getPlaceId()).addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
if (task.isSuccessful()) {
PlaceBufferResponse places = task.getResult();
Place myPlace = places.get(0);
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(myPlace.getLatLng(), 17));
autoCompleteSelected.sendMessage(Message.obtain());
Log.i("getPlaceById", "Place found: " + myPlace.getName());
places.release();
} else Log.e("getPlaceById", "Place not found.");
}
});
Toast.makeText(context, resultPlaceList.get(holder.getAdapterPosition()).getFullText(null), Toast.LENGTH_LONG).show();
}
});
}
@Override
public int getItemCount() {
return resultPlaceList.size();
}
@Override
public Filter getFilter() {
if (placeAutoCompleteFilter == null)
placeAutoCompleteFilter = new PlaceAutoCompleteFilter(googleApiClient, this, resultPlaceList);
return placeAutoCompleteFilter;
}
public void setGoogleMap(GoogleMap googleMap) {
this.googleMap = googleMap;
}
}
PlaceAutoCompleteFilter.java
package com.equinox.prologix.Filters;
import android.text.style.CharacterStyle;
import android.util.Log;
import android.widget.Filter;
import com.equinox.prologix.Adapters.PlaceAutoCompleteAdapter;
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.Place;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.ui.PlaceAutocomplete;
import com.google.android.gms.maps.model.LatLngBounds;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.equinox.prologixappcommon.Models.DataHolderCommon.currentCountry;
import static com.equinox.prologixappcommon.Models.DataHolderCommon.currentLocation;
import static com.equinox.prologixappcommon.Utils.BackendTransform.transform;
import static com.equinox.prologixappcommon.Utils.BackendTransform.transform2;
import static com.google.android.gms.location.places.AutocompleteFilter.TYPE_FILTER_NONE;
/**
* Created by Mohammed Mukhtar on 12/1/2017.
*/
public class PlaceAutoCompleteFilter extends Filter {
private GoogleApiClient mGoogleApiClient;
private PlaceAutoCompleteAdapter placeAutoCompleteAdapter;
private List resultPlaceList;
public PlaceAutoCompleteFilter(GoogleApiClient mGoogleApiClient,
PlaceAutoCompleteAdapter placeAutoCompleteAdapter,
List resultPlaceList) {
this.mGoogleApiClient = mGoogleApiClient;
this.placeAutoCompleteAdapter = placeAutoCompleteAdapter;
this.resultPlaceList = resultPlaceList;
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// Skip the autocomplete query if no constraints are given.
if (constraint != null) {
// Query the autocomplete API for the (constraint) search string.
List tempResult = getAutoComplete(constraint);
if (tempResult != null) {
results.values = tempResult;
results.count = tempResult.size();
}
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
resultPlaceList.clear();
resultPlaceList.addAll((List) results.values);
placeAutoCompleteAdapter.notifyDataSetChanged();
}
else {
// The API did not return any results, invalidate the data set.
}
}
private ArrayList getAutoComplete(CharSequence constraint) {
if (mGoogleApiClient.isConnected()) {
Log.i("", "Starting autocomplete query for: " + constraint);
AutocompleteFilter autocompleteFilter = new AutocompleteFilter.Builder()
//.setCountry(currentCountry.getCountryCode())
.setTypeFilter(TYPE_FILTER_NONE)
.build();
// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
PendingResult results =
Places.GeoDataApi
.getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
new LatLngBounds.Builder().include(transform(currentLocation)).build(),
autocompleteFilter);
// This method should have been called off the main UI thread. Block and wait for at most 60s
// for a result from the API.
AutocompletePredictionBuffer autocompletePredictions = results.await(60, TimeUnit.SECONDS);
// Confirm that the query completed successfully, otherwise return null
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
// Toast.makeText(mContext, "Error contacting API: " + status.toString(),
// Toast.LENGTH_SHORT).show();
Log.e("", "Error getting autocomplete prediction API call: " + status.toString());
autocompletePredictions.release();
return null;
}
Log.i("", "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");
// Copy the results into our own data structure, because we can't hold onto the buffer.
// AutocompletePrediction objects encapsulate the API response (place ID and description).
Iterator iterator = autocompletePredictions.iterator();
ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
resultList.add(prediction.freeze());
}
// Release the buffer now that all data has been copied.
autocompletePredictions.release();
return resultList;
}
Log.e("", "Google API client is not connected for autocomplete query.");
return null;
}
}