LocationAvailability 没有可用的位置
Posted
技术标签:
【中文标题】LocationAvailability 没有可用的位置【英文标题】:LocationAvailability No Location Available 【发布时间】:2018-05-11 07:02:05 【问题描述】:Google 的 android 版 FusedLocationProviderApi
最近在过去几个月内被弃用,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
,以确保removeLocationUpdates
在requestLocationUpdates
后面的调用。如果没有 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 没有可用的位置的主要内容,如果未能解决你的问题,请参考以下文章