Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search locations inside a particular city in Google Places Apis

I am using Google Places Apis to filter results inside a particular city.I am able to filter results.but it also shows results out side of that city. For example if I set LatLngBounds of DELHI city and searching for a location in city NEWYORK. It also gives me result of NEWYORK city(but NEWYORK's LatLng is not lies inside DELHI).

How can I restrict my results to a particular city?

This is my PlaceAutoCompleteAdapter class

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.common.data.DataBufferUtils;
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.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class PlaceAutocompleteAdapter
        extends ArrayAdapter<AutocompletePrediction> implements Filterable {


    private ArrayList<AutocompletePrediction> mResultList;
    private GoogleApiClient mGoogleApiClient;
    private LatLngBounds mBounds;
    private AutocompleteFilter mPlaceFilter;

    public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient,
            LatLngBounds bounds, AutocompleteFilter filter) {
        super(context,R.layout.simple_expandble_text_view_item, R.id.text1);
        mGoogleApiClient = googleApiClient;
        mBounds = bounds;
        mPlaceFilter = filter;
    }

    public void setBounds(LatLngBounds bounds) {
        mBounds = bounds;
    }

    @Override
    public int getCount() {
        return mResultList.size();
    }

    @Override
    public AutocompletePrediction getItem(int position) {
        return mResultList.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = super.getView(position, convertView, parent);
        AutocompletePrediction item = getItem(position);

        TextView textView1 = (TextView) row.findViewById(R.id.text1);
        textView1.setText(item.getDescription());
        return row;
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                if (constraint != null) {
                    mResultList = getAutocomplete(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) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }

            @Override
            public CharSequence convertResultToString(Object resultValue) {
                if (resultValue instanceof AutocompletePrediction) {
                    return ((AutocompletePrediction) resultValue).getDescription();
                } else {
                    return super.convertResultToString(resultValue);
                }
            }
        };
    }

    private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {
        if (mGoogleApiClient.isConnected()) {
            PendingResult<AutocompletePredictionBuffer> results =
                    Places.GeoDataApi
                            .getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
                                    mBounds, mPlaceFilter);
            AutocompletePredictionBuffer autocompletePredictions = results
                    .await(60, TimeUnit.SECONDS);

            final Status status = autocompletePredictions.getStatus();
            if (!status.isSuccess()) {
                Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
                        Toast.LENGTH_SHORT).show();
                autocompletePredictions.release();
                return null;
            }
            return DataBufferUtils.freezeAndClose(autocompletePredictions);
        }
        return null;
    }
}
like image 455
Navin Gupta Avatar asked Nov 26 '15 13:11

Navin Gupta


People also ask

How do I get a city from places API?

2) Make another web-service call to https://maps.googleapis.com/maps/api/place/details/json?key=API_KEY&placeid=place_id_retrieved_in_step_1. This will return a JSON which contains address_components . Looping through the types to find locality and postal_code can give you the city name and postal code.

What is the best way to display information about a certain location in Google Maps API?

Once you have a place_id from a Place Search, you can request more details about a particular establishment or point of interest by initiating a Place Details request.


2 Answers

Looking at the documentation:

public abstract PendingResult getAutocompletePredictions (GoogleApiClient client, String query, LatLngBounds bounds, AutocompleteFilter filter) Returns autocomplete predictions for a query based on the names and addresses of places. For more information, see the developer's guide.

This method performs a network lookup.

Access to this method is subject to quota restrictions. See Usage Limits for more details.

Parameters

query The query string for which the autocomplete predictions are to be fetched.

bounds A geographic bounds. If present, returned predictions will be biased towards places in this area.

filter A filter to use for restricting the returned predictions. If null, a filter with no constraints will be used.

The description for "bounds" is to return biased predictions. So those are not filtered, but biased basing on this bounds. This means that the results inside the bound should have higher priority, but those will not be the only results.

UPDATE

As of April 2018 Google added possibility to specify how to treat the bounds in autocomplete predictions. Now you can use the getAutocompletePredictions() method of GeoDataClient class with boundsMode parameter.

See https://stackoverflow.com/a/50134855/5140781 for more details.

like image 133
N Dorigatti Avatar answered Oct 23 '22 21:10

N Dorigatti


The code you have written is right. I also had done this but never tried with bounds. I checked with bounds and gone through the documentation, its written that it will give biased results that means it will give results with priority to the within the given bounds.

Here is the documentation link

https://developers.google.com/places/android-api/autocomplete

like image 43
Nigam Patro Avatar answered Oct 23 '22 23:10

Nigam Patro