假设我的应用中有5种不同的活动希望使用LocationClient.getLastLocation()
来获取最后的已知位置。这看起来很简单。
理想情况下,我只想在每个活动中创建一个LocationClient并调用getLastLocation()。但是,要连接到Google Play服务还需要做一些额外的工作,例如致电LocationClient.connect()
并处理onConnected
,onDisconnected
和onConnectionFailed
回调。文档在这里:https://developer.android.com/training/location/retrieve-current.html
据我所知,我的五个不同活动中的每一个都必须处理LocationClient的生命周期方法。他们也无法立即在getLastLocation()
中致电onCreate()
,因为该活动的连接可能尚未确定。
是否有一种简单的方法可以简化LocationClient的生命周期,以便在我为我的应用建立一次连接后,getLastLocation()
可以立即在任何新活动中使用?
答案 0 :(得分:5)
我使用融合位置提供程序API来定期更新位置。我在后台服务中实现了它(例如LocationUpdateService extends Service
)。之前我使用的是Android Location框架API,但它对电池使用效果不佳。融合位置提供商API是有效使用电池的最佳选择。
我还准备了实施它所需的步骤说明(以及其他有用信息)。简单来说,这是目前在Android平台上获取位置数据的最佳方式。 Google Play服务提供了许多位置API来获取位置数据(例如,用户的当前位置,或者您可以说是设备的最后已知位置)。
融合位置提供商是Google Play服务中的位置API之一。 这些是先决条件:
Google Play服务SDK用作库项目(并且Google PlayService也已正确安装在您的设备中)。
GooglePlayServices
库从android google-play-services_lib
导入为Library项目。您应该拥有一个实际设备,因为此API无法在模拟器中使用。
融合位置提供商智能地管理基础定位技术(GPS / Wi-Fi /网络提供商的连接),并根据我们的需求为我们提供最佳位置。
我们可以选择其中一个位置提供商(网络或GPS)并请求位置更新或设置近距离警报。但这种方法存在两个主要问题: 1.如果我们需要定义精确的位置,我们必须在网络和GPS位置提供商之间切换(因为GPS不能在室内工作)。 2.接近警报用于通知用户某个位置的接近程度,这对电池寿命造成了影响。
使用此API的步骤:
在清单文件中声明与位置相关的权限。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
或者
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
实现相关接口和回调。在我们请求位置更新之前,我们必须首先实现位置服务用于向我们的应用程序传达连接状态的接口:
com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks
:指定位置客户端连接或断开连接时Location Services调用的方法。com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener
连接到Google Play服务,将LocationClient
与Google API相关联。为此,请创建LocationClient
对象(GoogleApiClient
的实例):
mLocationClient = new GoogleApiClient.Builder(getApplicationContext())
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
然后拨打mLocationClient.connect();
。
使用FusedLocationProviderApi
类创建LocationServices
的实例:
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
检索onConnected(Bundle bundle)
中的当前位置:
Location currentLocation = fusedLocationProviderApi .getLastLocation(mLocationClient);
if (mCurrentLocation != null) {
Log.d(TAG, "last location = " + mCurrentLocation.getLatitude() +
" - " + mCurrentLocation.getLongitude());
}
创建并设置LocationRequest
对象:
mLocationRequest = new LocationRequest();
private void setLocationParameter() {
// Set the update interval
mLocationRequest.setInterval(Constants.SECONDS_TO_UP);
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest.setFastestInterval(Constants.SECONDS_TO_UP);
// Set the distance to 10 meters.
mLocationRequest.setSmallestDisplacement(Constants.METERS_TO_UP);
}
要从位置服务获取定期位置更新,我们会使用位置客户端发送请求。
LocationListener listener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Utils.locationUpdates = Utils.locationUpdates + 1;
if (Utils.locationUpdates == 1) {
mLocationRequest .setPriority(LocationRequest.PRIORITY_LOW_POWER);
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, listener);
}
}
};
答案 1 :(得分:2)
您可以创建服务以在后台处理融合位置提供程序,并将位置和状态广播到您的活动。请参阅链接https://gist.github.com/blackcj/20efe2ac885c7297a676
答案 2 :(得分:1)
您可以创建一个实现所有这些方法的基本活动,然后您的所有活动只需要扩展它。
答案 3 :(得分:1)
如果您熟悉反应式编程,则必须尝试RxLocation库,该库将Fused API包装为RX方式。
示例:
// Create one instance and share it
RxLocation rxLocation = new RxLocation(context);
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5000);
rxLocation.location().updates(locationRequest)
.flatMap(location -> rxLocation.geocoding().fromLocation(location).toObservable())
.subscribe(address -> {
/* do something */
});