【问题标题】:Fused Location Provider unexpected behavior融合位置提供程序意外行为
【发布时间】:2014-11-29 19:05:27
【问题描述】:

这是我注册我的应用以接收位置更新的方式:

mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);

Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);

mGoogleApiClient = builder.addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

mGoogleApiClient.connect();

....
....

@Override
public void onConnected(Bundle connectionHint) {
   LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}

我的待定意图几乎在确切请求的时间间隔内在后台被调用...

到目前为止一切顺利。

问题:当 WIFI 被禁用/未连接到任何网络,或者没有启用 3G/4G 网络数据时 - 融合的位置提供程序不提供新的位置更新!!

我的位置信息访问设置已打开,并检查了 GPS 卫星和 WI-FI 和移动网络位置。

更大的问题:有时在这种情况下,我确实会通过挂起的意图收到位置更新回调,但它知道的最后一个位置(即使是一个小时前,而且我离那个地方好远好远)

根据PRIORITY_BALANCED_POWER_ACCURACY的文档:

与 setPriority(int) 一起使用以请求“块”级别的准确性。 块级精度被认为是大约 100 米的精度。使用这样的粗略精度通常会消耗更少的功率。

我希望融合位置提供者在别无选择时会打开 GPS,或者如果他没有任何其他选择,至少不会提供新的位置更新。

另一个不可预测和令人不安的问题:

我将 PRIORITY_BALANCED_POWER_ACCURACY 更改为 PRIORITY_HIGH_ACCURACY 以查看它的行为(24 小时)。所有间隔保持不变(更新之间的间隔为 10 分钟)。即使在没有网络/SIM 卡的手机中也确实收到了准确的位置,但是 - 电池很快耗尽了!当我查看电池历史记录时,我很惊讶地发现 GPS 无线电一直处于全传输模式!!!! 而且我还在日志中看到每分钟都会收到位置信息,甚至我每十分钟请求一次位置(我没有任何其他安装的应用程序可以打开 GPS 来接收位置..)

我在几台设备(例如 Moto X 2013、HTC One X、Nexus 5)上注意到了这种行为,所有设备都使用最新的 Google Play 服务(版本 6.1.11)和 android KITKAT 4.4.4

我的应用程序很大程度上依赖于用户当前的位置,只要用户登录,就会在指定的时间间隔内定期接收位置更新,所以我不想使用PRIORITY_HIGH_ACCURACY 模式,以防止电池耗尽。 .

我的问题:

  • 如果融合位置提供商设置为接收PRIORITY_BALANCED_POWER_ACCURACY 的更新并且没有任何 WI-FI 或手机信号塔信息,它是否应该使用 GPS?

  • 如果是这样,那我做错了什么?

  • 为什么我会收到这种不正确的误导性位置更新? (正如我在“更大的问题”部分中解释的那样..

  • 当我使用PRIORITY_HIGH_ACCURACY 参数时,为什么 GPS 无线电一直打开而不是 10 分钟间隔打开? (我没有其他可以更快触发位置更新的已安装应用程序..)

【问题讨论】:

    标签: android gps google-play-services android-location location-services


    【解决方案1】:

    对于指定的问题,

    1. 是融合位置提供程序,如果它设置为使用PRIORITY_BALANCED_POWER_ACCURACY 接收更新并且没有任何 WI-FI 或手机信号塔信息? &
    2. 如果是这样,那我做错了什么?

    显然,在文档中的任何地方都没有明确指定唯一的来源。使用任一PRIORITY 选项,即使通过代码,获得的location 的“来源”也是“融合”的。
    [location.getProvider() 返回 :"fused"]
    我看到只有在LocationRequest 具有 PRIORITY_HIGH_ACCURACY 时才使用 GPS。所以它在其他条件下不使用 GPS。

    4.当我使用 PRIORITY_HIGH_ACCURACY 参数时,为什么 GPS 无线电一直打开而不是 10 分钟间隔打开? (我没有其他安装的应用程序可以更快地触发位置更新..)

    最快间隔已设置为 1 分钟。据我了解,当最快间隔的值比 setInterval 的值更短时,setFastestInterval 优先于 setInterval
    就你而言,1 分钟对 10 分钟。
    关于没有安装其他触发位置更新的应用程序,它只是作为示例给出,并没有明确说明只有这种情况。

    这控制了您的申请将收到的最快速度 位置更新,在某些情况下可能比 setInterval(long) 更快 情况(例如,如果其他应用程序正在触发位置 更新)。

    所以,PRIORITY_HIGH_ACCURACY 会发生什么情况,它通过使用 GPS(有点独占)以最快的间隔设置 - 1 分钟请求location

    3.为什么我会收到这种不正确的误导性位置更新? (正如我在“更大的问题”部分中解释的那样..

    还需要检查pendingIntent 机制的代码。尽管可能需要注意一些事项:
    您可以添加location.getTime() 以确保和验证获取位置的时间。如果范围内没有 wifi 信号塔并且使用了PRIORITY_BALANCED_POWER_ACCURACY,则很可能没有更新。
    首先,在调用“lastKnown”时使用的块级位置精度无济于事。

    电池消耗是由于 GPS 和 1 分钟更新的组合。尝试将最快的时间间隔设置为 5 或 10 分钟,如果这适合您的实施,但如果您需要绝对准确的位置,PRIORITY_BALANCED_POWER 可能无济于事。我通常会检查在onLocationChanged 中获得的位置,并根据它在LocationRequest 中切换优先级。当然,它通常有助于获得位置,除非我在没有 GPS 视线的建筑物内,并且 Wifi 网络已关闭。

    【讨论】:

    • 谢谢。当我更改最快的间隔以及您提到的所有其他点时,我将检查事情的表现。如果它真的像那样工作 - 我会很高兴回来奖励你的答案
    • 当然,没问题,也可以在独立位置的应用程序中尝试没有视线的高精度,它可能不会返回任何更新的准确位置..只是为了确保行为跨度>
    • 这可能会有所帮助,它的one of the better answers for why GPS uses so much battery,仍然需要检查特定的移动应用程序上下文,我会尝试要求用户根据他/她何时需要准确的位置来启用/禁用它,这种方式不会使其成为强制性的,我猜对你的情况不起作用(考虑到一致的要求)
    • 这些解释对于像我这样的新开发者非常有帮助。与位置管理器/GPS 提供商/网络提供商等相比,我发现新的 Fused 位置界面非常好......但是我的应用程序中遇到了同样的问题和问题非常感谢。
    • 要么问题被删除,要么链接问题...找不到页面
    【解决方案2】:

    我建议您将AlarmManagerFusedLocationProvider 一起使用,这样您的AlarmManager 火警每10 分钟就会发出一次警报,以便开始位置更新。

    获取更新的位置后,断开位置客户端。您不需要通过在LocationRequest 中设置间隔时间来让它一直运行,而是可以使用AlarmManager 在每个时间间隔上调用该进程。

    在这种机制下,您将获得以下好处来解决您的问题:

    • GPS 无线电在检索位置时只会保持打开几秒钟,因为您将在获得第一次位置更新后断开连接。因此 GPS 收音机不会一直保持打开状态,从而节省电池电量。
    • 您将能够每 10 分钟获得一次新位置,而不会弄乱旧位置或其他东西。

    希望对你有所帮助。

    【讨论】:

    • 其实我想过做这样的事情。它可能有效,但是 - 这是我更愿意避免的解决方法。
    • @TalKanel:AFAIK,这是行不通的。它是一种替代方法。当您开发一些专门用于导航地图等的应用程序时,您可以继续当前的方法,当用户使用它时,这些应用程序将一直显示在屏幕上。如果它不是导航类的应用程序,那么 AlarmManager 就是要走的路。
    • 每十分钟连接到 google play 服务 (IPC) 以注册和请求一次位置,这听起来像是一种糟糕的方法。你不这么认为吗?我可能错了..请启发我
    • @TalKanel:您应该执行测试运行。我想我的方法会更加用户友好,并且不会消耗太多电池,因为它不会让 GPS 无线电保持 24x7 全天候运行。您肯定会看到巨大的性能差异。除此之外,如果可能的话,我会坚持让你给用户一些选项来改变位置检索的频率。
    • @TalKanel,在 mehul joisar 的方法中,由于使用警报管理器,电池消耗会增加,但它更可靠,因为如果我们想在后台定期更新位置,我们可能会使用服务,但此服务可能会被 android 停止,因此唯一可能的选择是使用警报管理器定期调用一次服务。
    【解决方案3】:

    手机信号塔覆盖数英里的区域,因此它们不是获取位置的最佳选择。在处理位置时查看位置准确性。

    @Override
    public void onLocationChanged(Location location) {
        //it happens
        if (location == null) {
            return;
        }
        // all locations should have an accuracy
        if (!location.hasAccuracy()) {
            return;
        }
        // if its not accurate enough don't use it
        // this value is in meters
        if (location.getAccuracy() > 200) {
            return;
        }
    }
    

    您可以在网络状态上放置一个广播接收器,当没有连接时,您可以使用 priority_high_accuracy 重新启动您的位置提供程序,这将仅在用户启用 GPS 时使用 GPS,否则它会退回到 wifi 和手机信号塔。

    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    
    /** Checks whether the device currently has a network connection */
    
    private boolean isDeviceOnline() {
        ConnectivityManager connMgr = (ConnectivityManager) activity
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        }
        return false;
    }
    

    【讨论】:

      【解决方案4】:

      要更新 GPS 坐标,您也可以使用 GPS 和 WI-FI 提供商。对于位置的更新,以及最小距离参数。我会给你提供一个小型 GPS 服务示例。

      答案:

      1) PRIORITY_BALANCED_POWER_ACCURACY 请not 使用 GPS。

      2) 使用 GPS 和 WI-FI 检测位置。

      3) PRIORITY_BALANCED_POWER_ACCURACY 可能是因为该地区没有 WI-FI。

      代码示例:

      public class GPSservice extends Service implements LocationListener {
      
      
          private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;
      
          private static final long MIN_TIME_BW_UPDATES = 1000 * 1;
      
          double latitude, longitude;
      
          boolean isGPSEnabled = false;
      
          boolean isNetworkEnabled = false;
      
          boolean canGetLocation = false;
      
          Location location;
      
          protected LocationManager locationManager;
      
          @Override
          public IBinder onBind(Intent intent) {
              return null;
          }
      
      
          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
      
              getLocation();
      
              return super.onStartCommand(intent, flags, startId);
          }
      
      
          @Override
          public void onLocationChanged(Location location) {
              new LocationReceiver(location, getApplicationContext());
          }
      
      
          @Override
          public void onStatusChanged(String provider, int status, Bundle extras) {
      
          }
      
          @Override
          public void onProviderEnabled(String provider) {
      
          }
      
          @Override
          public void onProviderDisabled(String provider) {
      
          }
      
          public Location getLocation() {
              try {
                  locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
      
                  // getting GPS status
                  isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
      
                  isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
      
                  if (!isGPSEnabled && !isNetworkEnabled) {
                      Log.d("Network", "NO network");
                  } else {
                      this.canGetLocation = true;
                      if (isNetworkEnabled) {
                          locationManager.requestLocationUpdates(
                                  LocationManager.NETWORK_PROVIDER,
                                  MIN_TIME_BW_UPDATES,
                                  MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                          Log.d("Network", "Network");
                          if (locationManager != null) {
                              location = locationManager
                                      .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                              if (location != null) {
                                  latitude = location.getLatitude();
                                  longitude = location.getLongitude();
                              }
                          }
                      }
                      if (isGPSEnabled) {
                          if (location == null) {
                              locationManager.requestLocationUpdates(
                                      LocationManager.GPS_PROVIDER,
                                      MIN_TIME_BW_UPDATES,
                                      MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                              Log.d("GPS Enabled", "GPS Enabled");
                              if (locationManager != null) {
                                  location = locationManager
                                          .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                                  if (location != null) {
                                      latitude = location.getLatitude();
                                      longitude = location.getLongitude();
                                  }
                              }
                          }
                      }
                  }
      
              } catch (Exception e) {
                  e.printStackTrace();
              }
      
              return location;
          }
      }
      

      【讨论】:

      • “PRIORITY_BALANCED_POWER_ACCURACY 不使用 GPS” - 我在帖子中没有看到您提供的任何证据证明是这种情况。那里的人写道,他只认为这就是它的意思。另外,我知道我可以明确使用 LocationManager,但我想使用推荐的位置服务 API
      • 自己做个小研究,用wifi和gps试试看结果。
      猜你喜欢
      • 2015-11-01
      • 2013-08-02
      • 2013-09-01
      • 1970-01-01
      • 2017-07-01
      • 2016-09-20
      • 2014-09-05
      • 1970-01-01
      • 2019-07-28
      相关资源
      最近更新 更多