通过加载Google Places API获取AutoCompleteTextView中项目点击的地名?

时间:2018-01-11 05:07:39

标签: android autocomplete google-places-api

我正在GoogleApiClient使用Places.GEO_DATA_API api在AutoCompleteTextView中搜索时获取地点列表。地方正在变得很好,我只需要打印AutoCompleteTextView中选择的地点。我使用了OnItemClickListener并且它引发了一些错误。你能帮我打印一下从AutoCompleteTextView中选出的地方吗?有没有简单的方法来打印所选的地名?

我的班级文件

 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));

我的适配器

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;
    }


}

错误当我尝试打印地点时

   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)

1 个答案:

答案 0 :(得分:3)

我通过创建回调来实现这一点,因为我必须在不同的地方使用它,您可以根据您的要求更改此代码,我可以从上面的适配器获取地点详细信息。

// 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();
                }
            }
        };