LocationAvailability 没有可用的位置

Posted

技术标签:

【中文标题】LocationAvailability 没有可用的位置【英文标题】:LocationAvailability No Location Available 【发布时间】:2018-05-11 07:02:05 【问题描述】:

Google 的 androidFusedLocationProviderApi 最近在过去几个月内被弃用,FusedLocationProviderClient 是它的继任者,所以我最近更新了客户端应用程序中使用的位置 API 以使用新的 API。

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

    我们不会向最终用户表明任何误报 我们可以尝试解决问题,或者至少向最终用户报告他们应该做什么?

在我看来,要么已弃用的 API 提供了对这些问题的更多洞察,因为它与 GoogleApiClient 结合使用,或者我可能遗漏了一些较小的细节。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题。经过三天的尝试,我开始着手解决它。

我也和你一样要采集前台状态的位置,如果前台服务被破坏了,我还得注销。

我犯的第一个错误是不保证removeLocationUpdates 将在与requestLocationUpdates 相同的线程上运行。实际上,它不必是同一个线程,但是在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 吸引到removeLocationUpdates 中的addOnCompleteListener,以确保removeLocationUpdatesrequestLocationUpdates 后面的调用。如果没有 RxJava,当然会更容易实现。

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

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

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

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

所以我的LocationRequest 看起来像:

LocationRequest.apply 
  priority = PRIORITY_HIGH_ACCURACY
  interval = 10000L

希望我犯的三个错误和解决方法对你有帮助!

【讨论】:

你应该得到这么多的支持。【参考方案2】:

作为official documentation says:

onLocationAvailability 发生变化时调用 位置数据的可用性。 当 isLocationAvailable() 返回时 false 你可以假设位置不会被返回 onLocationResult(LocationResult) 直到 设备的设置或环境。 即使 isLocationAvailable() 返回 true onLocationResult(LocationResult) 可能并不总是 定期调用,但是设备位置是已知的,并且 最近交付的位置和 getLastLocation(GoogleApiClient) 鉴于活动指定的提示,将是合理的最新 位置请求。

所以这个方法没有提供原因信息。

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

    目前我只是忽略此方法的结果,因为它经常返回 false,然后又返回 true,依此类推。

    我们可以尝试解决问题,或者至少向最终用户报告他们应该做什么?

    检查是否启用了定位服务(使用LocationManager.isProviderEnabled()

    检查您是否有权限,如果需要,请求他们 (docs)

【讨论】:

【参考方案3】:

我通过调用这段代码来过滤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)
            
        

【讨论】:

【参考方案4】:

正如谷歌文档所说:

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

因此,您可以假设位置可能不可用,不仅是因为禁用了位置设置,还因为信号强度,或者卫星不可见或其他原因,它只是表明您将不会收到位置更新,直到发生变化.您可以向用户显示有关它的通知,例如“我们无法获取您的位置,请尝试启用位置设置”

【讨论】:

【参考方案5】:

我遇到了同样的问题,同时我看到设备上已启用位置服务,并且我的应用程序已允许用户授予权限。

我还是看到了

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

问题是手机上的 Location 项内有额外的偏好。我们必须选择省电/高精度选项。请查看提供的屏幕截图:

【讨论】:

以上是关于LocationAvailability 没有可用的位置的主要内容,如果未能解决你的问题,请参考以下文章

CentOS 没有可用软件包 libmcrypt

centos7nettools没有可用的软件包

避免在数据表中呈现“表中没有可用数据”

没有可用的来源..浏览以查找来源

国内都有哪些靠谱的 Javascript 库 CDN可用

没有可用的缓冲空间