谷歌自动填充API Android:边界不起作用

时间:2015-10-30 04:10:18

标签: android google-places-api

我正在定义我的界限如下:

describe('header Module', function(){
it('should check title text',function(callback){
    var header = element(by.css('.title'));
    header.getText()
       .then(function (text) {
           expect(text).toContain('Ionic Blank Starter');
           callback();
       }); 
});
});

按如下方式创建Goolge API客户端:

private static final LatLngBounds BOUNDS_CHENNAI = new LatLngBounds(
        new LatLng(12.8339547, 80.0817007), new LatLng(13.2611661, 80.33632279999999)); // Chennai city bounds.

使用适配器中的那些边界如下:

mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this,this)
            .addApi(Places.GEO_DATA_API)
            .addConnectionCallbacks(this)
            .build();

根据文件说明应该只返回我在钦奈市内的位置,但它返回我来自世界各地的位置。

E.g。当我输入“Sola”时,它返回艾哈迈达巴德市的“索拉路”,而不是在界限内显示匹配的结果。

3 个答案:

答案 0 :(得分:6)

我对android中的界限有同样的问题。我已经尝试了一切,无法解决问题。

在寻找其他网页时,我在尝试设置边界区域时在javascript文档中找到了这个:

  

结果偏向于(但不限于)包含在这些范围内的地方。

看起来android安置api文档不完整。我们将不得不等待。

答案 1 :(得分:0)

如果您必须显示指定国家/地区或附近国家/地区的结果,我找到了原始解决方法:

private ArrayList<PlaceAutocomplete> getAutocomplete(CharSequence constraint) {
    if (mGoogleApiClient.isConnected()) {

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

        AutocompletePredictionBuffer autocompletePredictions = results
                .await(60, TimeUnit.SECONDS);

        final Status status = autocompletePredictions.getStatus();
        if (status.isSuccess()) {
            Log.i(LOG_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<PlaceAutocomplete> 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.
                String data = prediction.getDescription();

                // here we manually checking whether description contains our needed country(ies)
                if (predictionIsInNeededCountry(data)) {
                    resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getDescription(),
                            prediction.getPrimaryText(mCharacterStyle), prediction.getSecondaryText(mCharacterStyle),
                            prediction.getFullText(mCharacterStyle)));
                }
            }
        } else {
            Toast.makeText(mContext, "Error contacting API: " + status.toString(),
                    Toast.LENGTH_SHORT).show();
            Log.e(LOG_TAG, "Error getting autocomplete prediction API call: " + status.toString());
            autocompletePredictions.release();
            return null;
        }

        // Release the buffer now that all data has been copied.
        autocompletePredictions.release();

        return resultList;
    }
    Log.e(LOG_TAG, "Google API client is not connected for autocomplete query.");
    return null;
}

private boolean predictionIsInNeededCountry(String data) {

    // here you can add countries (in different languages if you want)
    // also you can try get current country programmatically with use of Geocoder
    if (data.contains("Ukraine") || data.contains("Украина") || data.contains("Україна")) {
        return true;
    }
    return false;
}

对于边界,我使用当前坐标(西南和东北的当前纬度和经度)。

我也实施了另一种解决方案:

  1. 获取预测
  2. 获取每个预测的放置详细信息(您可以传递数组以立即获取所有点数。)
  3. 将Point的坐标与current进行比较,并将它们从最近到最远的位置进行排序。
  4. 显示按距离结果排序。
  5. 它似乎更准确,但需要额外的请求和计算 在我的情况下,我只需要来自2个国家的结果,所以我最终得到了第一个更简单的解决方案。

答案 2 :(得分:-2)

import android.content.Context;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.Spanned;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.TextView;
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.AutocompletePrediction;
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;

public class SearchPlacesActivity extends AppCompatActivity implements    GoogleApiClient.OnConnectionFailedListener {


protected GoogleApiClient mGoogleApiClient;

private PlaceAutocompleteAdapter mAdapter;

private AutoCompleteTextView mAutocompleteView;

private TextView mPlaceDetailsText;

private TextView mPlaceDetailsAttribution;
Toolbar toolbar;

private static final LatLngBounds BOUNDS_GREATER_SYDNEY = new LatLngBounds(
        // new LatLng(-34.041458, 150.790100), new LatLng(-33.682247, 151.383362));
        new LatLng(0, 0), new LatLng(0, 0));

@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, 0 /* clientId */, this)
            .addApi(Places.GEO_DATA_API)
            .build();

    setContentView(R.layout.activity_search_places);
    //Set toolbar
    toolbar = (Toolbar) findViewById(R.id.maintoolbar);

    toolbar.setTitle("Change Location");

    toolbar.setTitleTextColor(0xFFFFFFFF);

    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(false);



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

    // Set up the adapter that will retrieve suggestions from the Places Geo Data API that cover
    // the entire world.
    mAdapter = new PlaceAutocompleteAdapter(this, mGoogleApiClient, BOUNDS_GREATER_SYDNEY,
            null);
    mAutocompleteView.setAdapter(mAdapter);

    // Set up the 'clear text' button that clears the text in the autocomplete view
    Button clearButton = (Button) findViewById(R.id.button_clear);
    clearButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mAutocompleteView.setText("");
        }
    });
}

/**
 * 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(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 AutocompletePrediction from which we
         read the place ID and title.
          */
        final AutocompletePrediction item = mAdapter.getItem(position);
        final String placeId = item.getPlaceId();
        final CharSequence primaryText = item.getPrimaryText(null);

        AppLog.i("Search", "Autocomplete item selected: " + primaryText);

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

        /*Toast.makeText(getApplicationContext(), "Clicked: " + primaryText,
                Toast.LENGTH_SHORT).show();*/
        AppLog.i("Search", "Called getPlaceById to get Place details for " + 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
            AppLog.e("Search", "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(),place.getLatLng()));*/

        AppLog.e("LAtlng", ">>>>>>>>>>>>" + place.getLatLng());
        LatLng latLng = place.getLatLng();
        double lat = latLng.latitude;
        double lng = latLng.longitude;
SearchFood.searchresult = place.getName().toString() + "," +   place.getAddress().toString();
SearchActivity.searchresult = place.getName().toString() + "," + place.getAddress().toString();

        onBackPressed();
        places.release();
    }
};

private static Spanned formatPlaceDetails(Resources res, CharSequence name, String id,
                                          CharSequence address, CharSequence phoneNumber, Uri websiteUri, LatLng latLng) {
    AppLog.e("Search", 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) {

    AppLog.e("Search", "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();*/
}


@Override
public void onBackPressed() {

    super.onBackPressed();
    SearchPlacesActivity.this.finish();
    overridePendingTransition(R.anim.trans_right_in, R.anim.trans_right_out);

}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == android.R.id.home) {
        onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}
}

// ADAPTER CLASS


import android.content.Context;
import android.graphics.Typeface;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
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 com.eatcommunity.util.AppLog;
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;

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;


private GoogleApiClient mGoogleApiClient;


private LatLngBounds mBounds;
private AutocompleteFilter mPlaceFilter;
public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient,
                                LatLngBounds bounds, AutocompleteFilter filter) {
    super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1);
    mGoogleApiClient = googleApiClient;
    mBounds = bounds;
    mPlaceFilter = filter;
}
public void setBounds(LatLngBounds bounds) {
    mBounds = bounds;
}
@Override
public int getCount() {
    return mResultList.size();
}
@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;
}

@Override
public Filter getFilter() {
    return 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();
            }
        }

        @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);
            }
        }
    };
}
private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) {
    if (mGoogleApiClient.isConnected()) {
        AppLog.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);

        AutocompletePredictionBuffer autocompletePredictions = results
                .await(60, TimeUnit.SECONDS);

        final Status status = autocompletePredictions.getStatus();
        if (!status.isSuccess()) {
           /* Toast.makeText(getContext(), "Error contacting API: " + status.toString(),
                    Toast.LENGTH_SHORT).show();*/
            AppLog.e(TAG, "Error getting autocomplete prediction API call: " + status.toString());
            autocompletePredictions.release();
            return null;
        }

        return DataBufferUtils.freezeAndClose(autocompletePredictions);
    }
    AppLog.e(TAG, "Google API client is not connected for autocomplete query.");
    return null;
}
}




<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:id="@+id/container_toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

<include
android:id="@+id/maintoolbar"
layout="@layout/application_toolbar" />
</LinearLayout>

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/container_toolbar">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Search Places"
android:textAppearance="?  android:attr/textAppearanceMedium" />

<AutoCompleteTextView
android:id="@+id/autocomplete_places"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="Enter your place"
android:singleLine="true" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:src="@drawable/powered_by_google_light"
android:visibility="gone" />

<Button
android:id="@+id/button_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Clear text" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Selelcted Place"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="gone" />

<TextView
android:id="@+id/place_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:autoLink="all"
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/activity_vertical_margin"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</ScrollView>
</RelativeLayout>

Menifest File change

        <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="YOURAPIKEY" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />