使 Fused Location Provider LocationClient 更易于使用
Posted
技术标签:
【中文标题】使 Fused Location Provider LocationClient 更易于使用【英文标题】:Making the Fused Location Provider LocationClient easier to use 【发布时间】:2014-01-24 13:32:53 【问题描述】:假设我的应用中有 5 个不同的活动希望使用 LocationClient.getLastLocation()
来获取最后一个已知位置。这看起来很简单。
理想情况下,我会在每个活动中创建一个 LocationClient 并调用 getLastLocation()。但是,连接到 Google Play 服务还需要做一些额外的工作,例如调用 LocationClient.connect()
并处理 onConnected
、onDisconnected
和 onConnectionFailed
回调。文档在这里:https://developer.android.com/training/location/retrieve-current.html
据我所知,我的五个不同活动中的每一个都必须处理 LocationClient 的生命周期方法。他们也不能立即在onCreate()
中呼叫getLastLocation()
,因为该活动的连接可能尚未建立。
有没有一种简单的方法可以简化 LocationClient 的生命周期,以便在我为我的应用建立一次连接后,getLastLocation()
将立即在任何新活动中工作?
【问题讨论】:
你找到这个问题的解决方案了吗? 【参考方案1】:我已使用融合位置提供程序 API 来获取定期位置更新。我已经在后台服务中实现了它(例如LocationUpdateService extends Service
)。早些时候我使用的是 Android Location 框架 API,但它不利于电池使用。 Fused Location Provider API 是高效使用电池的最佳选择。
我还准备了实施它所需的步骤说明(以及其他有用的信息)。简而言之,这是目前在Android平台上获取位置数据的最佳方式。 Google Play 服务提供了许多位置 API 来获取位置数据(例如用户的当前位置,或者您可以说设备的最后一个已知位置)。
Fused Location Provider 是 Google Play 服务中的位置 API 之一。 这些是先决条件:
Google Play 服务 SDK 用作库项目(Google PlayService 也已正确安装在您的设备中)。
从 SDK 管理器下载并安装 Google Play 服务组件,并将库添加到您的项目中。 从您的开发项目中的 androidgoogle-play-services_lib
导入 GooglePlayServices
库作为库项目。
你应该有一个实际的设备,因为这个 API 在模拟器中不起作用。
Fused Location Provider 智能管理底层定位技术(GPS/Wi-Fi/网络提供商的连接),并根据我们的需要为我们提供最佳位置。
为什么要使用它
我们可以选择其中一个位置提供商(网络或 GPS)并请求位置更新或设置邻近警报。但是这种方法有两个主要问题: 1. 如果我们需要定义精确的位置,我们必须在网络和 GPS 位置提供者之间切换(因为 GPS 不能在室内工作)。 2. 接近警报用于通知用户接近某个位置,这会影响电池寿命。
好处
-
简单的 API:我们可以指定“高精度”或“低功耗”等高级需求,而不必担心位置提供者。
电池高效:它最大限度地减少了应用程序的电力使用。根据所有传入的位置请求和可用传感器,融合位置提供者选择最有效的方式来满足这些需求。
使用此 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
:指定位置服务在连接或断开位置客户端时调用的方法。
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();
。
使用LocationServices
类创建FusedLocationProviderApi
的实例:
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);
;
【讨论】:
这并没有回答有关如何以更智能的方式跨不同活动管理 LocationServices 的问题。【参考方案2】:您可以创建一个服务来在后台处理融合的位置提供程序,并将位置和状态广播到您的活动。参考链接https://gist.github.com/blackcj/20efe2ac885c7297a676
【讨论】:
【参考方案3】:您可以创建一个实现所有这些方法的基础活动,然后您的所有活动只需要扩展它。
供参考检查:android how to create my own Activity and extend it?
【讨论】:
并没有解决在onCreate() 中能够立即调用getLastLocation() 的问题。每个活动仍然需要等待 onConnected 回调才能使用 getLastLocation() @emmby 您必须以某种方式管理生命周期...您是否考虑过将片段与单个活动一起使用?根据您在每个活动中所做的事情,这可能不起作用,但如果确实如此,这将允许您管理其所有子片段的生命周期【参考方案4】:如果你熟悉响应式编程,你必须尝试 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 */
);
【讨论】:
以上是关于使 Fused Location Provider LocationClient 更易于使用的主要内容,如果未能解决你的问题,请参考以下文章
使用 Fused Location Provider 查找位置源
Fused Location Provider 是不错的选择吗?
使用 Location Manager 和 Fused Location Provider Api 获取位置有啥区别?
Fused Location Provider - 获得高精度