Jayesh M
Jayesh M

Reputation: 139

Get the place name on item click in AutoCompleteTextView by loading Google Places API?

I am using GoogleApiClient with Places.GEO_DATA_API api to get places list while searching in AutoCompleteTextView. Places are getting fine and I just needed to print the place that selected in AutoCompleteTextView. I used OnItemClickListener and it throws some error. Can you please help me to print the place which selected from AutoCompleteTextView. Is there any easy way to print the place name selected ?

My Class file

 mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .enableAutoManage(getActivity(), 200 /* clientId */, this)
                .addApi(Places.GEO_DATA_API)
                .build();

        ac_location.setAdapter(new PlaceAutocompleteAdapter(getActivity(), mGoogleApiClient, null, null));

My Adapter

package grocery.iroid.com.grocery.ui.main.location.adapter;

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.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 java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import grocery.iroid.com.grocery.R;

public class PlaceAutocompleteAdapter
        extends ArrayAdapter<AutocompletePrediction> implements Filterable {

    private static final String TAG = "PlaceAutocompleteAdapter";
    private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD);
    /**
     * Current results returned by this adapter.
     */
    private ArrayList<AutocompletePrediction> mResultList;

    /**
     * Handles autocomplete requests.
     */
    private GoogleApiClient mGoogleApiClient;

    /**
     * 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 ArrayAdapter#ArrayAdapter(Context, int)
     */
    public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient,
                                    LatLngBounds bounds, AutocompleteFilter filter) {
        //super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
        super(context, R.layout.row_place_auto_complete, R.id.tvPlace);
        mGoogleApiClient = googleApiClient;
        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(R.id.tvPlace);
        TextView textView2 = (TextView) row.findViewById(R.id.tvCountry);
        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.
     * objects to store the Place ID and description that the API returns.
     * 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 Places#GEO_DATA_API#getAutocomplete(CharSequence)
     * @see AutocompletePrediction#freeze()
     */
    private ArrayList<AutocompletePrediction> 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(),
                                    null/*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()) {
                Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
                        Toast.LENGTH_SHORT).show();
               // Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString());
                autocompletePredictions.release();
                return null;
            }

          //  Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
                  //  + " predictions.");

            // Freeze the results immutable representation that can be stored safely.
            return DataBufferUtils.freezeAndClose(autocompletePredictions);
        }
      //  Log.e(TAG, "Google API client is not connected for autocomplete query.");
        return null;
    }


}

Error When I tried to print the place

   ac_location.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // Get data associated with the specified position
            // in the list (AdapterView)
            String description = (String) parent.getItemAtPosition(position);
            Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
        }
    });

Logcat

 01-11 10:45:06.967 3527-3527/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 Process: grocery.iroid.com.grocery, PID: 3527
                                                 java.lang.ClassCastException: com.google.android.gms.location.places.internal.zza cannot be cast to java.lang.String
                                                     at grocery.iroid.com.grocery.ui.main.location.LocationResultFragment$2.onItemClick(LocationResultFragment.java:169)
                                                     at android.widget.AutoCompleteTextView.performCompletion(AutoCompleteTextView.java:906)
                                                     at android.widget.AutoCompleteTextView.-wrap1(AutoCompleteTextView.java)
                                                     at android.widget.AutoCompleteTextView$DropDownItemClickListener.onItemClick(AutoCompleteTextView.java:1202)
                                                     at android.widget.AdapterView.performItemClick(AdapterView.java:310)
                                                     at android.widget.AbsListView.performItemClick(AbsListView.java:1145)
                                                     at android.widget.AbsListView$PerformClick.run(AbsListView.java:3042)
                                                     at android.widget.AbsListView$3.run(AbsListView.java:3879)
                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                     at android.os.Looper.loop(Looper.java:148)
                                                     at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Upvotes: 2

Views: 1944

Answers (1)

lakshay
lakshay

Reputation: 713

I have achieved this by creating a callback, because i have to use this in different places, you can change this code according to your requirement, I am able to get place details from the above adapter.

// CallBack implement this callback to get place details    

public interface OnAutoLocationItemClickListner {

    public void onAutoLocationItemClicked(String addr, double Lat, double longitutde);
}

private AutoCompleteTextView autoCompleteTextView;
private PlaceAutocompleteAdapter mAdapter;

autoCompleteTextView = findViewById(R.id.autoCompleteTextView);
mAdapter = new PlaceAutocompleteAdapter(activity, mGoogleApiClient, null);
autoCompleteTextView.setAdapter(mAdapter);
autoCompleteTextView.setOnItemClickListener(mAutocompleteClickListener);  

private AdapterView.OnItemClickListener mAutocompleteClickListener = new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                final AutocompletePrediction item = mAdapter.getItem(position);
                if (item != null) {
                    final String placeId = item.getPlaceId();
                    final CharSequence primaryText = item.getPrimaryText(null);
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
                            .getPlaceById(mGoogleApiClient, placeId);
                    placeResult.setResultCallback(mUpdatePlaceDetailsCallback);
                }

            }
        };

        private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback
                = new ResultCallback<PlaceBuffer>() {
            @Override
            public void onResult(PlaceBuffer places) {
                try {
                    if (places.getStatus().isSuccess() && places.getCount() > 0) {
                        final Place myPlace = places.get(0);
                        if (listner != null)
                            isClicked = true;
                        listner.onAutoLocationItemClicked(myPlace.getAddress().toString(), myPlace.getLatLng().latitude, myPlace.getLatLng().longitude);
                        Log.e("Place found: ", "" + myPlace.getName());
                        // here you will get place string and its respective latitude and longitude
                    } else {
                        Log.e("Place not found", "");
                        ToastUtil.showShortToast("Error getting details of this address");
                    }
                    places.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

Upvotes: 3

Related Questions