Google的FusedLocationProviderApi
for Android最近在过去几个月内被弃用,其中FusedLocationProviderClient
是其继任者,因此我最近更新了客户端应用中使用的位置API使用新的。
每次在onLocationAvailability
中触发LocationCallback
时,locationAvailability.isLocationAvailable()
会在false
返回Service
时通知用户,但这种情况似乎比我在某些设备上预期的更频繁。我在前台GoogleApiClient
内运行这些位置更新,这些位置更新保持一致至关重要。有没有办法确定这种失败的原因所以
在我看来,不推荐使用的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)
};
一起使用,或者我错过了一些较小的细节。
答案 0 :(得分:2)
onLocationAvailability ,当 位置数据的可用性。 何时isLocationAvailable()返回 假,您可以假设不会返回该位置 onLocationResult(LocationResult),直到 设备的设置或环境。即使isLocationAvailable() 返回true,onLocationResult(LocationResult)可能并不总是 定期调用,但是设备位置已知并且 最近传送的位置和getLastLocation(GoogleApiClient) 会根据活动者指定的提示合理更新 LocationRequests。
因此,此方法不提供有关原因的信息。
我们不会向最终用户表明任何误报
我们可以尝试解决问题,或者至少向最终用户报告他们应该做什么?
检查是否启用了定位服务(使用LocationManager.isProviderEnabled())
检查您是否具有权限,如果需要,请请求权限(docs)
答案 1 :(得分:1)
如Google文档所述:
当isLocationAvailable()返回false时,您可以假定该位置 直到onLocationResult(LocationResult)都不会返回 设备的设置或环境发生了一些变化。
因此,您可以假定位置可能不可用,不仅是因为位置设置被禁用,还因为信号强度,或者卫星不可见或其他原因,它只是表明您不会接收位置更新,除非发生某些更改。您可以使用诸如“我们无法获取您的位置,请尝试启用位置设置”之类的内容向用户显示通知
答案 2 :(得分: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
吸引到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]
问题在于电话上的位置项内还有其他偏好设置。我们必须选择节电/高精度选项。请查看提供的屏幕截图:
答案 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)
}
}