【问题标题】:Making the Fused Location Provider LocationClient easier to use使 Fused Location Provider LocationClient 更易于使用
【发布时间】: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() 将立即在任何新活动中工作?

【问题讨论】:

  • 你找到这个问题的解决方案了吗?

标签: android geolocation location google-play


【解决方案1】:

我已使用融合位置提供程序 API 来获取定期位置更新。我已经在后台服务中实现了它(例如LocationUpdateService extends Service)。早些时候我使用的是 Android Location 框架 API,但它不利于电池使用。 Fused Location Provider API 是高效使用电池的最佳选择。

我还准备了实施它所需的步骤说明(以及其他有用的信息)。简而言之,这是目前在Android平台上获取位置数据的最佳方式。 Google Play 服务提供了许多位置 API 来获取位置数据(例如用户的当前位置,或者您可以说设备的最后一个已知位置)。

Fused Location Provider 是 Google Play 服务中的位置 API 之一。 这些是先决条件:

  1. Google Play 服务 SDK 用作库项目(Google PlayService 也已正确安装在您的设备中)。

    • 从 SDK 管理器下载并安装 Google Play 服务组件,并将库添加到您的项目中。
    • 从您的开发项目中的 android google-play-services_lib 导入 GooglePlayServices 库作为库项目。
  2. 你应该有一个实际的设备,因为这个 API 在模拟器中不起作用。

Fused Location Provider 智能管理底层定位技术(GPS/Wi-Fi/网络提供商的连接),并根据我们的需要为我们提供最佳位置。

为什么要使用它

我们可以选择其中一个位置提供商(网络或 GPS)并请求位置更新或设置邻近警报。但是这种方法有两个主要问题: 1. 如果我们需要定义精确的位置,我们必须在网络和 GPS 位置提供者之间切换(因为 GPS 不能在室内工作)。 2. 接近警报用于通知用户接近某个位置,这会影响电池寿命。

好处

  1. 简单的 API:我们可以指定“高精度”或“低功耗”等高级需求,而不必担心位置提供者。
  2. 电池高效:它最大限度地减少了应用程序的电力使用。根据所有传入的位置请求和可用传感器,融合位置提供者选择最有效的方式来满足这些需求。

使用此 API 的步骤:

  1. 在清单文件中声明位置相关权限。

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    

    或者

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    
  2. 实现相关的接口和回调。在我们请求位置更新之前,我们必须首先实现位置服务用来向我们的应用传达连接状态的接口:

    • com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks:指定位置服务在连接或断开位置客户端时调用的方法。
    • com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener
  3. 连接到 Google Play 服务,将 LocationClient 连接到 Google API。为此,请创建一个LocationClient 对象(GoogleApiClient 的实例):

    mLocationClient = new GoogleApiClient.Builder(getApplicationContext())
        .addApi(LocationServices.API).addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this).build();
    

    然后拨打mLocationClient.connect();

  4. 使用LocationServices 类创建FusedLocationProviderApi 的实例:

    private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
    
  5. 检索onConnected(Bundle bundle)中的当前位置:

    Location currentLocation = fusedLocationProviderApi                                  .getLastLocation(mLocationClient);
    if (mCurrentLocation != null) {
        Log.d(TAG, "last location = " + mCurrentLocation.getLatitude() +
            " - " + mCurrentLocation.getLongitude());
    }           
    
  6. 创建并设置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);
    }
    
  7. 为了从位置服务获取定期位置更新,我们使用位置客户端发送请求。

    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 */
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 2015-08-17
      相关资源
      最近更新 更多