I am implementing google's places autocomplete on my Android app and it is working which show every similar places, but how can I get cities suggestions only when user tries to search anything.
I have searched alot I was unable to find similar problems for Android places autocomplete.
I have implemented PlaceAutocompleteAdapter from google's example and this how it looks like
PlaceAutocompleteAdapter
package com.tribikram.smartcitytraveler;
import android.content.Context;
import android.graphics.Typeface;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
import android.util.Log;
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 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.AutocompletePredictionBufferResponse;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.tasks.RuntimeExecutionException;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Adapter that handles Autocomplete requests from the Places Geo Data Client.
* {@link AutocompletePrediction} results from the API are frozen and stored directly in this
* adapter. (See {@link AutocompletePrediction#freeze()}.)
*/
public class PlaceAutocompleteAdapter
extends ArrayAdapter<AutocompletePrediction> implements Filterable {
private static final String TAG = "PlaceACA";
private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD);
/**
* Current results returned by this adapter.
*/
private ArrayList<AutocompletePrediction> mResultList;
/**
* Handles autocomplete requests.
*/
private GeoDataClient mGeoDataClient;
/**
* The bounds used for Places Geo Data autocomplete API requests.
*/
private LatLngBounds mBounds;
/**
* The autocomplete filter used to restrict queries to a specific set of place types.
*/
private AutocompleteFilter mPlaceFilter;
/**
* Initializes with a resource for text rows and autocomplete query bounds.
*
* @see android.widget.ArrayAdapter#ArrayAdapter(android.content.Context, int)
*/
public PlaceAutocompleteAdapter(Context context, GeoDataClient geoDataClient,
LatLngBounds bounds, AutocompleteFilter filter) {
super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
mGeoDataClient = geoDataClient;
mBounds = bounds;
mPlaceFilter = filter;
}
/**
* Sets the bounds for all subsequent queries.
*/
public void setBounds(LatLngBounds bounds) {
mBounds = bounds;
}
/**
* Returns the number of results received in the last autocomplete query.
*/
@Override
public int getCount() {
return mResultList.size();
}
/**
* Returns an item from the last autocomplete query.
*/
@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);
// Sets the primary and secondary text for a row.
// Note that getPrimaryText() and getSecondaryText() return a CharSequence that may contain
// styling based on the given CharacterStyle.
AutocompletePrediction item = getItem(position);
TextView textView1 = (TextView) row.findViewById(android.R.id.text1);
TextView textView2 = (TextView) row.findViewById(android.R.id.text2);
textView1.setText(item.getPrimaryText(STYLE_BOLD));
textView2.setText(item.getSecondaryText(STYLE_BOLD));
return row;
}
/**
* Returns the filter for the current set of autocomplete results.
*/
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// We need a separate list to store the results, since
// this is run asynchronously.
ArrayList<AutocompletePrediction> filterData = new ArrayList<>();
// Skip the autocomplete query if no constraints are given.
if (constraint != null) {
// Query the autocomplete API for the (constraint) search string.
filterData = getAutocomplete(constraint);
}
results.values = filterData;
if (filterData != null) {
results.count = filterData.size();
} else {
results.count = 0;
}
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.
mResultList = (ArrayList<AutocompletePrediction>) results.values;
notifyDataSetChanged();
} else {
// The API did not return any results, invalidate the data set.
notifyDataSetInvalidated();
}
}
@Override
public CharSequence convertResultToString(Object resultValue) {
// Override this method to display a readable result in the AutocompleteTextView
// when clicked.
if (resultValue instanceof AutocompletePrediction) {
return ((AutocompletePrediction) resultValue).getFullText(null);
} else {
return super.convertResultToString(resultValue);
}
}
};
}
/**
* Submits an autocomplete query to the Places Geo Data Autocomplete API.
* Results are returned as frozen AutocompletePrediction objects, ready to be cached.
* Returns an empty list if no results were found.
* Returns null if the API client is not available or the query did not complete
* successfully.
* This method MUST be called off the main UI thread, as it will block until data is returned
* from the API, which may include a network request.
*
* @param constraint Autocomplete query string
* @return Results from the autocomplete API or null if the query was not successful.
* @see GeoDataClient#getAutocompletePredictions(String, LatLngBounds, AutocompleteFilter)
* @see AutocompletePrediction#freeze()
*/
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {
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.
Task<AutocompletePredictionBufferResponse> results =
mGeoDataClient.getAutocompletePredictions(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.
try {
Tasks.await(results, 60, TimeUnit.SECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
e.printStackTrace();
}
try {
AutocompletePredictionBufferResponse autocompletePredictions = results.getResult();
Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");
// Freeze the results immutable representation that can be stored safely.
return DataBufferUtils.freezeAndClose(autocompletePredictions);
} catch (RuntimeExecutionException e) {
// If the query did not complete successfully return null
Toast.makeText(getContext(), "Error contacting API: " + e.toString(),
Toast.LENGTH_SHORT).show();
Log.e(TAG, "Error getting autocomplete prediction API call", e);
return null;
}
}
}
I am beginner so If you found any mistake then please point out. That would be great help. Thank you!
You can use Place Autocomplete by google
Step 1:-
Add a project in google developers account and get the key from there https://console.developers.google.com/flows/enableapi?apiid=appsactivity&credential=client_key&pli=1
Example code
Step 2:-
Add gradle
implementation 'com.google.android.gms:play-services-places:9.6.0'
or latest version
implementation 'com.google.android.gms:play-services-places:latest_version'
Step 3:-
add this tag in manifest file
<meta-data android:name="com.google.android.geo.API_KEY" android:value="Your api key"/>
Step 4:-
Now Implement your fragment or activity class with PlaceSelectionListener
like this
public class Fragment_Profile extends Fragment implements View.OnClickListener, PlaceSelectionListener
declare this variable
private static final int REQUEST_SELECT_PLACE = 1000;
then finally on button click call this
try {
AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
.setTypeFilter(AutocompleteFilter.TYPE_FILTER_CITIES)
.build();
Intent intent = new PlaceAutocomplete.IntentBuilder
(PlaceAutocomplete.MODE_FULLSCREEN)
.setFilter(typeFilter)
.build(getActivity());
startActivityForResult(intent, REQUEST_SELECT_PLACE);
} catch (GooglePlayServicesRepairableException |
GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
This is the filter you are looking for
AutocompleteFilter.TYPE_FILTER_CITIES
then in the overridden method get the selected value
@Override
public void onPlaceSelected(Place place) {
Log.i("Selected", "Place Selected: " + place.getAddress());
}
You can check the documentation from here https://developers.google.com/places/android-sdk/autocomplete and http://codesfor.in/android-places-autocomplete-example/
Thanks
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With