使 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() 并处理 onConnectedonDisconnectedonConnectionFailed 回调。文档在这里: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 服务组件,并将库添加到您的项目中。 从您的开发项目中的 android google-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 - 获得高精度

从 Fused Location Provider 获取 GPS 或网络提供商

如何在 Service 类中使用 Fused Location Provider?