如何将Google Places API用于ANDROID

时间:2016-02-25 09:14:51

标签: android google-places-api

我正在尝试创建一个可以找到附近地方的应用。我想使用官方的Android API,但我找不到任何好的例子来学习。

我见过很多例子,但他们都使用的是Web版本,而不是Android API。谷歌的网站guides是如此蹩脚,唯一的指导是关于获得你的实际位置,我不能让它工作。我想,没有人使用这个API?

我已经获得了API_KEY,但我不知道下一步该怎么做

1 个答案:

答案 0 :(得分:1)

使用以下代码。

PickLocation.java

        import android.support.v4.app.FragmentActivity;
        import android.os.Bundle;

        import com.google.android.gms.maps.CameraUpdateFactory;
        import com.google.android.gms.maps.GoogleMap;
        import com.google.android.gms.maps.OnMapReadyCallback;
        import com.google.android.gms.maps.SupportMapFragment;
        import com.google.android.gms.maps.model.LatLng;
        import com.google.android.gms.maps.model.MarkerOptions;

        import grocery.srs.info.srsgrocery_v1.R;


        import android.os.Bundle;
        import android.support.v7.app.AppCompatActivity;
        import android.text.Html;
        import android.util.Log;
        import android.view.View;
        import android.view.WindowManager;
        import android.widget.AdapterView;
        import android.widget.AutoCompleteTextView;
        import android.widget.TextView;
        import android.widget.Toast;

        import com.google.android.gms.common.ConnectionResult;
        import com.google.android.gms.common.api.GoogleApiClient;
        import com.google.android.gms.common.api.PendingResult;
        import com.google.android.gms.common.api.ResultCallback;
        import com.google.android.gms.location.places.Place;
        import com.google.android.gms.location.places.PlaceBuffer;
        import com.google.android.gms.location.places.Places;
        import com.google.android.gms.maps.model.LatLng;
        import com.google.android.gms.maps.model.LatLngBounds;
        import grocery.srs.info.srsgrocery_v1.adapter.PlaceArrayAdapter;


        public class PickLocation extends AppCompatActivity implements
                GoogleApiClient.OnConnectionFailedListener,
                GoogleApiClient.ConnectionCallbacks {
            private static final String LOG_TAG = "MainActivity";
            private static final int GOOGLE_API_CLIENT_ID = 0;
            private AutoCompleteTextView mAutocompleteTextView;
            private TextView mNameTextView;
            private TextView mAddressTextView;
            private TextView mIdTextView;
            private TextView mPhoneTextView;
            private TextView mWebTextView;
            private TextView mAttTextView;
            private GoogleApiClient mGoogleApiClient;
            private PlaceArrayAdapter mPlaceArrayAdapter;
            private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(
                    new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.pick_location);
                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                        WindowManager.LayoutParams.FLAG_FULLSCREEN);
                mGoogleApiClient = new GoogleApiClient.Builder(PickLocation.this)
                        .addApi(Places.GEO_DATA_API)
                        .enableAutoManage(this, GOOGLE_API_CLIENT_ID, this)
                        .addConnectionCallbacks(this)
                        .build();
                mAutocompleteTextView = (AutoCompleteTextView) findViewById(R.id
                        .autoCompleteTextView);
                mAutocompleteTextView.setThreshold(3);
                mNameTextView = (TextView) findViewById(R.id.name);
                mAddressTextView = (TextView) findViewById(R.id.address);
                mIdTextView = (TextView) findViewById(R.id.place_id);
                mPhoneTextView = (TextView) findViewById(R.id.phone);
                mWebTextView = (TextView) findViewById(R.id.web);
                mAttTextView = (TextView) findViewById(R.id.att);
                mAutocompleteTextView.setOnItemClickListener(mAutocompleteClickListener);
                mPlaceArrayAdapter = new PlaceArrayAdapter(this, android.R.layout.simple_list_item_1,
                        BOUNDS_MOUNTAIN_VIEW, null);
                mAutocompleteTextView.setAdapter(mPlaceArrayAdapter);
            }

            private AdapterView.OnItemClickListener mAutocompleteClickListener
                    = new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    final PlaceArrayAdapter.PlaceAutocomplete item = mPlaceArrayAdapter.getItem(position);
                    final String placeId = String.valueOf(item.placeId);
                    Log.i(LOG_TAG, "Selected: " + item.description);
                    PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
                            .getPlaceById(mGoogleApiClient, placeId);
                    placeResult.setResultCallback(mUpdatePlaceDetailsCallback);
                    Log.i(LOG_TAG, "Fetching details for ID: " + item.placeId);
                }
            };

            private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback
                    = new ResultCallback<PlaceBuffer>() {
                @Override
                public void onResult(PlaceBuffer places) {
                    if (!places.getStatus().isSuccess()) {
                        Log.e(LOG_TAG, "Place query did not complete. Error: " +
                                places.getStatus().toString());
                        return;
                    }
                    // Selecting the first object buffer.
                    final Place place = places.get(0);
                    CharSequence attributions = places.getAttributions();

                    mNameTextView.setText(Html.fromHtml(place.getName() + ""));
                    mAddressTextView.setText(Html.fromHtml(place.getAddress() + ""));
                    mIdTextView.setText(Html.fromHtml(place.getId() + ""));
                    mPhoneTextView.setText(Html.fromHtml(place.getPhoneNumber() + ""));
                    mWebTextView.setText(place.getWebsiteUri() + "");
                    if (attributions != null) {
                        mAttTextView.setText(Html.fromHtml(attributions.toString()));
                    }
                }
            };

            @Override
            public void onConnected(Bundle bundle) {
                mPlaceArrayAdapter.setGoogleApiClient(mGoogleApiClient);
                Log.i(LOG_TAG, "Google Places API connected.");

            }

            @Override
            public void onConnectionFailed(ConnectionResult connectionResult) {
                Log.e(LOG_TAG, "Google Places API connection failed with error code: "
                        + connectionResult.getErrorCode());

                Toast.makeText(this,
                        "Google Places API connection failed with error code:" +
                                connectionResult.getErrorCode(),
                        Toast.LENGTH_LONG).show();
            }

            @Override
            public void onConnectionSuspended(int i) {
                mPlaceArrayAdapter.setGoogleApiClient(null);
                Log.e(LOG_TAG, "Google Places API connection suspended.");
            }
        }

pick_location.xml

        

        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <AutoCompleteTextView
            android:id="@+id/autoCompleteTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:hint="Enter Place Here"/>

        <LinearLayout
            android:id="@+id/mylocation_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/autoCompleteTextView"
            android:background="@color/border">

            <Button
                android:id="@+id/btn_use_my_location"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_below="@+id/location_searchView"
                android:layout_margin="5dp"
                android:background="#FFF"
                android:drawableLeft="@mipmap/location"
                android:gravity="center_vertical"
                android:text="Use My Location"
                android:textColor="@color/border" />
        </LinearLayout>



    </RelativeLayout>

PlaceArrayAdapter.java

    import android.content.Context;
    import android.util.Log;
    import android.widget.ArrayAdapter;
    import android.widget.Filter;
    import android.widget.Filterable;
    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.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.Iterator;
    import java.util.concurrent.TimeUnit;

    public class PlaceArrayAdapter
            extends ArrayAdapter<PlaceArrayAdapter.PlaceAutocomplete> implements Filterable {
        private static final String TAG = "PlaceArrayAdapter";
        private GoogleApiClient mGoogleApiClient;
        private AutocompleteFilter mPlaceFilter;
        private LatLngBounds mBounds;
        private ArrayList<PlaceAutocomplete> mResultList;

        /**
         * Constructor
         *
         * @param context  Context
         * @param resource Layout resource
         * @param bounds   Used to specify the search bounds
         * @param filter   Used to specify place types
         */
        public PlaceArrayAdapter(Context context, int resource, LatLngBounds bounds,
                                 AutocompleteFilter filter) {
            super(context, resource);
            mBounds = bounds;
            mPlaceFilter = filter;
        }

        public void setGoogleApiClient(GoogleApiClient googleApiClient) {
            if (googleApiClient == null || !googleApiClient.isConnected()) {
                mGoogleApiClient = null;
            } else {
                mGoogleApiClient = googleApiClient;
            }
        }

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

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

        private ArrayList<PlaceAutocomplete> getPredictions(CharSequence constraint) {
            if (mGoogleApiClient != null) {
                Log.i(TAG, "Executing autocomplete query for: " + constraint);
                PendingResult<AutocompletePredictionBuffer> results =
                        Places.GeoDataApi
                                .getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
                                        mBounds, mPlaceFilter);
                // Wait for predictions, set the timeout.
                AutocompletePredictionBuffer autocompletePredictions = results
                        .await(60, TimeUnit.SECONDS);
                final Status status = autocompletePredictions.getStatus();
                if (!status.isSuccess()) {
                    Toast.makeText(getContext(), "Error: " + status.toString(),
                            Toast.LENGTH_SHORT).show();
                    Log.e(TAG, "Error getting place predictions: " + status
                            .toString());
                    autocompletePredictions.release();
                    return null;
                }

                Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
                        + " predictions.");
                Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
                ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
                while (iterator.hasNext()) {
                    AutocompletePrediction prediction = iterator.next();
                    resultList.add(new PlaceAutocomplete(prediction.getPlaceId(),
                            prediction.getDescription()));
                }
                // Buffer release
                autocompletePredictions.release();
                return resultList;
            }
            Log.e(TAG, "Google API client is not connected.");
            return null;
        }

        @Override
        public Filter getFilter() {
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults results = new FilterResults();
                    if (constraint != null) {
                        // Query the autocomplete API for the entered constraint
                        mResultList = getPredictions(constraint);
                        if (mResultList != null) {
                            // 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;
        }

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