如何正确处理位置服务切换
How to properly handle location service toggling
在我的应用程序中,我有一个使用 FusedLocationProviderClient 获取用户当前位置的按钮。这可以正常工作,直到位置服务关闭然后再在设备上重新打开。发生这种情况时,FusedLocationProviderClient.getLastLocation()
总是 returns null。我应该如何处理这种情况?我需要以某种方式重新初始化 FusedLocationProviderClient
吗?
我从documentation that when location services are turned off, the last cached location is flushed. This tells me that I need to force a location request so the cache gets refreshed. However, I'm unsure of how to do this. I've also followed this Medium article了解到FusedLocationProviderClient
的设置,但它所做的只是检查定位结果是否为空,当它为空时不做任何处理。
我正在用 Kotlin 编写应用程序。以下是我如何初始化 FusedLocationProviderClient
并在我的片段中获取用户的当前位置:
class LocationFragment : Fragment() {
private lateinit var mFusedLocationProviderClient: FusedLocationProiderClient
override fun onCreate(savedInstanceState: Bundle?) {
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
// Initialize button on-click callback.
}
private fun getCurrentLocation() {
// Check that the location service is enabled.
// Check coarse and fine location permissions.
mFusedLocationProviderClient.lastLocation.addOnSuccessListener {
if (it != null) { // Always false if location services are toggled.
print(it.latitude, it.longitude)
}
}
}
}
我没有对 FusedLocationProviderClient 做很多事情,但据我了解(文档似乎也同意),使用 lastLocation
(getLastLocation() for Java 人)不会'不是真的出去 "fetch" 当前设备位置,而只是 return 设备获取的最后一个位置。通常,设备上的任何数量的服务都在请求位置,因此缓存中始终有一个相当准确的值供 lastLocation
使用。但是,如果您关闭并重新打开定位服务,然后立即调用 lastLocation
,您很可能会收到 null
returned。另请注意 lastLocation
状态的文档:
It is particularly well suited for applications that do not require an accurate location
并且来自 getLocationAvailability()
调用的文档:
Note it's always possible for getLastLocation() to return null even when this method returns true (e.g. location settings were disabled between calls).
这些也证实了该方法实际上并不进行位置查找,而只是 return 从缓存中进行最近的查找,当您切换服务时 off/on,缓存是空的。
如果您需要确保获取设备的当前位置并确保其相当准确,您可能需要使用 requestLocationUpdates()
让位置客户端实际计算出设备的当前位置和 return 它在你提供的回调中,然后在你完成后删除回调。
自从我与位置提供商合作以来已经有一段时间了,但我认为你可以做这样的事情,假设你只需要一个位置:
private val locationRequest: LocationRequest by lazy {
LocationRequest.create().apply {
interval = (LOCATION_UPDATE_INTERVAL_SECONDS * 1000).toLong()
fastestInterval = (LOCATION_FAST_INTERVAL_SECONDS * 1000).toLong()
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
smallestDisplacement =
MINIMUM_DISPLACEMENT_METERS
}
}
private fun isValidLocation(location: Location): Boolean {
/* TODO: validate that the location meets all of your
requirements for accuracy, etc, and return the
appropriate true/false value
*/
return true // or false, for example if the location accuracy is not good enough.
}
private val locationCallback = object: LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
Log.d(TAG, "Location Received: $locationResult")
val location = locationResult.lastLocation
if (isValidLocation(location)) {
Log.d(TAG, "Valid Location dectected: $location")
// we have a valid location, so stop receiving further location updates.
mFusedLocationClient.removeLocationUpdates(this)
//TODO: we have a valid location! Use it as you wish to update the
// view, or emit it via a LiveData, etc.
} else {
// nothing to do, wait for more results.
Log.d(TAG, "Location received was not valid: $location")
}
}
}
private fun watchLocation() {
// Check Location Permissions
// Check Google Play Services Version
// Check Location Settings
// If all three are good, then:
mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
}
上面的代码片段设置了一个 LocationCallback
,它在收到位置时被调用。它检查位置(通过 isValidLocation
方法),如果它有效,它会从提供者中删除自己,这样您就不会获得额外的位置更新。在它自己删除的那一行 (mFusedLocationClient.removeLocationUpdates(this)
) 之后,您可以对 location
对象做任何您需要做的工作。如果收到的位置无效,它会在收到位置时继续收到额外的回调,直到您收到一个有效的回调。要开始这一切,只需调用 watchLocation()
在我的应用程序中,我有一个使用 FusedLocationProviderClient 获取用户当前位置的按钮。这可以正常工作,直到位置服务关闭然后再在设备上重新打开。发生这种情况时,FusedLocationProviderClient.getLastLocation()
总是 returns null。我应该如何处理这种情况?我需要以某种方式重新初始化 FusedLocationProviderClient
吗?
我从documentation that when location services are turned off, the last cached location is flushed. This tells me that I need to force a location request so the cache gets refreshed. However, I'm unsure of how to do this. I've also followed this Medium article了解到FusedLocationProviderClient
的设置,但它所做的只是检查定位结果是否为空,当它为空时不做任何处理。
我正在用 Kotlin 编写应用程序。以下是我如何初始化 FusedLocationProviderClient
并在我的片段中获取用户的当前位置:
class LocationFragment : Fragment() {
private lateinit var mFusedLocationProviderClient: FusedLocationProiderClient
override fun onCreate(savedInstanceState: Bundle?) {
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
// Initialize button on-click callback.
}
private fun getCurrentLocation() {
// Check that the location service is enabled.
// Check coarse and fine location permissions.
mFusedLocationProviderClient.lastLocation.addOnSuccessListener {
if (it != null) { // Always false if location services are toggled.
print(it.latitude, it.longitude)
}
}
}
}
我没有对 FusedLocationProviderClient 做很多事情,但据我了解(文档似乎也同意),使用 lastLocation
(getLastLocation() for Java 人)不会'不是真的出去 "fetch" 当前设备位置,而只是 return 设备获取的最后一个位置。通常,设备上的任何数量的服务都在请求位置,因此缓存中始终有一个相当准确的值供 lastLocation
使用。但是,如果您关闭并重新打开定位服务,然后立即调用 lastLocation
,您很可能会收到 null
returned。另请注意 lastLocation
状态的文档:
It is particularly well suited for applications that do not require an accurate location
并且来自 getLocationAvailability()
调用的文档:
Note it's always possible for getLastLocation() to return null even when this method returns true (e.g. location settings were disabled between calls).
这些也证实了该方法实际上并不进行位置查找,而只是 return 从缓存中进行最近的查找,当您切换服务时 off/on,缓存是空的。
如果您需要确保获取设备的当前位置并确保其相当准确,您可能需要使用 requestLocationUpdates()
让位置客户端实际计算出设备的当前位置和 return 它在你提供的回调中,然后在你完成后删除回调。
自从我与位置提供商合作以来已经有一段时间了,但我认为你可以做这样的事情,假设你只需要一个位置:
private val locationRequest: LocationRequest by lazy {
LocationRequest.create().apply {
interval = (LOCATION_UPDATE_INTERVAL_SECONDS * 1000).toLong()
fastestInterval = (LOCATION_FAST_INTERVAL_SECONDS * 1000).toLong()
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
smallestDisplacement =
MINIMUM_DISPLACEMENT_METERS
}
}
private fun isValidLocation(location: Location): Boolean {
/* TODO: validate that the location meets all of your
requirements for accuracy, etc, and return the
appropriate true/false value
*/
return true // or false, for example if the location accuracy is not good enough.
}
private val locationCallback = object: LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
Log.d(TAG, "Location Received: $locationResult")
val location = locationResult.lastLocation
if (isValidLocation(location)) {
Log.d(TAG, "Valid Location dectected: $location")
// we have a valid location, so stop receiving further location updates.
mFusedLocationClient.removeLocationUpdates(this)
//TODO: we have a valid location! Use it as you wish to update the
// view, or emit it via a LiveData, etc.
} else {
// nothing to do, wait for more results.
Log.d(TAG, "Location received was not valid: $location")
}
}
}
private fun watchLocation() {
// Check Location Permissions
// Check Google Play Services Version
// Check Location Settings
// If all three are good, then:
mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
}
上面的代码片段设置了一个 LocationCallback
,它在收到位置时被调用。它检查位置(通过 isValidLocation
方法),如果它有效,它会从提供者中删除自己,这样您就不会获得额外的位置更新。在它自己删除的那一行 (mFusedLocationClient.removeLocationUpdates(this)
) 之后,您可以对 location
对象做任何您需要做的工作。如果收到的位置无效,它会在收到位置时继续收到额外的回调,直到您收到一个有效的回调。要开始这一切,只需调用 watchLocation()