2015-10-30 36 views
7

我定義我的範圍如下:谷歌的地方自動填充API安卓界限不工作

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

創建Goolge的API客戶端如下:

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

,並利用這些界限適配器如下:

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

根據文件是應該返回我只在欽奈市內的位置,但我t讓我回到世界各地。

E.g.當我輸入「Sola」時,它將返回Ahmedab​​ad城市的「Sola路」,而不是在邊界內顯示匹配結果。

+0

您是否找到了解決方案? –

+0

我想出了尋找最近的地方,在邊界,你可以使用當前的位置,而不是面積,它的工作更好一點 –

+0

不,我還沒有找到一個解決方案,它仍然給我所有的位置在世界各地。所以我在我的服務器端處理它以確認位置! –

回答

-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

@在Google Console API上設置你的Api,並實現上面的代碼並在播放清單中重放API密鑰。它會正常工作。 –

+0

你是認真的,這是怎麼回答的? –

+0

@jawad:請試試這個例子。它爲我工作。 –

6

我有與android中的邊界相同的問題。我嘗試了一切,無法解決問題。這些邊界內的

結果偏重,但不限於,地點:

尋找其他的網頁,我想邊界設置爲一個區域的時候發現了這個對JavaScript的文檔。

它看起來像android的地方api文檔不完整。我們將不得不等待。

+0

是的,他們不受限制。 –

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. 將點的座標與當前的座標進行比較,並將它們從最近到最遠排序。
  4. 按顯示排序結果。

它似乎工作更準確,但需要額外的請求和計算。
在我的情況下,我只需要來自2個國家的結果,所以我最終得到了第一個更簡單的解決方案。

相關問題