Android 地点自动完成设置经纬度范围
Android Places Autocomplete set lat long bounds
我正在使用 Google 个地方自动完成 API。我的应用程序有一个自动完成文本视图。一切正常,因为我按照示例 here 进行操作。
唯一的问题是我将 LatLng 范围设置为山景城的范围。
private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(
new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));
我的GoogleApiClient
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Places.GEO_DATA_API)
.build();
当我尝试输入新奥尔良的地址时,我必须输入很多内容,这对于任何不在 CA 的用户来说都不是很好的体验。有没有更好的方法来根据当前位置设置 LatLng 边界,而无需请求位置权限或精确位置。我假设这不是 Places API 的限制,而是我有限的知识。
提前致谢。
很遗憾,您需要位置权限,因为您在清单中选择的权限决定了 Google API 客户端返回的位置的准确性。我建议使用 ACCESS_COARSE_LOCATION,它在 1 个城市街区内是准确的。这是我如何动态获取用户的位置并进行大约的限制。他们所在位置周围 5 英里半径范围内。
public class PlacesSearchActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,GoogleApiClient.ConnectionCallbacks, LocationListener {
private String TAG = this.toString();
protected GoogleApiClient mGoogleApiClient;
private AutoCompleteTextView mAutocompleteView;
private PlaceAutocompleteAdapter mAdapter;
private LocationRequest mLocationRequest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_places_search);
// 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)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.enableAutoManage(this, 0 /* clientId */, this)
.addApi(Places.GEO_DATA_API)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_LOW_POWER)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
// 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);
}
private void setBounds(Location location, int mDistanceInMeters ){
double latRadian = Math.toRadians(location.getLatitude());
double degLatKm = 110.574235;
double degLongKm = 110.572833 * Math.cos(latRadian);
double deltaLat = mDistanceInMeters / 1000.0 / degLatKm;
double deltaLong = mDistanceInMeters / 1000.0 / degLongKm;
double minLat = location.getLatitude() - deltaLat;
double minLong = location.getLongitude() - deltaLong;
double maxLat = location.getLatitude() + deltaLat;
double maxLong = location.getLongitude() + deltaLong;
Log.d(TAG,"Min: "+Double.toString(minLat)+","+Double.toString(minLong));
Log.d(TAG,"Max: "+Double.toString(maxLat)+","+Double.toString(maxLong));
// 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, new LatLngBounds(new LatLng(minLat, minLong), new LatLng(maxLat, maxLong)), null);
mAutocompleteView.setAdapter(mAdapter);
}
/**
* 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);
Toast.makeText(getApplicationContext(), "Clicked: " + item.description,
Toast.LENGTH_SHORT).show();
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);
Log.i(TAG, "Place details received: " + place.getName());
places.release();
}
};
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
@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();
}
@Override
public void onLocationChanged(Location location) {
setBounds(location,5500);
}
@Override
public void onConnected(Bundle bundle) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} else {
setBounds(location,5500);
}
}
@Override
public void onConnectionSuspended(int i) {
}
}
如果有人正在寻找答案,@opt05 并不完全正确,如果我们实施 com.google.maps.android:android-maps-utils
,我们可以只使用 SphericalUtil.ComputeOffset
来获得
north corner
还有一个
south corner
并通过 autocompletefilter
设置界限。
一个完整的例子是:
LatLng center = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
LatLng northSide = SphericalUtil.computeOffset(center, 50000, 0);
LatLng southSide = SphericalUtil.computeOffset(center, 50000, 180);
LatLngBounds bounds = LatLngBounds.builder()
.include(northSide)
.include(southSide)
.build();
placeLocation.setBoundsBias(bounds);
placeLocation.setFilter(typeFilter);
placeDestination.setBoundsBias(bounds);
placeDestination.setFilter(typeFilter);
这里 placeLocation
是 AutoCompleteFragment
北侧和南侧方法 computeOffset
是
(您当前所在的中心位置或您想限制的任何位置"Put a radius on" 在您的情况下它是 moutainview)
(50,000 是以米为单位的距离)
(0 为北,90 为东,180 为南,270 为西)。
我正在使用 Google 个地方自动完成 API。我的应用程序有一个自动完成文本视图。一切正常,因为我按照示例 here 进行操作。
唯一的问题是我将 LatLng 范围设置为山景城的范围。
private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(
new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));
我的GoogleApiClient
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Places.GEO_DATA_API)
.build();
当我尝试输入新奥尔良的地址时,我必须输入很多内容,这对于任何不在 CA 的用户来说都不是很好的体验。有没有更好的方法来根据当前位置设置 LatLng 边界,而无需请求位置权限或精确位置。我假设这不是 Places API 的限制,而是我有限的知识。
提前致谢。
很遗憾,您需要位置权限,因为您在清单中选择的权限决定了 Google API 客户端返回的位置的准确性。我建议使用 ACCESS_COARSE_LOCATION,它在 1 个城市街区内是准确的。这是我如何动态获取用户的位置并进行大约的限制。他们所在位置周围 5 英里半径范围内。
public class PlacesSearchActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,GoogleApiClient.ConnectionCallbacks, LocationListener {
private String TAG = this.toString();
protected GoogleApiClient mGoogleApiClient;
private AutoCompleteTextView mAutocompleteView;
private PlaceAutocompleteAdapter mAdapter;
private LocationRequest mLocationRequest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_places_search);
// 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)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.enableAutoManage(this, 0 /* clientId */, this)
.addApi(Places.GEO_DATA_API)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_LOW_POWER)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
// 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);
}
private void setBounds(Location location, int mDistanceInMeters ){
double latRadian = Math.toRadians(location.getLatitude());
double degLatKm = 110.574235;
double degLongKm = 110.572833 * Math.cos(latRadian);
double deltaLat = mDistanceInMeters / 1000.0 / degLatKm;
double deltaLong = mDistanceInMeters / 1000.0 / degLongKm;
double minLat = location.getLatitude() - deltaLat;
double minLong = location.getLongitude() - deltaLong;
double maxLat = location.getLatitude() + deltaLat;
double maxLong = location.getLongitude() + deltaLong;
Log.d(TAG,"Min: "+Double.toString(minLat)+","+Double.toString(minLong));
Log.d(TAG,"Max: "+Double.toString(maxLat)+","+Double.toString(maxLong));
// 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, new LatLngBounds(new LatLng(minLat, minLong), new LatLng(maxLat, maxLong)), null);
mAutocompleteView.setAdapter(mAdapter);
}
/**
* 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);
Toast.makeText(getApplicationContext(), "Clicked: " + item.description,
Toast.LENGTH_SHORT).show();
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);
Log.i(TAG, "Place details received: " + place.getName());
places.release();
}
};
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
@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();
}
@Override
public void onLocationChanged(Location location) {
setBounds(location,5500);
}
@Override
public void onConnected(Bundle bundle) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} else {
setBounds(location,5500);
}
}
@Override
public void onConnectionSuspended(int i) {
}
}
如果有人正在寻找答案,@opt05 并不完全正确,如果我们实施 com.google.maps.android:android-maps-utils
,我们可以只使用 SphericalUtil.ComputeOffset
来获得
north corner
还有一个
south corner
并通过 autocompletefilter
设置界限。
一个完整的例子是:
LatLng center = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
LatLng northSide = SphericalUtil.computeOffset(center, 50000, 0);
LatLng southSide = SphericalUtil.computeOffset(center, 50000, 180);
LatLngBounds bounds = LatLngBounds.builder()
.include(northSide)
.include(southSide)
.build();
placeLocation.setBoundsBias(bounds);
placeLocation.setFilter(typeFilter);
placeDestination.setBoundsBias(bounds);
placeDestination.setFilter(typeFilter);
这里 placeLocation
是 AutoCompleteFragment
北侧和南侧方法 computeOffset
是
(您当前所在的中心位置或您想限制的任何位置"Put a radius on" 在您的情况下它是 moutainview)
(50,000 是以米为单位的距离)
(0 为北,90 为东,180 为南,270 为西)。