package com.sanchez.fmf.adapter; 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 android.content.Context; import android.util.Log; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget.Filterable; import java.util.ArrayList; import java.util.Iterator; import java.util.concurrent.TimeUnit; public class PlaceAutocompleteAdapter extends ArrayAdapter<PlaceAutocompleteAdapter.PlaceAutocomplete> implements Filterable { private static final String TAG = PlaceAutocompleteAdapter.class.getSimpleName(); private ArrayList<PlaceAutocomplete> mResultList; private GoogleApiClient mGoogleApiClient; private LatLngBounds mBounds; private AutocompleteFilter mPlaceFilter; public PlaceAutocompleteAdapter(Context context, int resource, GoogleApiClient googleApiClient, LatLngBounds bounds, AutocompleteFilter filter) { super(context, resource); mGoogleApiClient = googleApiClient; mBounds = bounds; mPlaceFilter = filter; } @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(); // Skip the autocomplete query if no constraints are given. if (constraint != null) { // Query the autocomplete API for the (constraint) search string. mResultList = getAutocomplete(constraint); if (mResultList != null) { // The API successfully returned results. 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> getAutocomplete(CharSequence constraint) { if (mGoogleApiClient.isConnected()) { Log.i(TAG, "Starting autocomplete query for: " + constraint); // Submit the query to the autocomplete API and retrieve a PendingResult that will // contain the results when the query completes. PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, constraint.toString(), mBounds, mPlaceFilter); // 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()) { Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString()); autocompletePredictions.release(); return null; } // PendingResult<PlacePhotoMetadataResult> pendingMetadata = // Places.GeoDataApi.getPlacePhotos(mGoogleApiClient, placeId); // PlacePhotoMetadataResult metadata = pendingMetadata.await(60, TimeUnit.SECONDS); // // PendingResult<PlacePhotoResult> pendingPhoto = // metadata.getPhotoMetadata().get(0).getPhoto(mGoogleApiClient); // PlacePhotoResult p = pendingPhoto.await(60, TimeUnit.SECONDS); // Bitmap photo = p.getBitmap(); Log.i(TAG, "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<AutocompletePrediction> iterator = autocompletePredictions.iterator(); ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount()); while (iterator.hasNext()) { AutocompletePrediction prediction = iterator.next(); // Only include U.S. cities // States only have 1 comma (e.g. AK, United States). Don't include states. if(prediction.getDescription().contains("United States") && prediction.getDescription().replaceAll("[^,]", "").length() > 1 ) { resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getDescription())); } } // Release the buffer now that all data has been copied. autocompletePredictions.release(); return resultList; } Log.e(TAG, "Google API client is not connected for autocomplete query."); return null; } public 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(); } } }