LocationAvailability无可用位置

时间:2017-11-27 22:48:39

标签: android google-api

Google的FusedLocationProviderApi for Android最近在过去几个月内被弃用,其中FusedLocationProviderClient是其继任者,因此我最近更新了客户端应用中使用的位置API使用新的。

每次在onLocationAvailability中触发LocationCallback时,locationAvailability.isLocationAvailable()会在false返回Service时通知用户,但这种情况似乎比我在某些设备上预期的更频繁。我在前台GoogleApiClient内运行这些位置更新,这些位置更新保持一致至关重要。有没有办法确定这种失败的原因所以

  1. 我们没有向最终用户表明任何误报
  2. 我们可以尝试解决问题,或者至少向最终用户报告他们应该做什么?
  3. 在我看来,不推荐使用的API可以提供对这些问题的更深入了解,因为它与var a = new { MinY = pts.Min(p => p.Y), MaxY = pts.Max(p => p.Y), MinX = pts.Min(p => p.X), MaxX = pts.Max(p => p.X) }; 一起使用,或者我错过了一些较小的细节。

5 个答案:

答案 0 :(得分:2)

official documentation says

  

onLocationAvailability ,当   位置数据的可用性。 何时isLocationAvailable()返回   假,您可以假设不会返回该位置   onLocationResult(LocationResult),直到   设备的设置或环境。即使isLocationAvailable()   返回true,onLocationResult(LocationResult)可能并不总是   定期调用,但是设备位置已知并且   最近传送的位置和getLastLocation(GoogleApiClient)   会根据活动者指定的提示合理更新   LocationRequests。

因此,此方法不提供有关原因的信息。

  1. 我们不会向最终用户表明任何误报

    • 当前,我只是忽略此方法的结果,因为它经常返回false,然后再次返回true,依此类推。
  2. 我们可以尝试解决问题,或者至少向最终用户报告他们应该做什么?

答案 1 :(得分:1)

如Google文档所述:

  

当isLocationAvailable()返回false时,您可以假定该位置   直到onLocationResult(LocationResult)都不会返回   设备的设置或环境发生了一些变化。

因此,您可以假定位置可能不可用,不仅是因为位置设置被禁用,还因为信号强度,或者卫星不可见或其他原因,它只是表明您不会接收位置更新,除非发生某些更改。您可以使用诸如“我们无法获取您的位置,请尝试启用位置设置”之类的内容向用户显示通知

答案 2 :(得分:1)

我遇到了同样的问题。经过三天的尝试后,我开始努力。

我还必须像您一样收集处于前台状态的位置,如果前台服务被破坏,则必须注销。

我犯的第一个错误是不保证removeLocationUpdatesrequestLocationUpdates在同一线程上运行。实际上,它不必是同一线程,但是在requestLocationUpdates之后,必须调用removeLocationUpdates使下一个requestLocationUpdates有效。为确保这一点,在同一线程上工作要容易得多。

例如:

  private fun FusedLocationProviderClient.requestLocation(
      request: LocationRequest
  ): Single<LocationResult> {
    return Single.create<LocationResult> { emitter ->
      requestLocationUpdates(request, object : LocationCallback() {
        override fun onLocationResult(result: LocationResult?) {
          removeLocationUpdates(object : LocationCallback() {})
              .addOnCompleteListener {
                if (emitter.isDisposed) {
                  info("onLocationResult called after disposing.")
                  return@addOnCompleteListener
                }

                if (result != null && result.locations.isNotEmpty()) {
                  onSuccess(result)
                } else {
                  onError(RuntimeException("Invalid location result"))
                }
              }
        }

        private fun onError(error: Exception) {
          if (!emitter.isDisposed) {
            emitter.onError(error)
          }
        }

        private fun onSuccess(item: LocationResult) {
          if (!emitter.isDisposed) {
            emitter.onSuccess(item)
          }
        }

      }, Looper.getMainLooper())
    }
  }

如代码所示,我已经将Single的emitter吸引到addOnCompleteListener中的removeLocationUpdates上,以确保在removeLocationUpdates之后调用requestLocationUpdates。当然,如果没有RxJava,将更易于实现。

我犯的第二个错误是interval中的LocationRequest设置错误。根据文档:

  

此方法以毫秒为单位设置您的应用希望接收位置更新的速率。请注意,位置更新可能会比此速度快一些或慢一些,以优化电池使用量,或者可能根本没有更新(例如,如果设备没有连接)。

这种解释是毫无根据的,但是最终,如果您调用一次requestLocationUpdates,则必须在下一个interval之前有一个由requestLocationUpdates触发的位置更新事件。找到这个错误最困难。

我犯的第三个错误是在LocationRequest中设置了错误的priority。在API 10及以下版本中,它不是PRIORITY_BALANCED_POWER_ACCURACY,但是可以通过使用PRIORITY_HIGH_ACCURACY来解决。在这种情况下,我仅在仿真器上进行了测试,因此实际设备可能会有不同的结果。我猜PRIORITY_BALANCED_POWER_ACCURACY似乎不能正常工作,因为该模拟器不提供蓝牙硬件。

所以我的LocationRequest如下:

LocationRequest.apply {
  priority = PRIORITY_HIGH_ACCURACY
  interval = 10000L
}

我希望我犯的三个错误和解决方案对您有所帮助!

答案 3 :(得分:0)

我遇到了同样的问题,并且同一时间我看到设备上的位置服务已启用,并且我的ap允许了用户的权限。

我仍然看到

com.google.android.gms.location.LocationCallback#onLocationAvailability LocationAvailability[isLocationAvailable: false]

问题在于电话上的位置项内还有其他偏好设置。我们必须选择节电/高精度选项。请查看提供的屏幕截图:

The issue detection cause

答案 4 :(得分:0)

我通过调用这段代码来过滤locationAvailability.isLocationAvailable()的误报,以检查是否启用了定位服务。

fun isLocationEnabled(): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
            lm.isLocationEnabled
        } else {
            val mode = Settings.Secure.getInt(
                context.contentResolver, Settings.Secure.LOCATION_MODE,
                Settings.Secure.LOCATION_MODE_OFF
            )
            mode != Settings.Secure.LOCATION_MODE_OFF
        }
    }
override fun onLocationAvailability(p0: LocationAvailability?) {
            if (isLocationEnabled().not()) {
                locationUpdateSubject.failed(LocationAvailabilityError)
            }
        }