ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[![screenshot](https://box.kancloud.cn/2015-09-17_55fa6f7c6e809.png "screenshot")](https://box.kancloud.cn/2015-09-17_55fa6f7c6e809.png "screenshot") -activity_main.xml | ~~~ 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 ~~~ | ~~~ <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/margin_16dp" android:orientation="vertical"> <AutoCompleteTextView android:id="@+id/autocomplete_places" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:hint="@string/autocomplete_hint" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingTop="@dimen/margin_8dp"> <Button android:id="@+id/ll_current_location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/get_current_place" android:textAppearance="?android:attr/textAppearanceSmall" /> </LinearLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:src="@drawable/powered_by_google_light" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/selected_place" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/place_details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:autoLink="all" android:paddingTop="@dimen/margin_8dp" android:text="" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/place_attribution" android:layout_width="wrap_content" android:layout_height="wrap_content" android:autoLink="all" android:paddingTop="@dimen/margin_16dp" android:text="" android:textAppearance="?android:attr/textAppearanceSmall" /></LinearLayout> ~~~ | -PlaceAutocompleteAdapter.java | ~~~ 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 ~~~ | ~~~ public class PlaceAutocompleteAdapter extends ArrayAdapter<PlaceAutocompleteAdapter.PlaceAutocomplete> implements Filterable { private static final String TAG = "PlaceAutocompleteAdapter"; /** * Current results returned by this adapter. */ private ArrayList<PlaceAutocomplete> 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, int resource, GoogleApiClient googleApiClient, LatLngBounds bounds, AutocompleteFilter filter) { super(context, resource); 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 PlaceAutocomplete getItem(int position) { return mResultList.get(position); } /** * Returns the filter for the current set of autocomplete results. */ @Override public Filter getFilter() { Filter filter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); // Skip the autocomplete query if no constraints are given. if (constraint != null) { // Query the autocomplete API for the (constraint) search string. mResultList = getAutocomplete(constraint); if (mResultList != null) { // The API successfully returned 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; } private ArrayList<PlaceAutocomplete> 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(), 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."); // Copy the results into our own data structure, because we can't hold onto the buffer. // AutocompletePrediction objects encapsulate the API response (place ID and description). Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator(); ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount()); while (iterator.hasNext()) { AutocompletePrediction prediction = iterator.next(); // Get the details of this prediction and copy it into a new PlaceAutocomplete object. resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getDescription())); } // Release the buffer now that all data has been copied. autocompletePredictions.release(); return resultList; } Log.e(TAG, "Google API client is not connected for autocomplete query."); return null; } /** * Holder for Places Geo Data Autocomplete API results. */ 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(); } }} ~~~ | -MainActivity.java | ~~~ 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 ~~~ | ~~~ public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener { /** * GoogleApiClient wraps our service connection to Google Play Services and provides access * to the user's sign in state as well as the Google's APIs. */ private static final int GOOGLE_API_CLIENT_ID = 0; protected GoogleApiClient mGoogleApiClient; private PlaceAutocompleteAdapter mAdapter; private AutoCompleteTextView mAutocompleteView; private TextView mPlaceDetailsText; private TextView mPlaceDetailsAttribution; private Button mCurrentLocation; private static final String TAG = "MainActivity"; private static final LatLngBounds BOUNDS_GREATER_SYDNEY = new LatLngBounds( new LatLng(-34.041458, 150.790100), new LatLng(-33.682247, 151.383362)); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Construct a GoogleApiClient for the {@link Places#GEO_DATA_API} using AutoManage // functionality, which automatically sets up the API client to handle Activity lifecycle // events. If your activity does not extend FragmentActivity, make sure to call connect() // and disconnect() explicitly. mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this, GOOGLE_API_CLIENT_ID /* clientId */, this) .addApi(Places.GEO_DATA_API) .addApi(Places.PLACE_DETECTION_API) .build(); setContentView(R.layout.activity_main); // Retrieve the AutoCompleteTextView that will display Place suggestions. mAutocompleteView = (AutoCompleteTextView) findViewById(R.id.autocomplete_places); // Register a listener that receives callbacks when a suggestion has been selected mAutocompleteView.setOnItemClickListener(mAutocompleteClickListener); // Retrieve the TextViews that will display details and attributions of the selected place. mPlaceDetailsText = (TextView) findViewById(R.id.place_details); mPlaceDetailsAttribution = (TextView) findViewById(R.id.place_attribution); // CurrentLocation mCurrentLocation = (Button) findViewById(R.id.ll_current_location); mCurrentLocation.setOnClickListener(mOnClickListener); // Set up the adapter that will retrieve suggestions from the Places Geo Data API that cover // the entire world. mAdapter = new PlaceAutocompleteAdapter(this, android.R.layout.simple_list_item_1, mGoogleApiClient, BOUNDS_GREATER_SYDNEY, null); mAutocompleteView.setAdapter(mAdapter); } private View.OnClickListener mOnClickListener = new View.OnClickListener() { @Override public void onClick(View view) { PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi .getCurrentPlace(mGoogleApiClient, null); result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() { @Override public void onResult(PlaceLikelihoodBuffer likelyPlaces) { if (!likelyPlaces.getStatus().isSuccess()) { // Request did not complete successfully Log.e(TAG, "Place query did not complete. Error: " + likelyPlaces.getStatus().toString()); likelyPlaces.release(); return; } String placeName = String.format("%s", likelyPlaces.get(0).getPlace().getName()); String placeAttributuion = String.format("%s", likelyPlaces.get(0).getPlace().getAddress()); mPlaceDetailsText.setText(placeName); mPlaceDetailsAttribution.setText(placeAttributuion); likelyPlaces.release(); } }); } }; /** * Listener that handles selections from suggestions from the AutoCompleteTextView that * displays Place suggestions. * Gets the place id of the selected item and issues a request to the Places Geo Data API * to retrieve more details about the place. * * @see com.google.android.gms.location.places.GeoDataApi#getPlaceById(com.google.android.gms.common.api.GoogleApiClient, * String...) */ private AdapterView.OnItemClickListener mAutocompleteClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { /* Retrieve the place ID of the selected item from the Adapter. The adapter stores each Place suggestion in a PlaceAutocomplete object from which we read the place ID. */ final PlaceAutocompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position); final String placeId = String.valueOf(item.placeId); Log.i(TAG, "Autocomplete item selected: " + item.description); /* Issue a request to the Places Geo Data API to retrieve a Place object with additional details about the place. */ PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi .getPlaceById(mGoogleApiClient, placeId); placeResult.setResultCallback(mUpdatePlaceDetailsCallback); Log.i(TAG, "Called getPlaceById to get Place details for " + item.placeId); } }; /** * Callback for results from a Places Geo Data API query that shows the first place result in * the details view on screen. */ private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback = new ResultCallback<PlaceBuffer>() { @Override public void onResult(PlaceBuffer places) { if (!places.getStatus().isSuccess()) { // Request did not complete successfully Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString()); places.release(); return; } // Get the Place object from the buffer. final Place place = places.get(0); // Format details of the place for display and show it in a TextView. mPlaceDetailsText.setText(formatPlaceDetails(getResources(), place.getName(), place.getId(), place.getAddress(), place.getPhoneNumber(), place.getWebsiteUri())); // Display the third party attributions if set. final CharSequence thirdPartyAttribution = places.getAttributions(); if (thirdPartyAttribution == null) { mPlaceDetailsAttribution.setVisibility(View.GONE); } else { mPlaceDetailsAttribution.setVisibility(View.VISIBLE); mPlaceDetailsAttribution.setText(Html.fromHtml(thirdPartyAttribution.toString())); } Log.i(TAG, "Place details received: " + place.getName()); places.release(); } }; private static Spanned formatPlaceDetails(Resources res, CharSequence name, String id, CharSequence address, CharSequence phoneNumber, Uri websiteUri) { Log.e(TAG, res.getString(R.string.place_details, name, id, address, phoneNumber, websiteUri)); return Html.fromHtml(res.getString(R.string.place_details, name, id, address, phoneNumber, websiteUri)); } /** * Called when the Activity could not connect to Google Play services and the auto manager * could resolve the error automatically. * In this case the API is not available and notify the user. * * @param connectionResult can be inspected to determine the cause of the failure */ @Override public void onConnectionFailed(ConnectionResult connectionResult) { Log.e(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode()); // TODO(Developer): Check error code and notify the user of error state and resolution. Toast.makeText(this, "Could not connect to Google API Client: Error " + connectionResult.getErrorCode(), Toast.LENGTH_SHORT).show(); MainActivity.this.finish(); }} ~~~ | [![screenshot](https://box.kancloud.cn/2015-09-17_55fa6f820aba7.png "screenshot")](https://box.kancloud.cn/2015-09-17_55fa6f820aba7.png "screenshot")[![screenshot](https://box.kancloud.cn/2015-09-17_55fa6f82760b5.png "screenshot")](https://box.kancloud.cn/2015-09-17_55fa6f82760b5.png "screenshot")