2015-10-30 18 views
7

Tôi xác định giới hạn của tôi như sau:nơi Google tự động hoàn Android API: giới hạn không làm việc

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

Tạo client Goolge API như sau:

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

Và sử dụng những giới hạn trong bộ chuyển đổi như sau :

PendingResult<AutocompletePredictionBuffer> results = 
       Places.GeoDataApi 
         .getAutocompletePredictions(mGoogleApiClient, constraint.toString(), 
           mBounds, mPlaceFilter); 

Theo tài liệu hướng dẫn sẽ chỉ trả lại vị trí của tôi trong thành phố Chennai, nhưng tôi t trả lại cho tôi vị trí từ khắp nơi trên thế giới.

Ví dụ: Khi tôi gõ "Sola" nó trả về "Sola road" của thành phố Ahmedabad thay vì hiển thị kết quả phù hợp trong giới hạn.

+0

bạn đã tìm thấy giải pháp chưa? –

+0

Tôi đã tìm ra rằng để tìm những địa điểm gần nhất, trong giới hạn bạn có thể sử dụng vị trí hiện tại thay vì khu vực và nó hoạt động tốt hơn một chút –

+0

Tôi chưa tìm được giải pháp nào, nó vẫn mang lại cho tôi tất cả các địa điểm trên khắp thế giới. Vì vậy, tôi xử lý nó ở phía máy chủ của tôi để xác nhận vị trí! –

Trả lời

-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" /> 
+0

@Thiết lập Api của bạn trên API Google Console và triển khai mã trên và phát lại khóa api trong phần kê khai. Nó sẽ hoạt động tốt. –

+0

Bạn có nghiêm túc không, câu trả lời này như thế nào? –

+0

@jawad: Vui lòng thử ví dụ này. Đó là làm việc cho tôi. –

6

Tôi gặp vấn đề tương tự với giới hạn trong Android. Tôi đã thử mọi thứ và không thể giải quyết vấn đề.

Nhìn cho các trang web khác, tôi thấy điều này trong các tài liệu cho javascript khi cố gắng để thiết lập giới hạn đến một khu vực:

Các kết quả được thiên vị về phía, nhưng không bị giới hạn, địa điểm chứa bên trong những giới hạn.

Dường như tài liệu api địa điểm android chưa hoàn tất. Chúng ta sẽ phải đợi.

+0

Có, chúng không bị hạn chế. –

0

Tôi tìm thấy một workaround nguyên thủy trong trường hợp bạn phải hiển thị một kết quả của đất nước quy định hoặc các nước lân cận:

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

Đối với các giới hạn tôi sử dụng tọa độ hiện tại (vĩ độ hiện tại và kinh độ cho tây nam và đông bắc).

Ngoài ra tôi thực hiện một giải pháp:

  1. Nhận dự đoán
  2. Nhận Nơi chi tiết của mỗi dự đoán (bạn có thể vượt qua một mảng để có được tất cả các điểm cùng một lúc).
  3. So sánh các tọa độ của điểm với hiện tại và sắp xếp chúng từ xa nhất đến xa nhất.
  4. Hiển thị được sắp xếp theo kết quả khoảng cách.

Dường như hoạt động chính xác hơn, nhưng yêu cầu các yêu cầu và tính toán bổ sung.
Trong trường hợp của tôi, tôi chỉ cần kết quả từ 2 quốc gia để tôi kết thúc với giải pháp đơn giản đầu tiên.

Các vấn đề liên quan